libmongocrypt-1.8.4/000077500000000000000000000000001454530651600144255ustar00rootroot00000000000000libmongocrypt-1.8.4/.clang-format000066400000000000000000000017351454530651600170060ustar00rootroot00000000000000--- Language: Cpp # (Options are sorted alphabetically) AlignAfterOpenBracket: Align AlignEscapedNewlines: Right AlignOperands: AlignAfterOperator AllowAllArgumentsOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: Empty AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false BinPackArguments: false BinPackParameters: false BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Attach ColumnLimit: 120 ContinuationIndentWidth: 4 IndentCaseLabels: false IndentWidth: 4 InsertBraces: true KeepEmptyLinesAtTheStartOfBlocks: false PointerAlignment: Right QualifierAlignment: Custom QualifierOrder: ["static", "inline", "const", "volatile", "type", "restrict"] SeparateDefinitionBlocks: Always SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpacesInLineCommentPrefix: Minimum: 1 Maximum: -1 UseTab: Never libmongocrypt-1.8.4/.clang-tidy000066400000000000000000000005161454530651600164630ustar00rootroot00000000000000# Older clang-tidy gives a warning for an uninitialized va_args, # even on the test case that they assert should not produce that warning: # https://github.com/llvm-mirror/clang/blob/59207d134acb8a1c6cb9974c32c1c04bd31f8f7b/test/Analysis/valist-uninitialized.c#L30 Checks: "-clang-analyzer-valist.Uninitialized" WarningsAsErrors: "*" libmongocrypt-1.8.4/.earthlyignore000066400000000000000000000000461454530651600173020ustar00rootroot00000000000000cmake-build/ cmake-build-deb/ _build/ libmongocrypt-1.8.4/.evergreen/000077500000000000000000000000001454530651600164655ustar00rootroot00000000000000libmongocrypt-1.8.4/.evergreen/build_all.sh000077500000000000000000000104571454530651600207620ustar00rootroot00000000000000#!/bin/bash # Compiles libmongocrypt dependencies and targets. # # Set extra cflags for libmongocrypt variables by setting LIBMONGOCRYPT_EXTRA_CFLAGS. # echo "Begin compile process" . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" # We may need some more C++ flags _cxxflags="" : "${CONFIGURE_ONLY:=}" : "${LIBMONGOCRYPT_BUILD_TYPE:=RelWithDebInfo}" if [ "$OS_NAME" = "windows" ]; then # Enable exception handling for MSVC _cxxflags="-EHsc" if is_false WINDOWS_32BIT && is_false USE_NINJA; then # These options are only needed for VS CMake generators to force it to # generate a 64-bit build. Default is 32-bit. Ninja inherits settings # from the build environment variables. ADDITIONAL_CMAKE_FLAGS="-Thost=x64 -A x64" fi fi # Have CTest print test failure info to stderr export CTEST_OUTPUT_ON_FAILURE=1 if [ "$PPA_BUILD_ONLY" ]; then # Clean-up from previous build iteration rm -rf -- "$LIBMONGOCRYPT_DIR"/cmake-build* "$MONGOCRYPT_INSTALL_PREFIX" ADDITIONAL_CMAKE_FLAGS="$ADDITIONAL_CMAKE_FLAGS -DENABLE_BUILD_FOR_PPA=ON" fi if [ "$MACOS_UNIVERSAL" = "ON" ]; then ADDITIONAL_CMAKE_FLAGS="$ADDITIONAL_CMAKE_FLAGS -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64'" fi for suffix in "dll" "dylib" "so"; do cand="$(abspath "$LIBMONGOCRYPT_DIR/../mongocrypt_v1.$suffix")" if test -f "$cand"; then ADDITIONAL_CMAKE_FLAGS="$ADDITIONAL_CMAKE_FLAGS -DMONGOCRYPT_TESTING_CRYPT_SHARED_FILE=$cand" fi done ADDITIONAL_CMAKE_FLAGS="$ADDITIONAL_CMAKE_FLAGS -DENABLE_MORE_WARNINGS_AS_ERRORS=ON" build_dir="$LIBMONGOCRYPT_DIR/cmake-build" common_cmake_args=( $ADDITIONAL_CMAKE_FLAGS $LIBMONGOCRYPT_EXTRA_CMAKE_FLAGS -DCMAKE_C_FLAGS="$LIBMONGOCRYPT_EXTRA_CFLAGS" -DCMAKE_CXX_FLAGS="$LIBMONGOCRYPT_EXTRA_CFLAGS $_cxxflags" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE="$LIBMONGOCRYPT_BUILD_TYPE" -H"$LIBMONGOCRYPT_DIR" -B"$build_dir" ) if is_true USE_NINJA; then export NINJA_EXE : "${NINJA_EXE:="$build_dir/ninja$EXE_SUFFIX"}" common_cmake_args+=( -GNinja -DCMAKE_MAKE_PROGRAM="$NINJA_EXE" ) bash "$EVG_DIR/ensure-ninja.sh" fi # Build and install libmongocrypt. run_cmake \ -DCMAKE_INSTALL_PREFIX="$MONGOCRYPT_INSTALL_PREFIX" \ "${common_cmake_args[@]}" if [ "$CONFIGURE_ONLY" ]; then echo "Only running cmake"; exit 0; fi echo "Installing libmongocrypt" run_cmake --build "$build_dir" --target install --config "$LIBMONGOCRYPT_BUILD_TYPE" run_cmake --build "$build_dir" --target test-mongocrypt --config "$LIBMONGOCRYPT_BUILD_TYPE" run_cmake --build "$build_dir" --target test_kms_request --config "$LIBMONGOCRYPT_BUILD_TYPE" run_chdir "$build_dir" run_ctest -C "$LIBMONGOCRYPT_BUILD_TYPE" # MONGOCRYPT-372, ensure macOS universal builds contain both x86_64 and arm64 architectures. if [ "$MACOS_UNIVERSAL" = "ON" ]; then echo "Checking if libmongocrypt.dylib contains both x86_64 and arm64 architectures..." ARCHS=$(lipo -archs $MONGOCRYPT_INSTALL_PREFIX/lib/libmongocrypt.dylib) if [[ "$ARCHS" == *"x86_64"* && "$ARCHS" == *"arm64"* ]]; then echo "Checking if libmongocrypt.dylib contains both x86_64 and arm64 architectures... OK" else echo "Checking if libmongocrypt.dylib contains both x86_64 and arm64 architectures... ERROR. Got: $ARCHS" exit 1 fi fi if [ "$PPA_BUILD_ONLY" ]; then echo "Only building/installing for PPA"; exit 0; fi if "${DEFAULT_BUILD_ONLY:-false}"; then echo "Skipping nocrypto+sharedbson builds" exit 0 fi # Build and install libmongocrypt with no native crypto. run_cmake \ -DDISABLE_NATIVE_CRYPTO=ON \ -DCMAKE_INSTALL_PREFIX="$MONGOCRYPT_INSTALL_PREFIX/nocrypto" \ "${common_cmake_args[@]}" run_cmake --build "$build_dir" --target install --config "$LIBMONGOCRYPT_BUILD_TYPE" run_cmake --build "$build_dir" --target test-mongocrypt --config "$LIBMONGOCRYPT_BUILD_TYPE" run_chdir "$build_dir" run_ctest -C "$LIBMONGOCRYPT_BUILD_TYPE" # Build and install libmongocrypt without statically linking libbson run_cmake \ -UDISABLE_NATIVE_CRYPTO \ -DUSE_SHARED_LIBBSON=ON \ -DCMAKE_INSTALL_PREFIX="$MONGOCRYPT_INSTALL_PREFIX/sharedbson" \ "${common_cmake_args[@]}" run_cmake --build "$build_dir" --target install --config "$LIBMONGOCRYPT_BUILD_TYPE" run_chdir "$build_dir" run_ctest -C "$LIBMONGOCRYPT_BUILD_TYPE" libmongocrypt-1.8.4/.evergreen/clang-tidy.sh000077500000000000000000000006001454530651600210530ustar00rootroot00000000000000#!/bin/bash # Run after running "CONFIGURE_ONLY=ON compile.sh" to run the clang-tidy # static analyzer. # . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" CLANG_TIDY=/opt/mongodbtoolchain/v3/bin/clang-tidy $CLANG_TIDY --version python "$LIBMONGOCRYPT_DIR/etc/list-compile-files.py" \ "$LIBMONGOCRYPT_DIR/cmake-build/" \ | xargs $CLANG_TIDY -p "$LIBMONGOCRYPT_DIR/cmake-build/" libmongocrypt-1.8.4/.evergreen/cmake.sh000066400000000000000000000002121454530651600200740ustar00rootroot00000000000000#!/usr/bin/env bash . "$(dirname "${BASH_SOURCE[0]}")/init.sh" . "$EVG_DIR/ensure-cmake.sh" # Execute CMake: command "$CMAKE_EXE" "$@" libmongocrypt-1.8.4/.evergreen/compile.sh000077500000000000000000000005341454530651600204560ustar00rootroot00000000000000#!/bin/bash # Downloads and prepares the C driver source, then compiles libmongocrypt's # dependencies and targets. # # NOTE: This script is not meant to be invoked for Evergreen builds. It is a # convenience script for users of libmongocrypt . "$(dirname "${BASH_SOURCE[0]}")/init.sh" bash "$EVG_DIR/setup-env.sh" bash "$EVG_DIR/build_all.sh" libmongocrypt-1.8.4/.evergreen/compile_cs.sh000066400000000000000000000017151454530651600211420ustar00rootroot00000000000000#!/bin/bash # Compiles libmongocrypt dependencies and targets. # # Set extra cflags for libmongocrypt variables by setting LIBMONGOCRYPT_EXTRA_CFLAGS. # . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" echo "Begin compile process" evergreen_root="$(pwd)" if [ "$OS_NAME" = "windows" ]; then # Make sure libbson.dll is in the path on Windows export PATH="${MONGOCRYPT_INSTALL_PREFIX}/mongo-c-driver/bin:$PATH" for var in TMP TEMP NUGET_PACKAGES NUGET_HTTP_CACHE_PATH APPDATA; do export $var=z:\\data\\tmp; done # Make dotnet happy over ssh export DOTNET_CLI_HOME=$(cygpath -w "${evergreen_root}/dotnet_home") else export PATH=$PATH:/usr/share/dotnet fi dotnet_tool=$(which dotnet) "$dotnet_tool" build -c Release "$LIBMONGOCRYPT_DIR/cmake-build/bindings/cs/cs.sln" "$dotnet_tool" test -c Release "$LIBMONGOCRYPT_DIR/cmake-build/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj" -- RunConfiguration.TargetPlatform=x64 libmongocrypt-1.8.4/.evergreen/config.yml000077500000000000000000001341241454530651600204650ustar00rootroot00000000000000# Welcome. Evergreen configuration can be time consuming to modify and test. # So each script has a header comment describing how to run it locally. # # Some environment variables are hidden in the evergreen project config. # View this in Evergreen => Projects => libmongocrypt. # functions: "cleanup environment": - command: shell.exec params: script: | set -o verbose rm -rf ~/.aws ~/.notary_env.sh exit 0 "fetch source": - command: git.get_project params: {directory: libmongocrypt} - command: shell.exec params: shell: bash script: |- set -o errexit . libmongocrypt/.evergreen/init.sh bash "$EVG_DIR/print-env-info.sh" # determine if we have a release tag present on HEAD head_tag=$(run_chdir libmongocrypt/ git tag -l --points-at HEAD '[0-9].*' || true) use_tag="" if test "${is_patch}" != "true"; then echo "Setting tag_upload_location to '$head_tag'" use_tag="$head_tag" fi echo "tag_upload_location: '$use_tag'" > tag_expansion.yml - command: expansions.update params: ignore_missing_file: true file: tag_expansion.yml "tar and upload libmongocrypt libraries": - command: archive.targz_pack params: target: libmongocrypt.tar.gz source_dir: install/libmongocrypt include: [./**] - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: '${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt.tar.gz' bucket: mciuploads permissions: public-read local_file: 'libmongocrypt.tar.gz' content_type: '${content_type|application/x-gzip}' - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: '${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix_copy}/libmongocrypt.tar.gz' bucket: mciuploads permissions: public-read local_file: 'libmongocrypt.tar.gz' content_type: '${content_type|application/x-gzip}' "build and test": - command: "shell.exec" params: shell: bash script: |- . libmongocrypt/.evergreen/init.sh export LSAN_OPTIONS="suppressions=$LIBMONGOCRYPT_DIR/.lsan-suppressions" export VS_VERSION=${vs_version|} export VS_TARGET_ARCH=${vs_target_arch|amd64} export USE_NINJA=ON env ${compile_env|} \ bash "$EVG_DIR/env-run.sh" \ bash "$EVG_DIR/build_all.sh" env ${compile_env|} \ bash "$EVG_DIR/env-run.sh" \ bash "$EVG_DIR/linker-tests.sh" env ${compile_env|} \ bash "$EVG_DIR/env-run.sh" \ bash "$EVG_DIR/pkgconfig-tests.sh" "create packages and repos": - command: "shell.exec" params: shell: bash script: | env "WORKDIR=${workdir}" \ "PYTHON=${python|}" \ "HAS_PACKAGES=${has_packages|false}" \ "PACKAGER_DISTRO=${packager_distro}" \ "PACKAGER_ARCH=${packager_arch}" \ ${compile_env|} \ bash libmongocrypt/.evergreen/create-packages-and-repos.sh - command: archive.targz_pack params: target: libmongocrypt-distro-packages.tar.gz source_dir: libmongocrypt/repo include: [./**] - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: '${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt-distro-packages.tar.gz' bucket: mciuploads permissions: public-read local_file: 'libmongocrypt-distro-packages.tar.gz' content_type: '${content_type|application/x-gzip}' optional: true "run clang-tidy": - command: "shell.exec" params: script: |- if test "$OS_NAME" != "windows"; then export USE_NINJA=ON; fi env ${compile_env|} CONFIGURE_ONLY=ON ${clang_env|CC=clang CXX=clang++} \ bash libmongocrypt/.evergreen/build_all.sh ./libmongocrypt/.evergreen/clang-tidy.sh "test java": - command: "shell.exec" params: script: |- export GIT_REVISION="${revision}" cd ./libmongocrypt/bindings/java/mongocrypt && ${test_env|} ./.evergreen/test.sh "test python": - command: "shell.exec" params: script: |- export MONGOCRYPT_DIR="$(pwd)/all/${variant_name}" cd ./libmongocrypt/bindings/python && ${test_env|} ./.evergreen/test.sh "build and test node": - command: "subprocess.exec" params: binary: bash working_dir: "./libmongocrypt/bindings/node" args: - "./.evergreen/test.sh" env: PROJECT_DIRECTORY: ${project_directory} NODE_GITHUB_TOKEN: ${node_github_token} DISTRO_ID: ${distro_id} BUILD_VARIANT: ${build_variant} NODE_NVM_USE_VERSION: ${nvm_use_version|18} "build and test node no peer dependencies": - command: "subprocess.exec" params: binary: bash working_dir: "./libmongocrypt/bindings/node" args: - "./.evergreen/test.sh" env: PROJECT_DIRECTORY: ${project_directory} NODE_GITHUB_TOKEN: ${node_github_token} DISTRO_ID: ${distro_id} BUILD_VARIANT: ${build_variant} OMIT_PEER_DEPS: "true" NODE_NVM_USE_VERSION: ${nvm_use_version|18} "attach node xunit results": - command: attach.xunit_results params: file: ./libmongocrypt/bindings/node/xunit.xml "publish java": - command: git.get_project params: {directory: libmongocrypt} - command: shell.exec params: script: |- set -o errexit chmod u+x libmongocrypt/.evergreen/*.sh ./libmongocrypt/.evergreen/print-env-info.sh - command: shell.exec params: script: |- if [ "${is_patch}" = "true" ]; then echo "Patch build detected, skipping" exit 0 fi export PROJECT_DIRECTORY=${project_directory} export NEXUS_USERNAME=${nexus_username} export NEXUS_PASSWORD=${nexus_password} export SIGNING_PASSWORD=${signing_password} export SIGNING_KEY_ID=${signing_keyId} export RING_FILE_GPG_BASE64=${ring_file_gpg_base64} cd ./libmongocrypt/bindings/java/mongocrypt && ${test_env|} ./.evergreen/publish.sh "download tarball": - command: s3.get params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: '${project}/${variant_name}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt.tar.gz' bucket: mciuploads extract_to: all/${variant_name} "download distro package tarball": - command: s3.get params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: '${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt-distro-packages.tar.gz' bucket: mciuploads extract_to: libmongocrypt/repo "setup packaging credentials": - command: shell.exec params: silent: true shell: bash script: | set -o errexit if [ "${is_patch}" = "true" ]; then exit 0 fi # set AWS credentials rm -rf ~/.aws mkdir -p ~/.aws cat <> ~/.aws/config [default] region = us-east-1 EOF cat <> ~/.aws/credentials [default] aws_access_key_id = ${repo_aws_key} aws_secret_access_key = ${repo_aws_secret} EOF # set notary credentials rm -f ~/.notary_env.sh cat < ~/.notary_env.sh export NOTARY_TOKEN=${repo_notary_secret} export NOTARY_KEY_NAME=${repo_notary_name} export BARQUE_USERNAME=${barque_username} export BARQUE_API_KEY=${barque_api_key} EOF "build csharp and test": - command: "shell.exec" params: shell: bash script: |- . libmongocrypt/.evergreen/init.sh if test "$OS_NAME" != "windows"; then export USE_NINJA=ON; fi env ${compile_env|} DEFAULT_BUILD_ONLY=true \ bash ./libmongocrypt/.evergreen/build_all.sh env ${compile_env|} bash ./libmongocrypt/.evergreen/compile_cs.sh "build python release macos": - command: shell.exec params: script: | set -ex cd ./libmongocrypt/bindings/python PYTHON=${PYTHON} MACOS_TARGET=${MACOS_TARGET} ./release.sh "build python release": - command: shell.exec params: script: | set -ex cd ./libmongocrypt/bindings/python ./release.sh "test python release": - command: shell.exec params: script: | set -ex cd ./libmongocrypt/bindings/python ROOT=$(pwd) for file in ./dist/*.whl; do ${PYTHON} -m pip uninstall -y pymongocrypt ${PYTHON} -m pip install --upgrade --user $file cd $HOME ${PYTHON} -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" cd $ROOT done "upload python release": - command: archive.targz_pack params: target: "release-files.tgz" source_dir: "libmongocrypt/bindings/python/dist" include: - "*" - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: release-files.tgz remote_file: '${project}/python-release/${branch_name}/${libmongocrypt_s3_suffix}/${task_id}-${execution}-release-files.tar.gz' bucket: mciuploads permissions: public-read content_type: ${content_type|application/gzip} display_name: Release Python files "download and merge python releases": - command: shell.exec params: silent: true shell: "bash" script: | # set AWS credentials rm -rf ~/.aws mkdir -p ~/.aws cat <> ~/.aws/config [default] region = us-east-1 EOF cat <> ~/.aws/credentials [default] aws_access_key_id = ${aws_key} aws_secret_access_key = ${aws_secret} EOF - command: shell.exec params: shell: "bash" script: | set -o xtrace # Download all the release files. aws s3 cp --recursive s3://mciuploads/${project}/python-release/${branch_name}/${libmongocrypt_s3_suffix}/ release/ # Combine releases into one directory. ls -la release/ mkdir releases for REL in release/*; do tar zxvf $REL -C releases/ done - command: archive.targz_pack params: target: "release-files-all.tgz" source_dir: "releases/" include: - "*" - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: release-files-all.tgz remote_file: '${project}/python-release/${branch_name}/${libmongocrypt_s3_suffix}/${task_id}-${execution}-release-files-all.tar.gz' bucket: mciuploads permissions: public-read content_type: ${content_type|application/gzip} display_name: Release Python files all earthly: - command: shell.exec params: shell: bash working_dir: ${working_dir|libmongocrypt} script: bash ${workdir}/libmongocrypt/.evergreen/earthly.sh ${args} tasks: - name: build-and-test-and-upload commands: - func: "fetch source" - func: "build and test" - func: "tar and upload libmongocrypt libraries" - func: "create packages and repos" - name: clang-tidy commands: - func: "fetch source" - func: "run clang-tidy" - name: build-and-test-shared-bson commands: - func: "fetch source" - func: "build and test" vars: compile_env: ${compile_env|} LIBMONGOCRYPT_EXTRA_CMAKE_FLAGS="-DUSE_SHARED_LIBBSON=ON" - name: build-and-test-asan commands: - func: "fetch source" - func: "build and test" vars: compile_env: >- ${compile_env|} LIBMONGOCRYPT_EXTRA_CFLAGS="-fsanitize=address -pthread" # Add detect_odr_violation=0 to ASAN_OPTIONS to ignore odr-violation in IntelDFP symbol: __dpml_bid_globals_table ASAN_OPTIONS="detect_leaks=1 detect_odr_violation=0" - name: build-and-test-asan-mac commands: - func: "fetch source" - func: "build and test" vars: compile_env: ${compile_env|} LIBMONGOCRYPT_EXTRA_CFLAGS="-fsanitize=address" - name: build-and-test-asan-s390x commands: - func: "fetch source" - func: "build and test" vars: compile_env: ${compile_env|} LIBMONGOCRYPT_EXTRA_CFLAGS="-fsanitize=address" - name: test-java depends_on: - variant: ubuntu2004-64 name: upload-java commands: - func: "fetch source" - func: "test java" vars: { variant_name: "${build_variant}" } - name: test-python depends_on: - build-and-test-and-upload commands: - func: "fetch source" - func: "download tarball" vars: { variant_name: "${build_variant}" } - func: "test python" vars: { variant_name: "${build_variant}" } - name: test-python-windows depends_on: # Depends on the windows-64-vs2017-test upload. - variant: windows-test name: build-and-test-and-upload commands: - func: "fetch source" - func: "download tarball" vars: { variant_name: windows-test } - func: "test python" vars: { variant_name: windows-test } - name: "release-python-macos-1100" tags: ["release_python_tag"] run_on: macos-1100 commands: - func: "fetch source" - func: "build python release macos" - func: "test python release" vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 } - func: "upload python release" - name: "release-python-macos-1014" tags: ["release_python_tag"] run_on: macos-1014 commands: - func: "fetch source" - func: "build python release macos" vars: PYTHON: /Library/Frameworks/Python.framework/Versions/3.7/bin/python3 MACOS_TARGET: macos_x86_64 - func: "test python release" vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.7/bin/python3 } - func: "upload python release" - name: "release-python-linux" tags: ["release_python_tag"] run_on: ubuntu2004-small exec_timeout_secs: 216000 # 60 minutes (manylinux task is slow). commands: - func: "fetch source" - func: "build python release" - func: "test python release" vars: { PYTHON: /opt/python/3.7/bin/python3 } - func: "upload python release" - name: "release-python-windows" tags: ["release_python_tag"] run_on: windows-64-vsMulti-small commands: - func: "fetch source" - func: "build python release" - func: "test python release" vars: { PYTHON: C:/python/Python37/python.exe } - func: "upload python release" - name: "release-python-combine" tags: ["release_python_tag"] run_on: ubuntu2004-small depends_on: - name: "*" variant: ".release_python_tag" patch_optional: true commands: - func: "download and merge python releases" - name: build-and-test-csharp commands: - func: "fetch source" - func: "build csharp and test" vars: test_env: PROJECT_DIRECTORY=${project_directory} - name: build-and-test-node commands: - func: "fetch source" - func: "build and test node" - func: "attach node xunit results" - name: build-and-test-node-no-peer-dependencies commands: - func: "fetch source" - func: "build and test node no peer dependencies" - func: "attach node xunit results" # Note: keep this disabled unless you want master to force-push - name: build-and-test-node-force-publish commands: - func: "fetch source" - func: "build and test node" - func: "attach node xunit results" - name: publish-java depends_on: - variant: ubuntu2004-64 name: upload-java commands: - func: "publish java" - name: upload-java depends_on: - variant: rhel-62-64-bit name: build-and-test-and-upload - variant: rhel72-zseries-test name: build-and-test-and-upload - variant: rhel-71-ppc64el name: build-and-test-and-upload - variant: ubuntu1604-arm64 name: build-and-test-and-upload - variant: windows-test name: build-and-test-and-upload - variant: macos_x86_64 name: build-and-test-and-upload - variant: macos name: build-and-test-and-upload commands: - command: shell.exec params: script: mkdir all - func: "download tarball" vars: { variant_name: "rhel-62-64-bit" } - func: "download tarball" vars: { variant_name: "rhel72-zseries-test" } - func: "download tarball" vars: { variant_name: "rhel-71-ppc64el" } - func: "download tarball" vars: { variant_name: "ubuntu1604-arm64" } - func: "download tarball" vars: { variant_name: "windows-test" } - func: "download tarball" vars: { variant_name: "macos_x86_64" } - func: "download tarball" vars: { variant_name: "macos" } - command: archive.targz_pack params: target: libmongocrypt-java.tar.gz source_dir: all include: [./**] - command: shell.exec params: script: |- set -o errexit if [ -n "${tag_upload_location}" ]; then # the "fetch source" step detected a release tag on HEAD, so we # prepare a local file for upload to a location based on the tag cp -a libmongocrypt-java.tar.gz libmongocrypt-java-${tag_upload_location}.tar.gz fi - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: 'libmongocrypt/java/${revision}/libmongocrypt-java.tar.gz' bucket: mciuploads permissions: public-read local_file: 'libmongocrypt-java.tar.gz' content_type: '${content_type|application/x-gzip}' - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: 'libmongocrypt/java/${tag_upload_location}/libmongocrypt-java.tar.gz' bucket: mciuploads permissions: public-read optional: true display_name: 'libmongocrypt-java-${tag_upload_location}.tar.gz' local_file: 'libmongocrypt-java-${tag_upload_location}.tar.gz' content_type: '${content_type|application/x-gzip}' - name: upload-all depends_on: - variant: ubuntu1604 name: build-and-test-and-upload - variant: macos_x86_64 name: build-and-test-and-upload - variant: rhel72-zseries-test name: build-and-test-and-upload - variant: windows-test name: build-and-test-and-upload - variant: linux-64-amazon-ami name: build-and-test-and-upload - variant: amazon2 name: build-and-test-and-upload - variant: amazon2-arm64 name: build-and-test-and-upload - variant: amazon2023 name: build-and-test-and-upload - variant: amazon2023-arm64 name: build-and-test-and-upload - variant: debian11 name: build-and-test-and-upload - variant: debian10 name: build-and-test-and-upload - variant: debian92 name: build-and-test-and-upload - variant: rhel-62-64-bit name: build-and-test-and-upload - variant: rhel-70-64-bit name: build-and-test-and-upload - variant: rhel-71-ppc64el name: build-and-test-and-upload - variant: rhel-80-64-bit name: build-and-test-and-upload - variant: rhel-81-ppc64el name: build-and-test-and-upload - variant: rhel-82-arm64 name: build-and-test-and-upload - variant: rhel-83-zseries name: build-and-test-and-upload - variant: rhel-91-64-bit name: build-and-test-and-upload - variant: rhel-91-arm64 name: build-and-test-and-upload - variant: suse12-64 name: build-and-test-and-upload - variant: suse15-64 name: build-and-test-and-upload - variant: ubuntu1604-arm64 name: build-and-test-and-upload - variant: ubuntu1804-64 name: build-and-test-and-upload - variant: ubuntu1804-arm64 name: build-and-test-and-upload - variant: ubuntu2004-64 name: build-and-test-and-upload - variant: ubuntu2004-arm64 name: build-and-test-and-upload - variant: ubuntu2204-64 name: build-and-test-and-upload - variant: ubuntu2204-arm64 name: build-and-test-and-upload - variant: macos name: build-and-test-and-upload commands: - func: "fetch source" - command: shell.exec params: script: mkdir all - func: "download tarball" vars: { variant_name: ubuntu1604 } - func: "download tarball" vars: { variant_name: "macos" } - func: "download tarball" vars: { variant_name: "rhel72-zseries-test" } - func: "download tarball" vars: { variant_name: "windows-test" } - func: "download tarball" vars: { variant_name: "linux-64-amazon-ami" } - func: "download tarball" vars: { variant_name: "amazon2" } - func: "download tarball" vars: { variant_name: "amazon2-arm64" } - func: "download tarball" vars: { variant_name: "amazon2023" } - func: "download tarball" vars: { variant_name: "amazon2023-arm64" } - func: "download tarball" vars: { variant_name: "debian11" } - func: "download tarball" vars: { variant_name: "debian10" } - func: "download tarball" vars: { variant_name: "debian92" } - func: "download tarball" vars: { variant_name: "rhel-62-64-bit" } - func: "download tarball" vars: { variant_name: "rhel-70-64-bit" } - func: "download tarball" vars: { variant_name: "rhel-71-ppc64el" } - func: "download tarball" vars: { variant_name: "rhel-80-64-bit" } - func: "download tarball" vars: { variant_name: "rhel-81-ppc64el" } - func: "download tarball" vars: { variant_name: "rhel-82-arm64" } - func: "download tarball" vars: { variant_name: "rhel-83-zseries" } - func: "download tarball" vars: { variant_name: "rhel-91-64-bit" } - func: "download tarball" vars: { variant_name: "rhel-91-arm64" } - func: "download tarball" vars: { variant_name: "suse12-64" } - func: "download tarball" vars: { variant_name: "suse15-64" } - func: "download tarball" vars: { variant_name: "ubuntu1604-arm64" } - func: "download tarball" vars: { variant_name: "ubuntu1804-64" } - func: "download tarball" vars: { variant_name: "ubuntu1804-arm64" } - func: "download tarball" vars: { variant_name: "ubuntu2004-64" } - func: "download tarball" vars: { variant_name: "ubuntu2004-arm64" } - func: "download tarball" vars: { variant_name: "ubuntu2204-64" } - func: "download tarball" vars: { variant_name: "ubuntu2204-arm64" } - func: "download tarball" vars: { variant_name: "macos" } - command: archive.targz_pack params: target: libmongocrypt-all.tar.gz source_dir: all include: [./**] - command: shell.exec params: script: |- set -o errexit if [ -n "${tag_upload_location}" ]; then # the "fetch source" step detected a release tag on HEAD, so we # prepare a local file for upload to a location based on the tag cp -a libmongocrypt-all.tar.gz libmongocrypt-all-${tag_upload_location}.tar.gz fi - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: 'libmongocrypt/all/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt-all.tar.gz' bucket: mciuploads permissions: public-read local_file: 'libmongocrypt-all.tar.gz' content_type: '${content_type|application/x-gzip}' - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: 'libmongocrypt/all/${branch_name}/${libmongocrypt_s3_suffix_copy}/libmongocrypt-all.tar.gz' bucket: mciuploads permissions: public-read local_file: 'libmongocrypt-all.tar.gz' content_type: '${content_type|application/x-gzip}' - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: 'libmongocrypt/all/${tag_upload_location}/libmongocrypt-all.tar.gz' bucket: mciuploads permissions: public-read optional: true display_name: 'libmongocrypt-all-${tag_upload_location}.tar.gz' local_file: 'libmongocrypt-all-${tag_upload_location}.tar.gz' content_type: '${content_type|application/x-gzip}' - name: publish-packages depends_on: build-and-test-and-upload commands: - func: "fetch source" - func: "download distro package tarball" - func: "setup packaging credentials" - command: shell.exec params: working_dir: libmongocrypt shell: bash script: |- [ -f ~/.notary_env.sh ] && . ~/.notary_env.sh set -o xtrace set -o errexit set -o verbose if [ "${is_patch}" = "true" ]; then echo "patch build, skipping packaging publication" exit 0 fi if [ "${has_packages|}" != "true" ] ; then echo "'has_packages' is not 'true', skipping package publication" exit 0 fi # Some venv-activate scripts are not nounset-clean set +u # Need requests and poster for notary-client.py python -m virtualenv venv cd venv . bin/activate ./bin/pip install requests ./bin/pip install poster ./bin/pip install pycrypto cd .. # Get the current version of libmongocrypt. pkg_version="$(python etc/calc_release_version.py)" CURATOR_RELEASE=${curator_release|"e0b5f66fc89ec0acddcd40ea5f447a8300ded2b9"} curl -L -O http://boxes.10gen.com/build/curator/curator-dist-rhel70-$CURATOR_RELEASE.tar.gz tar -zxvf curator-dist-rhel70-$CURATOR_RELEASE.tar.gz ./curator version ./curator repo submit --config etc/repo_config.yaml --distro ${packager_distro} --edition org --version $pkg_version --arch ${packager_arch} --service https://barque.corp.mongodb.com/ --packages https://mciuploads.s3.amazonaws.com/${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt-distro-packages.tar.gz - name: windows-upload-check depends_on: build-and-test-and-upload commands: - func: "fetch source" - command: shell.exec params: working_dir: libmongocrypt script: |- set -o xtrace set -o errexit CMAKE=/cygdrive/c/cmake/bin/cmake mongocrypt_version="$(python etc/calc_release_version.py)" case "$mongocrypt_version" in *+*) # Not a tagged release. echo "{}" > ./.evergreen/windows-upload.json ;; *-*) # This is an unstable release, like 1.1.0-beta1 or 1.0.1-rc0 cp ./.evergreen/windows-upload-doit-unstable.json ./.evergreen/windows-upload.json ;; *) # It is a tagged release. cp ./.evergreen/windows-upload-doit.json ./.evergreen/windows-upload.json ;; esac - command: generate.tasks params: files: - libmongocrypt/.evergreen/windows-upload.json - name: windows-upload commands: - command: s3.get params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: '${project}/windows-test/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt.tar.gz' bucket: mciuploads extract_to: libmongocrypt_download - command: shell.exec params: script: |- set -o xtrace set -o errexit # Move just the mongocrypt files needed into the final upload mkdir libmongocrypt_upload mkdir libmongocrypt_upload/bin mkdir libmongocrypt_upload/include mv libmongocrypt_download/bin/mongocrypt.dll libmongocrypt_upload/bin/mongocrypt.dll mv libmongocrypt_download/include/mongocrypt libmongocrypt_upload/include - command: archive.targz_pack params: target: libmongocrypt_upload.tar.gz source_dir: libmongocrypt_upload include: [./**] - command: s3.put params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: 'libmongocrypt/windows/latest_release/libmongocrypt${upload_suffix}.tar.gz' bucket: mciuploads permissions: public-read local_file: 'libmongocrypt_upload.tar.gz' content_type: '${content_type|application/x-gzip}' - name: debian-package-build run_on: &deb-package-build-run_on - ubuntu2004 - ubuntu2004-small tags: [packaging] commands: - func: "fetch source" - command: shell.exec type: test params: working_dir: "libmongocrypt" shell: bash script: |- set -o errexit set -o xtrace bash .evergreen/debian_package_build.sh --is-patch=${is_patch} - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: deb.tar.gz remote_file: libmongocrypt/${branch_name}/${revision}/${version_id}/${build_id}/${execution}/debian-packages.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/x-gzip} display_name: "deb.tar.gz" - name: debian-package-build-i386 run_on: *deb-package-build-run_on tags: [packaging] commands: - func: "fetch source" - command: shell.exec type: test params: working_dir: "libmongocrypt" shell: bash script: |- set -o errexit set -o xtrace bash .evergreen/debian_package_build.sh --arch=i386 --is-patch=${is_patch} - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: deb.tar.gz remote_file: libmongocrypt/${branch_name}/${revision}/${version_id}/${build_id}/${execution}/debian-packages-i386.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/x-gzip} display_name: "deb.tar.gz" - name: rpm-package-build tags: [packaging] run_on: &docker-distros # * The RHEL76-docker distro runs an old and unsupported version of Docker. # * (We requires the --mount parameter) - ubuntu2004-small - ubuntu2004 - ubuntu1804 - ubuntu1804-medium - debian10 - debian11 - amazon2 commands: - func: fetch source - func: earthly vars: args: +rpm-runtime-test - name: check-format tags: [misc] run_on: *docker-distros commands: - func: fetch source - func: earthly vars: args: +check-format pre: # Update the evergreen expansion to dynamically set the ${libmongocrypt_s3_suffix} and ${libmongocrypt_s3_suffix_copy} expansions. - command: "shell.exec" params: # Uploads are prefixed with ${project}/${build_variant}/${branch_name|all} script: |- if [ "${is_patch}" = "true" ]; then # patch build. REMOTE_SUFFIX="${revision}/${version_id}" REMOTE_SUFFIX_COPY="latest/${version_id}" elif [ "${branch_name}" = "master" ]; then # waterfall build. REMOTE_SUFFIX="${revision}" REMOTE_SUFFIX_COPY="latest" else # waterfall build, not on master branch. REMOTE_SUFFIX="${revision}" REMOTE_SUFFIX_COPY="latest-${branch_name}" fi PROJECT_DIRECTORY="$(pwd)" echo "libmongocrypt_s3_suffix: $REMOTE_SUFFIX" echo "libmongocrypt_s3_suffix_copy: $REMOTE_SUFFIX_COPY" echo "project_directory: $PROJECT_DIRECTORY" cat < expansion.yml libmongocrypt_s3_suffix: "$REMOTE_SUFFIX" libmongocrypt_s3_suffix_copy: "$REMOTE_SUFFIX_COPY" project_directory: "$PROJECT_DIRECTORY" EOT - command: expansions.update params: file: expansion.yml - func: "cleanup environment" post: - func: "cleanup environment" # NOTE: When adding a new variant, update the "upload-all" task. buildvariants: - name: ubuntu1604 display_name: "Ubuntu 16.04 64-bit" run_on: ubuntu1604-test expansions: has_packages: true packager_distro: ubuntu1604 packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - ubuntu2004-small - name: macos_x86_64 display_name: "macOS (x86_64) 10.14" run_on: macos-1014 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan-mac - build-and-test-node - build-and-test-node-no-peer-dependencies - build-and-test-csharp - test-python - test-java - name: rhel72-zseries-test display_name: "RHEL 7.2 on zSeries" run_on: rhel72-zseries-test expansions: has_packages: true packager_distro: rhel72 packager_arch: s390x tasks: - build-and-test-and-upload - build-and-test-shared-bson - test-java - name: publish-packages distros: - rhel70-small - name: rhel83-zseries # rhel83-zseries has a new enough g++ to build the C++ tests. # rhel72-zseries-test does not build the C++ tests. display_name: "RHEL 8.3 on zSeries" run_on: rhel83-zseries-small tasks: - build-and-test-and-upload - name: windows-vs2015-compile display_name: "Windows VS 2015 compile" run_on: windows-64-vs2015-test expansions: vs_version: "14" vs_target_arch: amd64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - name: windows-test display_name: "Windows 2016" run_on: windows-64-vs2017-test expansions: vs_version: "15" vs_target_arch: amd64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-csharp - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - windows-upload-check - name: windows-test-python display_name: "Windows Python" run_on: windows-64-vsMulti-small tasks: - test-python-windows - name: python-release display_name: Python Release batchtime: 20160 # 14 days tags: ["release_python_tag"] tasks: - ".release_python_tag" - name: linux-64-amazon-ami display_name: "Amazon Linux" run_on: amazon1-2018-test expansions: has_packages: true packager_distro: amazon packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - rhel70-small - name: amazon2 display_name: "Amazon Linux 2" run_on: amazon2-test expansions: has_packages: true packager_distro: amazon2 packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - rhel70-small - name: amazon2-arm64 display_name: "Amazon Linux 2 (arm64)" run_on: amazon2-arm64 expansions: has_packages: true packager_distro: amazon2 packager_arch: aarch64 node_lts_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - name: publish-packages distros: - rhel70-small - name: amazon2023 display_name: "Amazon Linux 2023" run_on: amazon2023.0-small expansions: has_packages: true packager_distro: amazon2023 packager_arch: x86_64 node_lts_version: 16 tasks: - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: amazon2023-arm64 display_name: "Amazon Linux 2023 (arm64)" run_on: amazon2023-arm64-small expansions: has_packages: true packager_distro: amazon2023 packager_arch: aarch64 node_lts_version: 16 tasks: - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: debian11 display_name: "Debian 11.0" run_on: debian11-large expansions: has_packages: true packager_distro: debian11 packager_arch: x86_64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies # - test-java - Fails with `JAVA_HOME is set to an invalid directory`. Unskip once MONGOCRYPT-593 is resolved. - name: publish-packages distros: - ubuntu2004-small - name: debian10 display_name: "Debian 10.0" run_on: debian10-test expansions: has_packages: true packager_distro: debian10 packager_arch: x86_64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - ubuntu2004-small - name: debian92 display_name: "Debian 9.2" run_on: debian92-test expansions: has_packages: true packager_distro: debian92 packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - ubuntu2004-small - name: rhel-62-64-bit display_name: "RHEL 6.2 64-bit" run_on: rhel62-small expansions: has_packages: true packager_distro: rhel62 packager_arch: x86_64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - test-java - name: publish-packages distros: - rhel70-small - name: rhel-70-64-bit display_name: "RHEL 7.0 64-bit" run_on: rhel70-small expansions: has_packages: true packager_distro: rhel70 packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-node - build-and-test-node-no-peer-dependencies - test-python - test-java - name: publish-packages distros: - rhel70-small - name: rhel-71-ppc64el display_name: "RHEL 7.1 ppc64el" run_on: rhel71-power8-test expansions: has_packages: true packager_distro: rhel71 packager_arch: ppc64le tasks: - build-and-test-and-upload - build-and-test-shared-bson - test-java - name: publish-packages distros: - rhel70-small - name: rhel-80-64-bit display_name: "RHEL 8.0 64-bit" run_on: rhel80-test expansions: has_packages: true packager_distro: rhel80 packager_arch: x86_64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - rhel70-small - name: rhel-82-arm64 display_name: "RHEL 8.2 arm64" run_on: rhel82-arm64-small expansions: has_packages: true packager_distro: rhel82 packager_arch: aarch64 tasks: - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: rhel-81-ppc64el display_name: "RHEL 8.1 ppc64el" run_on: rhel81-power8-small expansions: has_packages: true packager_distro: rhel81 packager_arch: ppc64le tasks: - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: rhel-83-zseries display_name: "RHEL 8.3 zSeries" run_on: rhel83-zseries-small expansions: has_packages: true packager_distro: rhel83 packager_arch: s390x tasks: - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: rhel-91-64-bit display_name: "RHEL 9.1 64-bit" run_on: rhel91-small expansions: has_packages: true packager_distro: rhel91 packager_arch: x86_64 tasks: - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: rhel-91-arm64 display_name: "RHEL 9.1 arm64" run_on: rhel91-arm64-small expansions: has_packages: true packager_distro: rhel91 packager_arch: aarch64 tasks: - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: suse12-64 display_name: "SLES 12 64-bit" run_on: suse12-sp5-small expansions: has_packages: true packager_distro: suse12 packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - name: publish-packages distros: - rhel70-small - name: suse15-64 display_name: "SLES 15 64-bit" run_on: suse15-test expansions: has_packages: true packager_distro: suse15 packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - rhel70-small - name: ubuntu1604-arm64 display_name: "Ubuntu 16.04 arm64" run_on: ubuntu1604-arm64-large expansions: has_packages: true packager_distro: ubuntu1604 packager_arch: arm64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - ubuntu2004-small - name: ubuntu1804-64 display_name: "Ubuntu 18.04 64-bit" run_on: ubuntu1804-test expansions: has_packages: true packager_distro: ubuntu1804 packager_arch: x86_64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - build-and-test-csharp - test-java - name: publish-packages distros: - ubuntu2004-small - name: ubuntu1804-64-clang7 # ubuntu1804-64-clang7 is used to test Ubuntu 18.04 with Clang 7.0.1. # This is a supported configuration built by the MongoDB Server. # The MongoDB Server vendors libmongocrypt. Refer: MONGOCRYPT-501. display_name: "Ubuntu 18.04 64-bit clang7" run_on: ubuntu1804-test expansions: compile_env: LIBMONGOCRYPT_EXTRA_CMAKE_FLAGS="-DCMAKE_C_COMPILER=/opt/mongodbtoolchain/v3/bin/clang -DCMAKE_CXX_COMPILER=/opt/mongodbtoolchain/v3/bin/clang++" tasks: - build-and-test-and-upload - name: ubuntu1804-arm64 display_name: "Ubuntu 18.04 arm64" run_on: ubuntu1804-arm64-build expansions: has_packages: true packager_distro: ubuntu1804 packager_arch: arm64 nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - ubuntu2004-small - name: ubuntu2004-64 display_name: "Ubuntu 20.04 64-bit" run_on: ubuntu2004-small expansions: has_packages: true packager_distro: ubuntu2004 packager_arch: x86_64 tasks: - clang-tidy - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies - build-and-test-csharp - test-java - upload-java - publish-packages - name: ubuntu2004-arm64 display_name: "Ubuntu 20.04 arm64" run_on: ubuntu2004-arm64-small expansions: has_packages: true packager_distro: ubuntu2004 packager_arch: arm64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies # - test-java - Fails with `JAVA_HOME is set to an invalid directory`. Unskip once MONGOCRYPT-593 is resolved. - name: publish-packages distros: - ubuntu2004-small - name: ubuntu2204-64 display_name: "Ubuntu 22.04 64-bit" run_on: ubuntu2204-small expansions: has_packages: true packager_distro: ubuntu2204 packager_arch: x86_64 clang_env: CC=clang-12 CXX=clang++-12 tasks: - clang-tidy - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies # see https://jira.mongodb.org/browse/MONGOCRYPT-515 #- build-and-test-csharp - test-java - upload-java - name: publish-packages distros: - ubuntu2004-small - name: ubuntu2204-arm64 display_name: "Ubuntu 22.04 arm64" run_on: ubuntu2204-arm64-small expansions: has_packages: true packager_distro: ubuntu2204 packager_arch: arm64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - build-and-test-node - build-and-test-node-no-peer-dependencies # - test-java - Fails with `JAVA_HOME is set to an invalid directory`. Unskip once MONGOCRYPT-593 is resolved. - name: publish-packages distros: - ubuntu2004-small - name: publish display_name: "Publish" run_on: ubuntu1804-test tasks: - name: "upload-java" - name: "upload-all" - name: java-release display_name: Java Release run_on: ubuntu2004-small tasks: - "publish-java" - name: packaging display_name: "Linux Distro Packaging" tasks: [.packaging] - name: misc display_name: Miscellaneous tasks: [.misc] - name: macos display_name: macOS m1 (Apple LLVM) run_on: macos-1100-arm64 expansions: compile_env: MACOS_UNIVERSAL=ON CMAKE=/opt/homebrew/bin/cmake tasks: - build-and-test-and-upload - build-and-test-node - build-and-test-node-no-peer-dependencies - test-python - test-java - name: windows-vs2017-32bit # Test Windows 32 bit builds for PHPC. PHPC builds libmongocrypt from source. See MONGOCRYPT-391. display_name: "Windows VS 2017 32-bit compile" run_on: windows-64-vs2017-small expansions: compile_env: WINDOWS_32BIT=ON vs_version: "15" vs_target_arch: x86 tasks: - build-and-test-and-upload libmongocrypt-1.8.4/.evergreen/create-packages-and-repos.sh000066400000000000000000000035551454530651600237360ustar00rootroot00000000000000#!/bin/bash . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" # Generate an error if these are unset: : "$PACKAGER_DISTRO" "$PACKAGER_ARCH" if ! "${HAS_PACKAGES:-false}"; then echo "'HAS_PACKAGES' is not 'true': Skipping package build" exit 0 fi if test -d "$WORKDIR/venv"; then if test "$OS" = "Windows_NT"; then # Need to quote the path on Windows to preserve the separator. . "$WORKDIR/venv/Scripts/activate" 2> /tmp/activate_error.log else . "$WORKDIR/venv/bin/activate" 2> /tmp/activate_error.log fi if test $? -ne 0; then echo "Failed to activate virtualenv: $(cat /tmp/activate_error.log)" fi python=python else python="${PYTHON:-/opt/mongodbtoolchain/v3/bin/python3}" fi export PYTHONPATH : "${PYTHONPATH:=}" if test "$OS" = "Windows_NT"; then PYTHONPATH="$PYTHONPATH;$(cygpath -w "$WORKDIR/src")" else PYTHONPATH="$PYTHONPATH:$WORKDIR/src" fi # Get current version of libmongocrypt. pushd "$LIBMONGOCRYPT_DIR" mongocrypt_version="$("$python" etc/calc_release_version.py)" popd PPA_BUILD_ONLY=1 "$LIBMONGOCRYPT_DIR/.evergreen/build_all.sh" pkg_version=$mongocrypt_version tar -zcv -C install \ --transform="s|^libmongocrypt/|libmongocrypt-$pkg_version/|" \ --exclude=nocrypto \ --exclude=sharedbson \ -f "libmongocrypt-$pkg_version.tar.gz" \ libmongocrypt pushd "$LIBMONGOCRYPT_DIR/etc/" # The files from libmongocrypt/debian/ are the official maintainer scripts, # but libmongocrypt/etc/debian/ contains a few custom scripts that are # meant to support the packager.py workflow. This step "fills in" around # those custom scripts. cp -nr ../debian/* debian/ command "$python" ./packager.py \ --prefix "$LIBMONGOCRYPT_DIR" \ --distros "$PACKAGER_DISTRO" \ --tarball "$LIBMONGOCRYPT_DIR-$pkg_version.tar.gz" \ --library-version "$pkg_version" \ --metadata-gitspec HEAD \ --arches "$PACKAGER_ARCH" popd libmongocrypt-1.8.4/.evergreen/ctest.sh000066400000000000000000000002121454530651600201360ustar00rootroot00000000000000#!/usr/bin/env bash . "$(dirname "${BASH_SOURCE[0]}")/init.sh" . "$EVG_DIR/ensure-cmake.sh" # Execute CTest: command "$CTEST_EXE" "$@" libmongocrypt-1.8.4/.evergreen/debian_package_build.sh000066400000000000000000000052121454530651600230750ustar00rootroot00000000000000#!/bin/env bash # # Test libmongocrypt's Debian packaging scripts. # # Supported options: # --is-patch={true,false} # If "true", this is an Evergreen patch build. (Default 'false') # --arch= # If specified, sets the "--arch" option for debootstrap. set -euxo pipefail IS_PATCH=false _dbs_args=() for arg in "$@"; do case $arg in --arch=*) a="${arg#*=}" _dbs_args+=(--arch "$a") ;; --is-patch=*) IS_PATCH="${arg#*=}" ;; *) echo "Unknown argument '$arg'" exit 1 ;; esac done on_exit () { if [ -e ./unstable-chroot/debootstrap/debootstrap.log ]; then echo "Dumping debootstrap.log" cat ./unstable-chroot/debootstrap/debootstrap.log fi } trap on_exit EXIT if [ "${IS_PATCH}" = "true" ]; then git diff HEAD -- . ':!debian' > ../upstream.patch git diff HEAD -- debian > ../debian.patch git clean -fdx git reset --hard HEAD if [ -s ../upstream.patch ]; then [ -d debian/patches ] || mkdir debian/patches mv ../upstream.patch debian/patches/ echo upstream.patch >> debian/patches/series git add debian/patches/* git commit -m 'Evergreen patch build - upstream changes' git log -n1 -p fi if [ -s ../debian.patch ]; then git apply --index ../debian.patch git commit -m 'Evergreen patch build - Debian packaging changes' git log -n1 -p fi fi cd .. _dbs_args+=(unstable) git clone https://salsa.debian.org/installer-team/debootstrap.git debootstrap.git export DEBOOTSTRAP_DIR=`pwd`/debootstrap.git sudo -E ./debootstrap.git/debootstrap "${_dbs_args[@]}" ./unstable-chroot/ http://cdn-aws.deb.debian.org/debian cp -a libmongocrypt ./unstable-chroot/tmp/ sudo chroot ./unstable-chroot /bin/bash -c "(set -o xtrace && \ apt-get install -y build-essential git-buildpackage fakeroot debhelper cmake curl ca-certificates libssl-dev pkg-config libbson-dev libintelrdfpmath-dev && \ chown -R root:root /tmp/libmongocrypt && \ cd /tmp/libmongocrypt && \ git clean -fdx && \ git reset --hard HEAD && \ python3 etc/calc_release_version.py > VERSION_CURRENT && \ git add --force VERSION_CURRENT && \ git commit VERSION_CURRENT -m 'Set current version' && \ LANG=C /bin/bash ./debian/build_snapshot.sh && \ debc ../*.changes && \ dpkg -i ../*.deb && \ /usr/bin/gcc -I/usr/include/mongocrypt -I/usr/include/libbson-1.0 -o example-state-machine test/example-state-machine.c -lmongocrypt -lbson-1.0 )" [ -e ./unstable-chroot/tmp/libmongocrypt/example-state-machine ] || (echo "Example 'example-state-machine' was not built!" ; exit 1) (cd ./unstable-chroot/tmp/ ; tar zcvf ../../deb.tar.gz *.dsc *.orig.tar.gz *.debian.tar.xz *.build *.deb) libmongocrypt-1.8.4/.evergreen/earthly.sh000077500000000000000000000016421454530651600204770ustar00rootroot00000000000000#!/usr/bin/bash . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" set -euo pipefail : "${EARTHLY_VERSION:=0.6.30}" # Calc the arch of the executable we want arch="$(uname -m)" case "$arch" in x86_64) arch=amd64 ;; aarch64|arm64) arch=arm64 ;; *) echo "Unknown architecture: $arch" 1>&1 exit 99 ;; esac # The location where the Earthly executable will live cache_dir="$USER_CACHES_DIR/earthly-sh/$EARTHLY_VERSION" mkdir -p "$cache_dir" exe_filename="earthly-$OS_NAME-$arch$EXE_SUFFIX" exe_path="$cache_dir/$exe_filename" # Download if it isn't already present if ! test -f "$exe_path"; then echo "Downloading $exe_filename $EARTHLY_VERSION" url="https://github.com/earthly/earthly/releases/download/v$EARTHLY_VERSION/$exe_filename" curl --retry 5 -LsS --max-time 120 --fail "$url" --output "$exe_path" fi chmod a+x "$exe_path" "$exe_path" "$@" libmongocrypt-1.8.4/.evergreen/ensure-cmake.sh000066400000000000000000000135351454530651600214070ustar00rootroot00000000000000#!/usr/bin/env bash ## This script ensures the presence of a CMake executable matching a specific ## version. After sourcing this script, a variable "$CMAKE_EXE" will refer to ## the CMake executable to be used. ## ## The following environment variables are defined by this script, and can also ## be defined by a caller to control this script. All variables are optional ## and have defaults for this file: ## ## - CMAKE_VERSION: The CMake version to obtain ## - CMAKE_CACHES_ROOT: The directory where all obtained CMake versions will be cached ## - CMAKE_CACHE_DIR: The directory where we will expect/write the CMake that we obtain. ## - CMAKE_EXE: A CMake executable to use. If set, no obtaining logic will execute. ## - CTEST_EXE: The CTest executable for the CMAKE_EXE. . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" # The version that we will attempt to obtain: : "${CMAKE_VERSION:=3.25.1}" # Root of all cached versions : "${CMAKE_CACHES_ROOT:="$BUILD_CACHE_DIR/cmake"}" # Cache directory for this particular version: : "${CMAKE_CACHE_DIR:="$CMAKE_CACHES_ROOT/$CMAKE_VERSION"}" # The executable that we want to use (can be overriden by an invoker) _prev_cmake_exe=${CMAKE_EXE-} : "${CMAKE_EXE:="$CMAKE_CACHE_DIR/bin/cmake$EXE_SUFFIX"}" : "${CTEST_EXE:="${CMAKE_EXE%cmake*}ctest"}" # Downloads a prebuilt CMake binary: _download_cmake() { # Directory where we will extract to (temporary) declare extract_dir="$CMAKE_CACHE_DIR.tmp" debug "Temporary extraction dir: [$extract_dir]" test -d "$extract_dir" && rm -r -- "$extract_dir" mkdir -p "$extract_dir" # The path for the downloaded archive (may be zip or tgz) declare archive="$CMAKE_CACHE_DIR.archive" debug "Temporary archive file: [$archive]" # The --strip-components for tar (different on macos) declare strip_components=1 # By default we will use tar. (Windows uses unzip) declare use=tar # Common prefix: declare url_base="https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION" # Select the URL and options: case "$OS_NAME" in linux) declare arch arch="$(uname -m)" url="$url_base/cmake-$CMAKE_VERSION-Linux-$arch.tar.gz" ;; macos) url="$url_base/cmake-$CMAKE_VERSION-macos10.10-universal.tar.gz" # We're pulling out the app bundle contents, so we need to skip more intermediate directories strip_components=3 ;; windows) url="$url_base/cmake-$CMAKE_VERSION-windows-x86_64.zip" # On windows we use 'unzip' use=unzip ;; *) fail "Unrecognized platform $(uname -a)" ;; esac # Download the file: log "Downloading [$url] ..." curl --retry 5 -LsS --max-time 120 --fail --output "$archive" "$url" # Extract the downloaded archive: log "Extracting to [$CMAKE_CACHE_DIR] ..." case $use in tar) debug "Expand with 'tar' into [$extract_dir]" tar -x -f "$archive" -C "$extract_dir" --strip-components=$strip_components ;; unzip) # Unzip has no --strip-components, so we need to move the files ourself debug "Expand with 'unzip' into [$extract_dir.1]" unzip -o -qq "$archive" -d "$extract_dir.1" mv -- "$extract_dir.1"/cmake-$CMAKE_VERSION-*/* "$extract_dir" ;; esac # Check that we got the file: declare test_file="$extract_dir/bin/cmake$EXE_SUFFIX" debug "Checking for file [$test_file]" test -f "$test_file" || fail "Download+extract did not produce the expected file [$test_file]??" # Put the temporary extracted dir into its final location: test -d "$CMAKE_CACHE_DIR" && rm -r -- "$CMAKE_CACHE_DIR" mv -- "$extract_dir" "$CMAKE_CACHE_DIR" } # Download and build CMake from source: _build_cmake() { declare src_dir="$CMAKE_CACHE_DIR.src" debug "Building in directory [$src_dir]" test -d "$src_dir" && rm -r -- "$src_dir" mkdir -p "$src_dir" declare src_tgz="$CMAKE_CACHE_DIR.tgz" declare url="https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION.tar.gz" log "Downloading source archive [$url] ..." curl --retry 5 -LsS --max-time 120 --fail --output "$src_tgz" "$url" log "Extracting [$src_tgz] into [$src_dir] ..." tar -x -f "$src_tgz" -C "$src_dir" --strip-components 1 log "Bootstrapping CMake build ..." run_chdir "$src_dir" bash "./bootstrap" --prefix="$CMAKE_CACHE_DIR" --parallel=10 log "Building CMake" make -C "$src_dir" log "Installing result ..." make -C "$src_dir" install test -f "$CMAKE_EXE" || fail "CMake build did not produce the expected file [$CMAKE_EXE]??" log "Successfully built CMake $CMAKE_VERSION into [$CMAKE_CACHE_DIR]" } # Ensures that we have a CMake executable matching our cache settings: _ensure_cmake() { # If we already have the executable, we don't need to get one debug "Expecting CMake executable [$CMAKE_EXE]" debug "Expecting CTest executable [$CTEST_EXE]" if test -f "$CMAKE_EXE"; then debug "CMake executable [$CMAKE_EXE] is already present. Nothing to to." return 0 fi declare arch arch="$(uname -m)" if test -f /etc/alpine-release; then arch="$arch-musl" fi # Otherwise we need to obtain it log "Obtaining CMake $CMAKE_VERSION for $OS_NAME-$arch" case "$OS_NAME-$arch" in linux-x86_64|linux-aarch64|windows-*|macos-*) # Download a pre-built _download_cmake ;; linux-*) # Build our own _build_cmake ;; *) fail "We don't know how to automatically obtain CMake $CMAKE_VERSION for this platform" ;; esac } if test -z "$_prev_cmake_exe"; then _ensure_cmake elif ! test -f "$_prev_cmake_exe"; then log "ensure-cmake.sh: CMAKE_EXE is set and refers to a non-existent file [$_prev_cmake_exe]" else debug "Using existing CMAKE_EXE [$_prev_cmake_exe]" fi libmongocrypt-1.8.4/.evergreen/ensure-ninja.sh000066400000000000000000000061231454530651600214210ustar00rootroot00000000000000#!/usr/bin/env bash . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" test -n "${NINJA_EXE-}" || fail "Set \$NINJA_EXE to point to a filepath where we will write the Ninja executable" # 1.8.2 is chosen as the last pre-built version that supports RHEL 6 : "${NINJA_VERSION:=1.8.2}" _ninja_cache_dir="${BUILD_CACHE_DIR}/ninja-${NINJA_VERSION}" _download_ninja() { declare extract_dir="$_ninja_cache_dir/ninja.d" declare expect_exe="$extract_dir/ninja$EXE_SUFFIX" if test -f "$expect_exe"; then debug "Using downloaded Ninja executable [$expect_exe]" mkdir -p -- "$(dirname "$NINJA_EXE")" cp -- "$expect_exe" "$NINJA_EXE" return 0 fi declare url_base="https://github.com/ninja-build/ninja/releases/download/v$NINJA_VERSION" declare fname case "$OS_NAME" in linux) fname="ninja-linux.zip" ;; macos) fname="ninja-mac.zip" ;; windows) fname="ninja-win.zip" ;; esac declare url="$url_base/$fname" log "Downloading Ninja Zip [$url]" mkdir -p "$BUILD_CACHE_DIR" declare archive=$_ninja_cache_dir/ninja.bin mkdir -p -- "$_ninja_cache_dir" curl --retry 5 -LsS --max-time 120 --fail --output "$archive" "$url" unzip -qq -o "$archive" "ninja$EXE_SUFFIX" -d "$extract_dir" test -f "$expect_exe" || fail "Unzip did not generate expected executable [$expect_exe]" # Recurisve invocation will find the extracted executable and copy it _download_ninja } _build_ninja() { declare build_out_dir="$_ninja_cache_dir/built" mkdir -p "$build_out_dir" declare expect_exe="$build_out_dir/ninja$EXE_SUFFIX" if test -f "$expect_exe"; then debug "Using built Ninja executable [$expect_exe]" mkdir -p -- "$(dirname "$NINJA_EXE")" cp -- "$expect_exe" "$NINJA_EXE" return 0 fi declare extract_dir="$_ninja_cache_dir/ninja-src" declare src_tgz="$_ninja_cache_dir/ninja-src.tgz" declare url="https://github.com/ninja-build/ninja/archive/refs/tags/v$NINJA_VERSION.tar.gz" if test -d "$extract_dir"; then rm -r -- "$extract_dir"; fi mkdir -p -- "$extract_dir" log "Downloading Ninja source [$url]" mkdir -p -- "$_ninja_cache_dir" curl --retry 5 -LsS --max-time 120 --fail --output "$src_tgz" "$url" tar -x -f "$src_tgz" -C "$extract_dir" --strip-components=1 log "Building Ninja from source" run_chdir "$build_out_dir" run_python "$extract_dir/configure.py" --bootstrap test -f "$expect_exe" || fail "Bootstrap did not generate the expected executable [$expect_exe]" # Recursive invocation will find our build and copy it _build_ninja } _ensure_ninja() { declare arch arch="$(uname -m)" if test -f /etc/alpine-release; then arch="$arch-musl" fi case "$OS_NAME-$arch" in linux-x86_64|windows-x86_64|macos-*) # Download a pre-built version _download_ninja ;; linux-*|windows-*) _build_ninja ;; *) fail "We don't know how to automatically obtain a Ninja executable for this platform" ;; esac } _ensure_ninja libmongocrypt-1.8.4/.evergreen/env-run.sh000066400000000000000000000013051454530651600204120ustar00rootroot00000000000000#!/usr/bin/env bash # Executes a subcommand using a VS environment if one is requested, otherwise # just executes the command with no modified environment set -eu if test -n "${VS_VERSION-}"; then here="$(dirname "${BASH_SOURCE[0]}")" # Set CC and CXX to force CMake to use cl.exe even if GCC/Clang is visible on PATH env _run_argv="$*" \ CC=cl \ CXX=cl \ powershell -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Unrestricted \ -Command "$here/vs-env-run.ps1" \ -Version "$VS_VERSION*" \ -TargetArch "${VS_TARGET_ARCH-amd64}" \ -Command "{ & Invoke-Expression \$env:_run_argv }" else command "$@" fi libmongocrypt-1.8.4/.evergreen/init.sh000066400000000000000000000166361454530651600200000ustar00rootroot00000000000000#!/bin/bash # Initial variables and helper functions for the libmongocrypt build ## Variables set by this file: # EVG_DIR = The path to the directory containing this script file # LIBMONGOCRYPT_DIR = The path to the libmongocrypt source directory # OS_NAME = One of 'windows', 'linux', 'macos', or 'unknown' ## (All of the above directory paths are native absolute paths) ## This script defines the following commands: # * abspath # Convert a given path into an absolute path. Relative paths are # resolved relative to the working directory. # # * have_command # Return zero if is the name of a command that can be executed, # returns non-zero otherwise. # # * run_chdir [args ...] # Run the given command with a working directory given by # # * log # Print to stderr # # * fail # Print to stderr and return non-zero # # * native_path # On MinGW/Cygwin/MSYS, convert the given Cygwin path to a Windows-native # path. NOTE: the MinGW runtime will almost always automatically convert # filepaths automatically when passed to non-MinGW programs, so this # utility is not usually needed. set -o errexit set -o pipefail set -o nounset # Inhibit msys path conversion export MSYS2_ARG_CONV_EXCL="*" if test "${TRACE:-0}" != "0"; then set -o xtrace fi # Write a message to stderr function log() { echo "${@}" 1>&2 return 0 } function debug() { if test "${DEBUG:-0}" != "0"; then log "${@}" fi } # Print a message and return non-zero function fail() { log "${@}" return 1 } # Determine whether we can execute the given name as a command function have_command() { test "$#" -eq 1 || fail "have_command expects a single argument" if type "${1}" > /dev/null 2>&1; then return 0 fi return 1 } # Run a command in a different directory: # * run_chdir [command ...] function run_chdir() { test "$#" -gt 1 || fail "run_chdir expects at least two arguments" local _dir="$1" shift pushd "$_dir" > /dev/null debug "Run in directory [$_dir]:" "$@" "$@" local _rc=$? popd > /dev/null return $_rc } # Given a path string, convert it to an absolute path with no redundant components or directory separators function abspath() { test "$#" -eq 1 || fail "abspath expects a single argument" local ret local arg="$1" debug "Resolve path [$arg]" # The parent path: local _parent _parent="$(dirname "$arg")" # The filename part: local _fname _fname="$(basename "$arg")" # There are four cases to consider from dirname: if test "$_parent" = "."; then # The parent is '.' as in './foo' # Replace the leading '.' with the working directory _parent="$PWD" elif test "$_parent" = ".."; then # The parent is '..' as in '../foo' # Replace a leading '..' with the parent of the working directory _parent="$(dirname "$PWD")" elif test "$arg" = "$_parent"; then # The parent is itself, as in '/' # A root directory is its own parent according to 'dirname' printf %s "$arg" return 0 else # The parent is some other path, like 'foo' in 'foo/bar' # Resolve the parent path _parent="$(set +x; DEBUG=0 abspath "$_parent")" fi # At this point $_parent is an absolute path if test "$_fname" = ".."; then # Strip one component ret="$(dirname "$_parent")" elif test "$_fname" = "."; then # Drop a '.' at the end of a path ret="$_parent" else # Join the result ret="$_parent/$_fname" fi # Remove duplicate dir separators while [[ "$ret" =~ "//" ]]; do ret="${ret//\/\///}" done debug "Resolved to: [$arg] -> [$ret]" printf %s "$ret" } # Get the platform name: One of 'windows', 'macos', 'linux', or 'unknown' function os_name() { have_command uname || fail "No 'uname' executable found" debug "Uname is [$(uname -a)]" local _uname _uname="$(uname -a | tr '[:upper:]' '[:lower:]')" local _os_name="unknown" if [[ "$_uname" =~ .*cygwin|windows|mingw|msys.* ]] || (have_command cmd.exe && ! [[ $_uname =~ .*wsl.* ]]); then # We are running on Windows, and not within a WSL environment _os_name="windows" elif [[ $_uname =~ darwin.* ]]; then _os_name='macos' elif [[ $_uname =~ linux.* ]]; then _os_name='linux' fi printf %s "$_os_name" } # Ensure the given path is in a native format (converts cygwin paths to Windows-local paths) function native_path() { test "$#" -eq 1 || fail "native_path expects one argument" if test "$OS_NAME" = "windows"; then have_command cygpath || fail "No 'cygpath' command is available, but we require it to normalize file paths." debug "Convert path [$1]" local r r="$(cygpath -w "$1")" debug "Convert to [$r]" printf %s "$r" else printf %s "$1" fi } # Join the given arguments with the given joiner string. Writes to stdout # Usage: join_str [argv [...]] function join_str() { local joiner first joiner="$1" first="${2-}" if shift 2; then # Print each element. Do a string-replace of the beginning of each # subsequent string with the joiner. printf "%s" "$first" "${@/#/$joiner}" fi } OS_NAME="$(os_name)" _init_sh_this_file="$(abspath "${BASH_SOURCE[0]}")" _init_sh_evg_dir="$(dirname "${_init_sh_this_file}")" # Get the EVG dir as a native absolute path. All other path vars are derived from # this one, and will therefore remain as native paths EVG_DIR="$(native_path "${_init_sh_evg_dir}")" LIBMONGOCRYPT_DIR="$(dirname "${EVG_DIR}")" is_true() { declare var="$1" declare val="${!var-}" # Default is '' empty case "$val" in 1|true|TRUE|True|yes|YES|Yes|on|ON|On) return 0;; 0|false|FALSE|False|no|NO|No|off|OFF|Off|"") return 1;; *) log "Unknown 'boolean' value for \$$var: '$val'" return 2;; esac } is_false() { ! is_true "$@" } # Executes CMake via the cache-managing script run_cmake() { command bash "$EVG_DIR/cmake.sh" "$@" } # Executes CTest via the cache-managing script run_ctest() { command bash "$EVG_DIR/ctest.sh" "$@" } run_python() { pys=( py python3.14 python3.13 python3.12 python3.11 python3.10 python3.9 python3.8 python3.7 python3.6 python3 python ) for cand in "${pys[@]}"; do if have_command "$cand" && "$cand" -c ""; then "$cand" "$@" return $? fi done } EXE_SUFFIX="" if test "$OS_NAME" = "windows"; then EXE_SUFFIX=".exe" fi if test "${USER_CACHES_DIR:=${XDG_CACHE_HOME:-}}" = ""; then case "$OS_NAME" in linux) USER_CACHES_DIR=$HOME/.cache ;; macos) USER_CACHES_DIR=$HOME/Library/Caches ;; windows) USER_CACHES_DIR=${LOCALAPPDATA:-$USERPROFILE/.cache} ;; *) log "Using ~/.cache as fallback user caching directory" USER_CACHES_DIR="$(abspath ~/.cache)" esac fi # Ensure we are dealing with a complete path USER_CACHES_DIR="$(abspath "$USER_CACHES_DIR")" : "${BUILD_CACHE_BUST:=1}" : "${BUILD_CACHE_DIR:="$USER_CACHES_DIR/libmongocrypt/build.$BUILD_CACHE_BUST"}" # Silence shellcheck: : "$LIBMONGOCRYPT_DIR,$EXE_SUFFIX" libmongocrypt-1.8.4/.evergreen/init.test.sh000066400000000000000000000020761454530651600207470ustar00rootroot00000000000000#!/bin/bash # Test shell utilities. . "$(dirname "${BASH_SOURCE[0]}")/init.sh" function assert_eq() { if [ "$1" != "$2" ]; then echo "${BASH_SOURCE[0]}:${BASH_LINENO[0]} assertion failed: '$1' != '$2'" return 1 fi } function test_abspath() { mkdir -p /tmp/a/b/c cd /tmp/a/b/c got=$(abspath .) expect=/tmp/a/b/c assert_eq "$got" "$expect" got=$(abspath ..) expect=/tmp/a/b assert_eq "$got" "$expect" got=$(abspath .././foo.txt) expect=/tmp/a/b/foo.txt assert_eq "$got" "$expect" got=$(abspath /foo.txt) expect=/foo.txt assert_eq "$got" "$expect" got=$(abspath /tmp/a/../a/foo.txt) expect=/tmp/a/foo.txt assert_eq "$got" "$expect" got=$(abspath /tmp//a//b//c//foo.txt) expect=/tmp/a/b/c/foo.txt assert_eq "$got" "$expect" pushd /tmp > /dev/null got=$(abspath ./a/b/c/foo.txt) expect=/tmp/a/b/c/foo.txt assert_eq "$got" "$expect" popd > /dev/null got=$(abspath /a/b/c/foo.txt) expect=/a/b/c/foo.txt assert_eq "$got" "$expect" } test_abspath libmongocrypt-1.8.4/.evergreen/linker-tests.sh000077500000000000000000000066661454530651600214660ustar00rootroot00000000000000#!/bin/bash # Directory layout # .evergreen # -linker_tests_deps # --app # --bson_patches # # linker_tests (created by this script) # -libmongocrypt-cmake-build (for artifacts built from libmongocrypt source) # -app-cmake-build # -mongo-c-driver # --cmake-build # -install # --bson1 # --bson2 # --libmongocrypt # . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" linker_tests_root="$LIBMONGOCRYPT_DIR/linker_tests" linker_tests_deps_root="$EVG_DIR/linker_tests_deps" rm -rf -- "$linker_tests_root" mkdir -p "$linker_tests_root"/{install,libmongocrypt-cmake-build,app-cmake-build} # Make libbson1 run_chdir "$linker_tests_root" bash "$EVG_DIR/prep_c_driver_source.sh" MONGOC_DIR="$linker_tests_root/mongo-c-driver" if test "$OS_NAME" = "windows" && is_false WINDOWS_32BIT && is_false USE_NINJA; then # These options are only needed for VS CMake generators to force it to # generate a 64-bit build. Default is 32-bit. Ninja inherits settings # from the build environment variables. ADDITIONAL_CMAKE_FLAGS="-Thost=x64 -A x64" fi if [ "${MACOS_UNIVERSAL-}" = "ON" ]; then ADDITIONAL_CMAKE_FLAGS="$ADDITIONAL_CMAKE_FLAGS -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64'" fi common_cmake_args=( $ADDITIONAL_CMAKE_FLAGS -DCMAKE_BUILD_TYPE=RelWithDebInfo ) if is_true USE_NINJA; then export NINJA_EXE : "${NINJA_EXE:="$linker_tests_root/ninja$EXE_SUFFIX"}" common_cmake_args+=( -GNinja -DCMAKE_MAKE_PROGRAM="$NINJA_EXE" ) bash "$EVG_DIR/ensure-ninja.sh" fi run_chdir "$MONGOC_DIR" git apply --ignore-whitespace "$linker_tests_deps_root/bson_patches/libbson1.patch" BUILD_PATH="$MONGOC_DIR/cmake-build" BSON1_INSTALL_PATH="$linker_tests_root/install/bson1" SRC_PATH="$MONGOC_DIR" run_cmake \ -DENABLE_MONGOC=OFF \ "${common_cmake_args[@]}" \ -DCMAKE_INSTALL_PREFIX="$BSON1_INSTALL_PATH" \ "-H$SRC_PATH" \ "-B$BUILD_PATH" run_cmake --build "$BUILD_PATH" --target install --config RelWithDebInfo # Prepare libbson2 run_chdir "$MONGOC_DIR" git reset --hard run_chdir "$MONGOC_DIR" git apply --ignore-whitespace "$linker_tests_deps_root/bson_patches/libbson2.patch" LIBBSON2_SRC_DIR="$MONGOC_DIR" # Build libmongocrypt, static linking against libbson2 BUILD_DIR="$linker_tests_root/libmongocrypt-cmake-build" LMC_INSTALL_PATH="$linker_tests_root/install/libmongocrypt" SRC_PATH="$LIBMONGOCRYPT_DIR" run_cmake \ "-DMONGOCRYPT_MONGOC_DIR=$LIBBSON2_SRC_DIR" \ "${common_cmake_args[@]}" \ -DCMAKE_INSTALL_PREFIX="$LMC_INSTALL_PATH" \ "-H$SRC_PATH" \ "-B$BUILD_DIR" run_cmake --build "$BUILD_DIR" --target install --config RelWithDebInfo echo "Test case: Modelling libmongoc's use" # app links against libbson1.so # app links against libmongocrypt.so BUILD_DIR="$linker_tests_root/app-cmake-build" PREFIX_PATH="$LMC_INSTALL_PATH;$BSON1_INSTALL_PATH" SRC_PATH="$linker_tests_deps_root/app" run_cmake \ "${common_cmake_args[@]}" \ -DCMAKE_PREFIX_PATH="$PREFIX_PATH" \ "-H$SRC_PATH" \ "-B$BUILD_DIR" run_cmake --build "$BUILD_DIR" --target app --config RelWithDebInfo export PATH="$PATH:$BSON1_INSTALL_PATH/bin:$LMC_INSTALL_PATH/bin" if is_true IS_MULTICONF; then APP_CMD="$BUILD_DIR/RelWithDebInfo/app.exe" else APP_CMD="$BUILD_DIR/app" fi check_output () { output="$($APP_CMD)" if [[ "$output" != *"$1"* ]]; then printf " Got: %s\nExpected: %s\n" "$output" "$1" exit 1; fi echo "ok" } check_output ".calling bson_malloc0..from libbson1..calling mongocrypt_binary_new..from libbson2." exit 0 libmongocrypt-1.8.4/.evergreen/linker_tests_deps/000077500000000000000000000000001454530651600222065ustar00rootroot00000000000000libmongocrypt-1.8.4/.evergreen/linker_tests_deps/app/000077500000000000000000000000001454530651600227665ustar00rootroot00000000000000libmongocrypt-1.8.4/.evergreen/linker_tests_deps/app/CMakeLists.txt000066400000000000000000000005051454530651600255260ustar00rootroot00000000000000cmake_minimum_required (VERSION 3.5) project (app C) add_executable (app app.c) find_package (bson-1.0 1.11 REQUIRED) message ("-- libbson found version \"${bson-1.0_VERSION}\"") target_link_libraries (app PRIVATE mongo::bson_static) find_package (mongocrypt REQUIRED) target_link_libraries (app PRIVATE mongo::mongocrypt)libmongocrypt-1.8.4/.evergreen/linker_tests_deps/app/app.c000066400000000000000000000005111454530651600237070ustar00rootroot00000000000000#include #include int main () { char *a; mongocrypt_binary_t *b; printf(".calling bson_malloc0."); a = bson_malloc0 (1); printf(".calling mongocrypt_binary_new."); b = mongocrypt_binary_new (); bson_free (a); mongocrypt_binary_destroy (b); return 0; }libmongocrypt-1.8.4/.evergreen/linker_tests_deps/bson_patches/000077500000000000000000000000001454530651600246565ustar00rootroot00000000000000libmongocrypt-1.8.4/.evergreen/linker_tests_deps/bson_patches/libbson1.patch000066400000000000000000000012661454530651600274150ustar00rootroot00000000000000Adds a printf to bson_malloc0 to test linking scenarios with two forms of libbson. See linker-tests.sh. If this patch fails to apply, regenerate from libbson's source. diff --git a/src/libbson/src/bson/bson-memory.c b/src/libbson/src/bson/bson-memory.c index 0e1523331..aa7112305 100644 --- a/src/libbson/src/bson/bson-memory.c +++ b/src/libbson/src/bson/bson-memory.c @@ -104,6 +104,7 @@ bson_malloc0 (size_t num_bytes) /* IN */ { void *mem = NULL; + printf (".from libbson1."); if (BSON_LIKELY (num_bytes)) { if (BSON_UNLIKELY (!(mem = gMemVtable.calloc (1, num_bytes)))) { fprintf (stderr, "Failure to allocate memory in bson_malloc0(). errno: %d.\n", errno); libmongocrypt-1.8.4/.evergreen/linker_tests_deps/bson_patches/libbson2.patch000066400000000000000000000012701454530651600274110ustar00rootroot00000000000000Adds a printf to bson_malloc0 to test linking scenarios with two forms of libbson. See linker-tests.sh. If this patch fails to apply, regenerate from libbson's source. diff --git a/src/libbson/src/bson/bson-memory.c b/src/libbson/src/bson/bson-memory.c index 0e1523331..aa7112305 100644 --- a/src/libbson/src/bson/bson-memory.c +++ b/src/libbson/src/bson/bson-memory.c @@ -104,6 +104,7 @@ bson_malloc0 (size_t num_bytes) /* IN */ { void *mem = NULL; + printf (".from libbson2.\n"); if (BSON_LIKELY (num_bytes)) { if (BSON_UNLIKELY (!(mem = gMemVtable.calloc (1, num_bytes)))) { fprintf (stderr, "Failure to allocate memory in bson_malloc0(). errno: %d.\n", errno); libmongocrypt-1.8.4/.evergreen/pkgconfig-tests.sh000077500000000000000000000142671454530651600221450ustar00rootroot00000000000000#!/bin/bash . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" if ! have_command pkg-config; then echo "pkg-config not present on this platform; skipping test ..." exit 0 fi pkgconfig_tests_root=$LIBMONGOCRYPT_DIR/_build/pkgconfig_tests rm -rf "$pkgconfig_tests_root" mongoc_src_dir="$pkgconfig_tests_root/mongo-c-driver" mkdir -p "$mongoc_src_dir" run_chdir "$pkgconfig_tests_root" "$EVG_DIR/prep_c_driver_source.sh" if test "$OS_NAME" = "windows" && is_false WINDOWS_32BIT && is_false USE_NINJA; then # These options are only needed for VS CMake generators to force it to # generate a 64-bit build. Default is 32-bit. Ninja inherits settings # from the build environment variables. ADDITIONAL_CMAKE_FLAGS="-Thost=x64 -A x64" fi if [ "$MACOS_UNIVERSAL" = "ON" ]; then ADDITIONAL_CMAKE_FLAGS="$ADDITIONAL_CMAKE_FLAGS -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64'" fi common_cmake_args=( -DCMAKE_BUILD_TYPE=RelWithDebInfo $ADDITIONAL_CMAKE_FLAGS ) if is_true USE_NINJA; then export NINJA_EXE : "${NINJA_EXE:="$pkgconfig_tests_root/ninja$EXE_SUFFIX"}" common_cmake_args+=( -GNinja -DCMAKE_MAKE_PROGRAM="$NINJA_EXE" ) bash "$EVG_DIR/ensure-ninja.sh" fi libbson_install_dir="$pkgconfig_tests_root/install/libbson" build_dir="$mongoc_src_dir/_build" run_cmake -DENABLE_MONGOC=OFF \ "${common_cmake_args[@]}" \ -DCMAKE_INSTALL_PREFIX="$libbson_install_dir" \ -H"$mongoc_src_dir" \ -B"$build_dir" run_cmake --build "$build_dir" --target install --config RelWithDebInfo libbson_pkg_config_path="$(native_path "$(dirname "$(find "$libbson_install_dir" -name libbson-1.0.pc)")")" # Build libmongocrypt, static linking against libbson and configured for the PPA mongocrypt_install_dir="$pkgconfig_tests_root/install/libmongocrypt" build_dir=$pkgconfig_tests_root/mongocrypt-build run_cmake -DUSE_SHARED_LIBBSON=OFF \ -DENABLE_BUILD_FOR_PPA=ON \ "${common_cmake_args[@]}" \ -DCMAKE_INSTALL_PREFIX="$mongocrypt_install_dir" \ -H"$LIBMONGOCRYPT_DIR" \ -B"$build_dir" run_cmake --build "$build_dir" --target install --config RelWithDebInfo # To validate the pkg-config scripts, we don't want the libbson script to be visible mongocrypt_pkg_config_path="$(native_path "$(dirname "$(find "$mongocrypt_install_dir" -name libmongocrypt.pc)")")" export PKG_CONFIG_PATH PKG_CONFIG_PATH="$mongocrypt_pkg_config_path:$libbson_pkg_config_path" echo "Validating pkg-config scripts" pkg-config --debug --print-errors --exists libmongocrypt-static pkg-config --debug --print-errors --exists libmongocrypt # Build example-state-machine, static linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt-static libbson-static-1.0) \ -o "$pkgconfig_tests_root/example-state-machine" \ "$LIBMONGOCRYPT_DIR/test/example-state-machine.c" \ $(pkg-config --libs libmongocrypt-static) run_chdir "$LIBMONGOCRYPT_DIR" "$pkgconfig_tests_root/example-state-machine" # Build example-no-bson, static linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt-static) \ -o "$pkgconfig_tests_root/example-no-bson" \ "$LIBMONGOCRYPT_DIR/test/example-no-bson.c" \ $(pkg-config --libs libmongocrypt-static) command "$pkgconfig_tests_root/example-no-bson" # Build example-state-machine, dynamic linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt libbson-static-1.0) \ -o "$pkgconfig_tests_root/example-state-machine" \ "$LIBMONGOCRYPT_DIR/test/example-state-machine.c" \ $(pkg-config --libs libmongocrypt) run_chdir "$LIBMONGOCRYPT_DIR" \ env LD_LIBRARY_PATH="$mongocrypt_install_dir/lib:$mongocrypt_install_dir/lib64" \ "$pkgconfig_tests_root/example-state-machine" # Build example-no-bson, dynamic linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt) \ -o "$pkgconfig_tests_root/example-no-bson" \ "$LIBMONGOCRYPT_DIR/test/example-no-bson.c" \ $(pkg-config --libs libmongocrypt) env LD_LIBRARY_PATH="$mongocrypt_install_dir/lib:$mongocrypt_install_dir/lib64" \ "$pkgconfig_tests_root/example-no-bson" # Clean up prior to next execution rm -r "$mongocrypt_install_dir" # Build libmongocrypt, dynamic linking against libbson run_cmake -DUSE_SHARED_LIBBSON=ON \ -DENABLE_BUILD_FOR_PPA=OFF \ "${common_cmake_args[@]}" \ -DCMAKE_INSTALL_PREFIX="$mongocrypt_install_dir" \ -H"$LIBMONGOCRYPT_DIR" \ -B"$build_dir" run_cmake --build "$build_dir" --target install --config RelWithDebInfo # Build example-state-machine, static linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt-static libbson-static-1.0) \ -o "$pkgconfig_tests_root/example-state-machine" \ "$LIBMONGOCRYPT_DIR/test/example-state-machine.c" \ $(pkg-config --libs libmongocrypt-static) run_chdir "$LIBMONGOCRYPT_DIR" \ env LD_LIBRARY_PATH="$libbson_install_dir/lib:/$libbson_install_dir/lib64" \ "$pkgconfig_tests_root/example-state-machine" # Build example-no-bson, static linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt-static) \ -o "$pkgconfig_tests_root/example-no-bson" \ "$LIBMONGOCRYPT_DIR/test/example-no-bson.c" \ $(pkg-config --libs libmongocrypt-static) env LD_LIBRARY_PATH="$libbson_install_dir/lib:/$libbson_install_dir/lib64" \ "$pkgconfig_tests_root/example-no-bson" # Build example-state-machine, dynamic linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt libbson-static-1.0) \ -o "$pkgconfig_tests_root/example-state-machine" \ "$LIBMONGOCRYPT_DIR/test/example-state-machine.c" \ $(pkg-config --libs libmongocrypt) run_chdir "$LIBMONGOCRYPT_DIR" \ env LD_LIBRARY_PATH="$mongocrypt_install_dir/lib:$mongocrypt_install_dir/lib64:$libbson_install_dir/lib:$libbson_install_dir/lib64" \ "$pkgconfig_tests_root/example-state-machine" # Build example-no-bson, dynamic linking against libmongocrypt gcc $(pkg-config --cflags libmongocrypt) \ -o "$pkgconfig_tests_root/example-no-bson" \ "$LIBMONGOCRYPT_DIR/test/example-no-bson.c" \ $(pkg-config --libs libmongocrypt) env LD_LIBRARY_PATH="$mongocrypt_install_dir/lib:$mongocrypt_install_dir/lib64:$libbson_install_dir/lib:$libbson_install_dir/lib64" \ "$pkgconfig_tests_root/example-no-bson" echo "pkg-config tests PASS" libmongocrypt-1.8.4/.evergreen/prep_c_driver_source.sh000077500000000000000000000006331454530651600232310ustar00rootroot00000000000000#!/bin/bash set -euxo pipefail # Clone mongo-c-driver and check out to a tagged version. MONGO_C_DRIVER_VERSION=1.17.0 # Force checkout with lf endings since .sh must have lf, not crlf on Windows git clone https://github.com/mongodb/mongo-c-driver.git --config core.eol=lf --config core.autocrlf=false --depth=1 --branch $MONGO_C_DRIVER_VERSION echo $MONGO_C_DRIVER_VERSION > mongo-c-driver/VERSION_CURRENT libmongocrypt-1.8.4/.evergreen/print-env-info.sh000077500000000000000000000003441454530651600217000ustar00rootroot00000000000000#!/bin/bash # Print information about the environment. # set -o xtrace evergreen_root=$(pwd) git --version openssl version python --version if which gcc; then gcc --version fi if which clang; then clang --version filibmongocrypt-1.8.4/.evergreen/requirements.txt000077500000000000000000000000121454530651600217450ustar00rootroot00000000000000virtualenvlibmongocrypt-1.8.4/.evergreen/setup-env.sh000066400000000000000000000021061454530651600207460ustar00rootroot00000000000000#!/bin/bash . "$(dirname "${BASH_SOURCE[0]}")/init.sh" : "${ADDITIONAL_CMAKE_FLAGS:=}" : "${LIBMONGOCRYPT_EXTRA_CMAKE_FLAGS:=}" : "${LIBMONGOCRYPT_EXTRA_CFLAGS:=}" : "${PPA_BUILD_ONLY:=}" : "${MACOS_UNIVERSAL:=}" : "${WINDOWS_32BIT:=}" : "${OS:=unspecified}" IS_MULTICONF=OFF if test "$OS_NAME" = "windows" && is_false USE_NINJA; then IS_MULTICONF=ON fi : "$IS_MULTICONF" # Silence shellcheck evergreen_root="$(dirname "$LIBMONGOCRYPT_DIR")" : "${MONGOCRYPT_INSTALL_PREFIX:="$evergreen_root/install/libmongocrypt"}" MONGOCRYPT_INSTALL_PREFIX="$(native_path "$MONGOCRYPT_INSTALL_PREFIX")" mkdir -p "$MONGOCRYPT_INSTALL_PREFIX" if test -f /proc/cpuinfo; then # Count the number of lines beginning with "processor" in the cpuinfo jobs="$(grep -c '^processor' /proc/cpuinfo)" if have_command bc; then # Add two (hueristic to compensate for I/O latency) jobs="$(echo "$jobs+2" | bc)" fi export MAKEFLAGS="-j$jobs ${MAKEFLAGS-}" else # Cannot tell the best number of jobs. Provide a reasonable default. export MAKEFLAGS="-j8 ${MAKEFLAGS-}" fi libmongocrypt-1.8.4/.evergreen/vs-env-run.ps1000066400000000000000000000221061454530651600211330ustar00rootroot00000000000000<# .SYNOPSIS Execute a command with a Visual Studio environment loaded .DESCRIPTION This script will load the specified Visual Studio environment with the specified options set, and then execute the given program This script makes use of vswhere.exe, which is installed with Visual Studio 2017 or later, but supports all Visual Studio versions. Only the -Version and -TargetArch parameters are required. The command should be given as a script block or executable string. .EXAMPLE PS C:\> vs-env-run.ps1 -Version 14.* -TargetArch amd64 { build_all.ps1 } This will load the Visual Studio 14 environment targetting amd64 processors and then run 'build_all.ps1' #> [CmdletBinding(PositionalBinding = $false)] param ( # Select a version of Visual Studio to activate. Accepts wildcards. # # Major versions by year release: # # - 14.* => VS 2015 # - 15.* => VS 2017 # - 16.* => VS 2019 # - 17.* => VS 2022 # # Use of a wildcard pattern in scripts is recommended for portability. # # Supports tab-completion if vswhere.exe is present. [Parameter(Mandatory)] # xxx: This requires PowerShell 5+, which some build hosts don't have: # [ArgumentCompleter({ # param($commandName, $paramName, $wordToComplete, $commandAst, $fakeBoundParameters) # $vswhere_found = @(Get-ChildItem -Filter vswhere.exe ` # -Path 'C:\Program Files*\Microsoft Visual Studio\Installer\' ` # -Recurse)[0] # if ($null -eq $vswhere_found) { # Write-Host "No vswhere found" # return $null # } # return & $vswhere_found -utf8 -nologo -format json -all -legacy -prerelease -products * ` # | ConvertFrom-Json ` # | ForEach-Object { $_.installationVersion } ` # | Where-Object { $_ -like "$wordToComplete*" } # })] [string] $Version, # The target architecture for the build [Parameter(Mandatory)] [ValidateSet("x86", "amd64", "arm", "arm64", IgnoreCase = $false)] [string] $TargetArch, # Select a specific Windows SDK version. [string] # xxx: This requires PowerShell 5+, which some build hosts don't have: # [ArgumentCompleter({ # param($commandName, $paramName, $wordToComplete, $commandAst, $fakeBoundParameters) # $found = @() # if (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\10\Include") { # $found += $( # Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\Include"` # | Where-Object { Test-Path "$($_.FullName)\um\Windows.h" }` # | ForEach-Object { Split-Path -Leaf $_.FullName } # ) # } # if (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\8.1\Include") { # $found += $( # Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\8.1\Include"` # | Where-Object { Test-Path "$($_.FullName)\um\Windows.h" }` # | ForEach-Object { Split-Path -Leaf $_.FullName } # ) # } # return $found | Where-Object { $_ -like "$wordToComplete*" } # })] $WinSDKVersion, # The host architecture to use. Not usually needed. Defaults to x86. [ValidateSet("x86", "amd64", IgnoreCase = $false)] [string] $HostArch = "x86", # The Visual C++ toolset to load [string] $VCToolsetVersion, # Prefer Visual C++ libraries with Spectre mitigations [switch] $UseSpectreMitigationLibraries, # The app platform to load. Default is "Desktop" [ValidateSet("Desktop", "UWP", IgnoreCase = $false)] [string] $AppPlatform = "Desktop", # The directory to store ephemeral files [string] $ScratchDir, # The command to execute within the VS environment. May be any invocable object. [Parameter(Mandatory, Position = 1)] $Command ) $ErrorActionPreference = 'Stop' $this_dir = $PSScriptRoot if ([string]::IsNullOrEmpty($ScratchDir)) { $ScratchDir = Join-Path (Split-Path -Parent $this_dir) "_build" } New-Item $ScratchDir -ItemType Directory -ErrorAction Ignore $vswhere = Join-Path $ScratchDir "vswhere.exe" if (!(Test-Path $vswhere)) { $ProgressPreference = "SilentlyContinue" [Net.ServicePointManager]::SecurityProtocol = 'tls12, tls11' Invoke-WebRequest ` -UseBasicParsing ` -Uri "https://github.com/microsoft/vswhere/releases/download/3.0.3/vswhere.exe" ` -OutFile $vswhere } # Ask vswhere for all the installed products: $vswhere_json = & $vswhere -utf8 -nologo -format json -all -legacy -prerelease -products * | Out-String $vs_versions = $vswhere_json | ConvertFrom-Json Write-Debug "Detected VS versions: $vs_versions" # Pick the product that matches the pattern $selected = @($vs_versions | Where-Object { $_.installationVersion -like $Version }) if ($selected.Length -eq 0) { throw "No Visual Studio was found with a version matching '$Version'" } $selected = $selected[0] Write-Host "Selected Visual Studio version $($selected.installationVersion) [$($selected.installationPath)]" # Find Windows SDK version if (-not [String]::IsNullOrEmpty($WinSDKVersion)) { $sdk_avail = @() if (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\10\Include") { $sdk_avail += $( Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\Include" ` | Where-Object { Test-Path "$($_.FullName)\um\Windows.h" } ` | ForEach-Object { Split-Path -Leaf $_.FullName } ) } if (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\8.1\Include") { $sdk_avail += $( Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\8.1\Include" ` | Where-Object { Test-Path "$($_.FullName)\um\Windows.h" } ` | ForEach-Object { Split-Path -Leaf $_.FullName } ) } Write-Debug "Detected Windows SDK versions: $sdk_avail" $sdk_selected = @($sdk_avail | Where-Object { $_ -like $WinSDKVersion })[0] if ($null -eq $sdk_selected) { throw "No Windows SDK version was found matching '$WinSDKVersion' (Of $sdk_avail)" } $WinSDKVersion = $sdk_selected } # Find the environment-activation script for the chosen VS $vsdevcmd_bat = @(Get-ChildItem ` -Path $selected.installationPath ` -Filter "VsDevCmd.bat" -Recurse)[0] $env_script_content = "" # Use batch and the 'set' command to get the required environment variables out. if ($null -eq $vsdevcmd_bat) { Write-Warning "No VsDevCmd.bat found for the requested VS version. Falling back to vcvarsall.bat" Write-Warning "Additional platform selection functionality will be limited" $vcvarsall_bat = @(Get-ChildItem -Path $selected.installationPath -Filter "vcvarsall.bat" -Recurse)[0] if ($null -eq $vcvarsall_bat) { throw "No VsDevCmd.bat nor vcvarsall.bat file found for requested Visual Studio version '$($selected.installationVersion)'" } Write-Debug "Using vcvarsall: [$($vcvarsall_bat.FullName)]" $env_script_content = @" @echo off call "$($vcvarsall_bat.FullName)" $TargetArch $WinSDKVersion set _rc=%ERRORLEVEL% set exit /b %_rc% "@ } else { # Build up the argument string to load the appropriate environment $argstr = "-no_logo -arch=$TargetArch -host_arch=$HostArch -app_platform=$AppPlatform" if ($UseSpectreMitigationLibraries) { $argstr += " -vcvars_spectre_libs=spectre" } if ($WinSDKVersion) { $argstr += " -winsdk=$WinSDKVersion" } if ($VCToolsetVersion) { $argstr += " -vcvars_ver=$VCToolsetVersion" } Write-Debug "Using VsDevCmd: [${vsdevcmd_bat.FullName}]" $env_script_content = @" @echo off call "$($vsdevcmd_bat.FullName)" $argstr set _rc=%ERRORLEVEL% set exit /b %_rc% "@ } # Write the script and then execute it, capturing its output Set-Content "$ScratchDir/.env.bat" $env_script_content Write-Host "Loading VS environment..." $output = & cmd.exe /c "$ScratchDir/.env.bat" if ($LASTEXITCODE -ne 0) { throw "Loading the environment failed [$LASTEXITCODE]:`n$output" } # The plain 'set' command emits VAR=VALUE lines for each loaded environment # variable. Parse those out and set them in our own environment. $prior_env = @{} foreach ($line in $output.Split("`r`n")) { if ($line -match "(\w+)=(.+)") { $varname = $Matches[1] $value = $Matches[2] # Set the environment value (may be null): $prior_env[$varname] = [System.Environment]::GetEnvironmentVariable($varname) [System.Environment]::SetEnvironmentVariable($varname, $value) } } Write-Debug "Running command: $(ConvertTo-Json $Command)" try { # Now invoke the external command. & $Command if ($LASTEXITCODE -ne 0) { # If it was a process that returned non-zero, throw an error. throw "Subcommand failed [$LASTEXITCODE]" } } finally { # Restore the prior environment foreach ($key in $prior_env.Keys) { [System.Environment]::SetEnvironmentVariable($key, $prior_env[$key]) } } libmongocrypt-1.8.4/.evergreen/windows-upload-doit-unstable.json000066400000000000000000000006521454530651600251070ustar00rootroot00000000000000{ "buildvariants": [ { "tasks": [ { "name": "windows-upload" } ], "display_name": "Windows uploader", "run_on": [ "windows-64-vs2017-test" ], "name": "windows-uploader", "expansions": { "upload_suffix": "_unstable" } } ] }libmongocrypt-1.8.4/.evergreen/windows-upload-doit.json000066400000000000000000000005221454530651600232700ustar00rootroot00000000000000{ "buildvariants": [ { "tasks": [ { "name": "windows-upload" } ], "display_name": "Windows uploader", "run_on": [ "windows-64-vs2017-test" ], "name": "windows-uploader" } ] }libmongocrypt-1.8.4/.git-blame-ignore-revs000066400000000000000000000000721454530651600205240ustar00rootroot00000000000000# Mass reformat: d60041a1a863c27bb08c43fe56c2e9588f56d920 libmongocrypt-1.8.4/.gitattributes000066400000000000000000000000771454530651600173240ustar00rootroot00000000000000# Shell scripts require lf endings *.sh text eol=lf libmongocrypt-1.8.4/.gitignore000066400000000000000000000010741454530651600164170ustar00rootroot00000000000000doc/html doc/latex test/schema.json .vscode # Default build directories cmake-build cmake-build-nocrypto _build/ # CMake generated files *.sln *.vcxproj *.vcxproj.filters *.xcodeproj CMakeCache.txt CTestTestFile.cmake CMakeFiles CMakeScripts Debug/* Makefile Win32/* cmake_install.cmake x64/* Testing/ CPackConfig.cmake CPackSourceConfig.cmake dist_manifest.txt *.sdf .vs install_manifest.txt # Build artifacts. *.a *.dylib *.gcda *.gcno *.gz *.lo *.o *.pc *.so *.so.* # Generated header src/mongocrypt-export.h # IDEs .idea/ VERSION_CURRENT .csfle *.pyc .DS_Store libmongocrypt-1.8.4/.lsan-suppressions000066400000000000000000000002221454530651600201320ustar00rootroot00000000000000leak:ccrng_cryptographic_init_once leak:ccrng_cryptographic_generate leak:CRYPTO_zalloc # Ignore leak reported in dlopen error. leak:_dlerror_run libmongocrypt-1.8.4/CHANGELOG.md000066400000000000000000000144361454530651600162460ustar00rootroot00000000000000# ChangeLog ## 1.8.3 ### Fixed - Fix `aarch64` packages for RHEL 8, RHEL 9, Amazon 2023, and Amazon 2 ## 1.8.3 ### Improvements - Include packages for RHEL 8, RHEL 9, and Amazon 2023 ## 1.8.2 ### Fixed - Fix possible leaks in Queryable Encryption in errors on malformed data. ## 1.8.1 - Bypass search index management commands in automatic encryption ## 1.8.0 This release adds stable support of the Queryable Encryption (QE) feature for the "Indexed" and "Unindexed" algorithms. ## 1.8.0-alpha1 This release makes backwards breaking changes to Queryable Encryption (QE) behavior added in the 1.8.0-alpha0 release: - Do not apply default to min/max values for int/long/date. - Enable the QEv2 protocol by default. Remove function to enable QEv2. ## 1.8.0-alpha0 ### Improvements - Support Queryable Encryption v2 protocol. ## 1.7.2 ### Improvements - Add toggle for Decimal128 Range Support. ### Fixed - Fix i686 (32-bit) build. - Fix 32-bit ARM build. ## 1.7.1 ### Improvements - Vendor Intel DFP library and allow using system DFP. ### Fixed - Fix possible abort on base64 decode error of KMS messages. - Fix ILP32-target builds. - Fix LTO build. - Fix IntelDFP to not require Git. ## 1.7.0 ### New Features - Add encryptExpression helper - Support for range index. NOTE: The Range algorithm is experimental only. It is not intended for public use. ## 1.7.0-alpha2 ### New Features - Support range index for decimal128. NOTE: The Range algorithm is experimental only. It is not intended for public use. ## 1.7.0-alpha1 ### New Features - Add encryptExpression helper ## 1.7.0-alpha0 ### New Features - Support range index for int32, int64, double, and date. NOTE: The Range algorithm is experimental only. It is not intended for public use. ## 1.6.2 ## Fixed - Fix build on FreeBSD. - Set context error state during KMS provider validation. ## 1.6.1 ## Fixed - Fix libbson dependency in pkg-config for PPA. ## 1.6.0 ## New Features - Support accessToken to authenticate with Azure. ## Fixed - Use correct schema when `collMod` command includes `validator.$jsonSchema`. ## 1.6.0-alpha0 ### New Features - Support accessToken to authenticate with GCP. ### Improvements - Use CRLF, not LF, for HTTP request newlines. - Include full body of HTTP errors in `mongocrypt_status_t`. ## 1.5.2 ### Fixed - Fix datakey decryption requiring multiple rounds of KMS requests. ## 1.5.1 ## Warnings - This release has a severe bug in the context returned by `mongocrypt_ctx_rewrap_many_datakey_init` that may result in data corruption. Please upgrade to 1.5.2 before using `mongocrypt_ctx_rewrap_many_datakey_init`. ### New Features - Update Java bindings to support remaining 1.5.0 API. ## 1.5.0 ## Warnings - This release has a severe bug in the context returned by `mongocrypt_ctx_rewrap_many_datakey_init` that may result in data corruption. Please upgrade to 1.5.2 before using `mongocrypt_ctx_rewrap_many_datakey_init`. ## Fixed - Update to use new payload for FLE 2.0 find. - Require contention factor. ## 1.5.0-rc2 ### Fixed - Fix handling of create command with $jsonSchema. - Fix leak on encrypt or decrypt error. ## Improved - Accept string values for QueryType and IndexType. ## 1.4.1 ### Fixed - Add missing MONGOCRYPT_EXPORT to mongocrypt_ctx_provide_kms_providers ## 1.5.0-rc1 ## Fixed - Revert new payload for FLE 2.0 find. - Do not send "create" and "createIndexes" to mongocryptd when bypassing query analysis. ## 1.5.0-rc0 ## Fixed - Account for shared library rename. - Update to use new payload for FLE 2.0 find. ## 1.5.0-alpha2 ## New Features - Fix explain when using csfle shared library. - Do not bypass "create" or "createIndexes" commands. Support "collMod". - Bypass "hello", "buildInfo", "getCmdLineOpts", and "getLog" commands. ## Fixed - Preserve $db in output command. - Add missing MONGOCRYPT_EXPORT to mongocrypt_ctx_provide_kms_providers ## 1.5.0-alpha1 ### Fixed - Pick a random contention factor on FLE 2.0 insert. ## 1.5.0-alpha0 ### New Features - Support FLE 2.0. - Support FLE 1.0 Shared Library. - Support Key Management API. ## 1.4.0 ### New Features - Support on-demand credentials with `MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS` state and `mongocrypt_ctx_provide_kms_providers`. ## 1.4.0-alpha0 ### New Features - Support on-demand AWS credentials with `MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS` state and `mongocrypt_ctx_provide_kms_providers`. ### Fixed - Resolve 32 bit Windows compile errors. ## 1.3.1 ### New Features - Support custom key material through `mongocrypt_ctx_setopt_key_material`. ### Fixed - Fix deprecation warnings with OpenSSL 3.0. - Resolve possible symbol conflicts with OpenSSL. ## 1.3.0 - Support "kmip" KMS provider. - Add mongocrypt_kms_ctx_get_kms_provider. - Apply default port to endpoints returned in mongocrypt_kms_ctx_endpoint ## 1.2.2 - Fix pkg-config and PPA build dependency on libbson. - Fix JSON schema caching behavior when server reports no JSON schema. ## 1.2.1 ### Fixed - Fix possible crash when oauth credentials expire. ## 1.2.0 ### Added - Support AWS temporary credentials via session token. ### Fixed - Add "=" padding to base64url encoding. ## 1.1.0 ### Added - Add ENABLE_PIC cmake option, set to ON by default, so static libraries build with -fPIC by default on relevant systems. ### Fixed - Errors produced in all crypto callbacks are propagated to user. ## 1.1.0-beta1 ### Deprecated - mongocrypt_setopt_kms_provider_aws and mongocrypt_setopt_kms_provider_local are deprecated in favor of the more flexible mongocrypt_setopt_kms_providers, which supports configuration of all KMS providers. - mongocrypt_ctx_setopt_masterkey_aws, mongocrypt_ctx_setopt_masterkey_aws_endpoint, and mongocrypt_ctx_setopt_masterkey_local are deprecated in favor of the more flexible mongocrypt_ctx_setopt_key_encryption_key, which supports configuration for all KMS providers. ### Added - Introduces a new crypto hook for signing the JSON Web Token (JWT) for Google Cloud Platform (GCP) requests: - mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 - Introduces a CLI utility `csfle` to test the context state machine against live KMS, mongocryptd, and mongod. See ./test/util/README.md. - Introduces two new functions to the libmongocrypt API. - mongocrypt_setopt_kms_providers To set the KMS providers. - mongocrypt_ctx_setopt_key_encryption_key To set the key encryption key. - Adds support for Azure and GCP KMS providers. libmongocrypt-1.8.4/CMakeLists.txt000066400000000000000000000623741454530651600172010ustar00rootroot00000000000000cmake_minimum_required (VERSION 3.12) # Preempt the MSVC_RUNTIME_LIBRARY properties if (POLICY CMP0091) cmake_policy (SET CMP0091 NEW) elseif (DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) message (WARNING "The CMAKE_MSVC_RUNTIME_LIBRARY variable is set, but CMake is too old to understand it") endif () project (mongocrypt C) # Used for the csfle-markup util: enable_language (CXX OPTIONAL) set (CMAKE_C_STANDARD 99) option (ENABLE_STATIC "Install static libraries" ON) option (ENABLE_PIC "Enables building of position independent code for static library components." ON ) option (ENABLE_BUILD_FOR_PPA "Maintainer-only option for preparing PPA build" OFF) option (ENABLE_ONLINE_TESTS "Enable online tests and the csfle utility" ON) if (ENABLE_WINDOWS_STATIC_RUNTIME) if (POLICY CMP0091) # CMake 3.15 makes this trivial: set (CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") else () # Fix it up the old-fashioned way string (REPLACE "/MDd" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") string (REPLACE "/MD" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") string (REPLACE "/MDd" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string (REPLACE "/MD" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") string (APPEND CMAKE_C_FLAGS_DEBUG " /MTd") string (APPEND CMAKE_CXX_FLAGS_DEBUG " /MTd") string (APPEND CMAKE_C_FLAGS_RELEASE " /MT") string (APPEND CMAKE_CXX_FLAGS_RELEASE " /MT") endif () endif () list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) include (GNUInstallDirs) include (LTO) include (ImportBSON) option (MONGOCRYPT_ENABLE_DECIMAL128 "Enable extended support for Decimal128" ON) mark_as_advanced (MONGOCRYPT_ENABLE_DECIMAL128) set (maybe_dfp_library) if (MONGOCRYPT_ENABLE_DECIMAL128) include (ImportDFP) set (maybe_dfp_library mongocrypt::intel_dfp) endif () if (USE_SHARED_LIBBSON AND ENABLE_BUILD_FOR_PPA) message (FATAL_ERROR "PPA build requires static linking to libbson") endif () if (DEFINED MONGOCRYPT_DFP_DIR AND ENABLE_BUILD_FOR_PPA) message (FATAL_ERROR "PPA build requires building with vendored Intel DFP") endif () # Enable a higher warning level and warnings-as-errors include (MongoC-Warnings) option (ENABLE_MORE_WARNINGS_AS_ERRORS "Enable extra warnings-as-errors in the build." OFF) if (ENABLE_MORE_WARNINGS_AS_ERRORS) mongoc_add_platform_compile_options ( msvc:/W3 msvc:/WX msvc:/wd4996 msvc:/wd4359 gnu-like:-Wall gnu-like:-Werror gnu-like:-Wswitch-enum gnu-like:-Wswitch-default ) add_link_options ( # Enable link-time warnings. VS 2015 sees LNK4099 spuriously, but it is a # non-fatal issue. LNK4217 and LNK4049 appear when using dllimport on # locally-defined symbols in kms-message. "$,/WX;/ignore:4217;/ignore:4049;/ignore:4099,-Werror>" ) endif () add_subdirectory (bindings/cs) include (GenerateExportHeader) include (CTest) include (Platform) set (MONGOCRYPT_PUBLIC_HEADERS src/mongocrypt-compat.h src/mongocrypt.h ) set (MONGOCRYPT_SOURCES src/crypto/cng.c src/crypto/commoncrypto.c src/crypto/libcrypto.c src/crypto/none.c src/mc-array.c src/mc-efc.c src/mc-fle2-find-range-payload.c src/mc-fle2-find-range-payload-v2.c src/mc-fle2-insert-update-payload.c src/mc-fle2-insert-update-payload-v2.c src/mc-fle2-encryption-placeholder.c src/mc-fle2-find-equality-payload.c src/mc-fle2-find-equality-payload-v2.c src/mc-fle2-payload-iev.c src/mc-fle2-payload-iev-v2.c src/mc-fle2-payload-uev.c src/mc-fle2-payload-uev-common.c src/mc-fle2-payload-uev-v2.c src/mc-fle2-rfds.c src/mc-range-edge-generation.c src/mc-range-mincover.c src/mc-range-encoding.c src/mc-rangeopts.c src/mc-reader.c src/mc-tokens.c src/mc-writer.c src/mongocrypt-binary.c src/mongocrypt-buffer.c src/mongocrypt-cache.c src/mongocrypt-cache-collinfo.c src/mongocrypt-cache-key.c src/mongocrypt-cache-oauth.c src/mongocrypt-ciphertext.c src/mongocrypt-crypto.c src/mongocrypt-ctx-datakey.c src/mongocrypt-ctx-decrypt.c src/mongocrypt-ctx-encrypt.c src/mongocrypt-ctx-rewrap-many-datakey.c src/mongocrypt-ctx.c src/mongocrypt-endpoint.c src/mongocrypt-kek.c src/mongocrypt-key.c src/mongocrypt-key-broker.c src/mongocrypt-kms-ctx.c src/mongocrypt-log.c src/mongocrypt-marking.c src/mongocrypt-opts.c src/mongocrypt-status.c src/mongocrypt-traverse-util.c src/mongocrypt-util.c src/mongocrypt.c src/os_win/os_mutex.c src/os_posix/os_mutex.c src/os_win/os_dll.c src/os_posix/os_dll.c ) # If MONGOCRYPT_CRYPTO is not set, choose a system default. if (NOT MONGOCRYPT_CRYPTO) set (MONGOCRYPT_CRYPTO OpenSSL) if (APPLE) set (MONGOCRYPT_CRYPTO CommonCrypto) elseif (WIN32) set (MONGOCRYPT_CRYPTO CNG) endif () endif () # Otherwise, override with crypto hooks. if (DISABLE_NATIVE_CRYPTO) set (MONGOCRYPT_CRYPTO none) endif () set (MONGOCRYPT_ENABLE_CRYPTO 0) set (MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO 0) set (MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO 0) set (MONGOCRYPT_ENABLE_CRYPTO_CNG 0) if (MONGOCRYPT_CRYPTO STREQUAL CommonCrypto) message ("Building with common crypto") set (MONGOCRYPT_ENABLE_CRYPTO 1) set (MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO 1) elseif (MONGOCRYPT_CRYPTO STREQUAL CNG) message ("Building with CNG") set (MONGOCRYPT_ENABLE_CRYPTO 1) set (MONGOCRYPT_ENABLE_CRYPTO_CNG 1) elseif (MONGOCRYPT_CRYPTO STREQUAL OpenSSL) message ("Building with OpenSSL") include (FindOpenSSL) message ("Found OpenSSL version ${OPENSSL_VERSION}") set (MONGOCRYPT_ENABLE_CRYPTO 1) set (MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO 1) elseif (MONGOCRYPT_CRYPTO STREQUAL none) message ("Building with no native crypto, hooks MUST be supplied with mongocrypt_setopt_crypto_hooks") else () message (FATAL_ERROR "Unknown crypto provider ${MONGOCRYPT_CRYPTO}") endif () set (MONGOCRYPT_ENABLE_TRACE 0) if (ENABLE_TRACE) message (WARNING "Building with trace logging. This is highly insecure. Do not use in a production environment") set (MONGOCRYPT_ENABLE_TRACE 1) endif () set (BUILD_VERSION "0.0.0" CACHE STRING "Library version") if (BUILD_VERSION STREQUAL "0.0.0") if (EXISTS ${CMAKE_BINARY_DIR}/VERSION_CURRENT) file (STRINGS ${CMAKE_BINARY_DIR}/VERSION_CURRENT BUILD_VERSION) elseif (EXISTS ${PROJECT_SOURCE_DIR}/VERSION_CURRENT) file (STRINGS ${PROJECT_SOURCE_DIR}/VERSION_CURRENT BUILD_VERSION) message (STATUS "File VERSION_CURRENT contained BUILD_VERSION ${BUILD_VERSION}") else () find_package (PythonInterp) if (PYTHONINTERP_FOUND) execute_process ( COMMAND ${PYTHON_EXECUTABLE} etc/calc_release_version.py WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE CALC_RELEASE_VERSION RESULT_VARIABLE CALC_RELEASE_VERSION_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE ) if (NOT CALC_RELEASE_VERSION_RESULT STREQUAL 0) # If python failed above, stderr would tell the user about it message (FATAL_ERROR "BUILD_VERSION not specified and could not be calculated\ (script invocation failed); specify in CMake command, -DBUILD_VERSION=" ) else () set (BUILD_VERSION ${CALC_RELEASE_VERSION}) message ("calculated BUILD_VERSION ${BUILD_VERSION}") file (WRITE ${CMAKE_BINARY_DIR}/VERSION_CURRENT ${CALC_RELEASE_VERSION}) endif () else () message (FATAL_ERROR "BUILD_VERSION not specified and could not be calculated\ (Python was not found on the system); specify in CMake command, -DBUILD_VERSION=" ) endif () message (STATUS "Storing BUILD_VERSION ${BUILD_VERSION} in file VERSION_CURRENT for later use") file (WRITE ${PROJECT_SOURCE_DIR}/VERSION_CURRENT ${BUILD_VERSION}) endif () else () message (STATUS "Storing BUILD_VERSION ${BUILD_VERSION} in file VERSION_CURRENT for later use") file (WRITE ${PROJECT_SOURCE_DIR}/VERSION_CURRENT ${BUILD_VERSION}) endif () set (MONGOCRYPT_BUILD_VERSION ${BUILD_VERSION}) configure_file ( "${PROJECT_SOURCE_DIR}/src/mongocrypt-config.h.in" "${PROJECT_BINARY_DIR}/src/mongocrypt-config.h" ) # Define the mlib target, which is private and header-only. It is not exported # nor are its headers installed. add_library (_mongo-mlib INTERFACE) add_library (mongo::mlib ALIAS _mongo-mlib) list (APPEND MLIB_DEFINITIONS MLIB_USER) CHECK_INCLUDE_FILE (strings.h HAVE_STRINGS_H) if (HAVE_STRINGS_H) list (APPEND MLIB_DEFINITIONS MLIB_HAVE_STRINGS_H) endif () set_property( TARGET _mongo-mlib APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS ${MLIB_DEFINITIONS} ) set_property( TARGET _mongo-mlib APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$" ) # kms-message add_subdirectory (kms-message) # Define mongocrypt library add_library (mongocrypt SHARED ${MONGOCRYPT_SOURCES}) target_include_directories ( mongocrypt PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/kms-message/src" "${CMAKE_CURRENT_SOURCE_DIR}/src" PUBLIC "$" ) target_link_libraries ( mongocrypt PRIVATE _mongocrypt::libbson_for_shared kms_message_static $ PUBLIC mongocrypt::platform ${maybe_dfp_library} ) if (NOT USE_SHARED_LIBBSON) if (APPLE) message ("compiling with unexported symbols list to hide bson symbols") set_target_properties (mongocrypt PROPERTIES LINK_FLAGS "-Wl,-unexported_symbols_list,\"${CMAKE_CURRENT_SOURCE_DIR}/cmake/libmongocrypt-hidden-symbols.txt\"") elseif (UNIX) message ("compiling with version map to version and hide bson symbols") set_target_properties (mongocrypt PROPERTIES LINK_FLAGS "-Wl,--version-script=\"${CMAKE_CURRENT_SOURCE_DIR}/cmake/libmongocrypt-hidden-symbols.map\"") endif () endif () if (NOT WIN32 AND CMAKE_VERSION VERSION_GREATER 3.25) # Do not enable conversion warnings with older cmake. Older cmake does not support # including headers as system headers when the headers are added to the project via # the add_subdirectory() CMake command. libbson produces conversion warnings and is # included in ImportBSON.cmake. target_compile_options (mongocrypt PRIVATE -Wconversion -Wsign-conversion) target_compile_options (kms_message_static PRIVATE -Wconversion -Wsign-conversion) endif () generate_export_header (mongocrypt EXPORT_FILE_NAME src/mongocrypt-export.h BASE_NAME mongocrypt ) add_library (mongocrypt_static STATIC ${MONGOCRYPT_SOURCES}) # Checking CMAKE_C_FLAGS for -fPIC is not a foolproof way of checking whether # -fPIC was set as a compiler flag. However, users were instructed before to # pass -fPIC through CMAKE_C_FLAGS. This will prevent redundant output in # the common case that users are setting -DCMAKE_C_FLAGS='-fPIC' string (FIND "${CMAKE_C_FLAGS}" "-fPIC" FPIC_LOCATION) if (NOT WIN32 AND ENABLE_PIC AND "${FPIC_LOCATION}" EQUAL "-1") target_compile_options (mongocrypt_static PUBLIC -fPIC) message ("Adding -fPIC to compilation of mongocrypt_static components") endif () target_include_directories ( mongocrypt_static PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/kms-message/src" "${CMAKE_CURRENT_SOURCE_DIR}/src" PUBLIC "$" ) target_compile_definitions ( mongocrypt_static PUBLIC MONGOCRYPT_STATIC_DEFINE KMS_MSG_STATIC ) target_link_libraries ( mongocrypt_static PRIVATE _mongocrypt::libbson_for_static kms_message_static $ PUBLIC mongocrypt::platform ${maybe_dfp_library} ) set (PKG_CONFIG_STATIC_LIBS "\${prefix}/${CMAKE_INSTALL_LIBDIR}/libmongocrypt-static.a") set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} ${CMAKE_THREAD_LIBS_INIT}") if (CMAKE_DL_LIBS) string (APPEND PKG_CONFIG_STATIC_LIBS " -l${CMAKE_DL_LIBS}") endif () set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} \${prefix}/${CMAKE_INSTALL_LIBDIR}/libkms_message-static.a") if (ENABLE_BUILD_FOR_PPA) set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} \${prefix}/${CMAKE_INSTALL_LIBDIR}/libbson-static-for-libmongocrypt.a") #librt needed for libbson on linux for clock_gettime find_library (RT_LIBRARY rt) if (RT_LIBRARY) set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} ${RT_LIBRARY}") endif () set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} -pthread") endif () if (MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM" AND MONGOCRYPT_ENABLE_DECIMAL128) get_property (SYSTEM_DFP_LOC TARGET intel_dfp PROPERTY IMPORTED_LOCATION) set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} ${SYSTEM_DFP_LOC}") endif () if (MONGOCRYPT_CRYPTO STREQUAL CommonCrypto) target_link_libraries (mongocrypt PRIVATE "-framework CoreFoundation -framework Security") target_link_libraries (mongocrypt_static PRIVATE "-framework CoreFoundation -framework Security") set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} -framework CoreFoundation -framework Security") elseif (MONGOCRYPT_CRYPTO STREQUAL CNG) target_link_libraries (mongocrypt PRIVATE "bcrypt") target_link_libraries (mongocrypt_static PRIVATE "bcrypt") set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} -lbcrypt") elseif (MONGOCRYPT_CRYPTO STREQUAL OpenSSL) target_link_libraries (mongocrypt PRIVATE OpenSSL::SSL OpenSSL::Crypto) target_link_libraries (mongocrypt_static PRIVATE OpenSSL::SSL OpenSSL::Crypto) set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} -lssl -lcrypto") endif () # Link to libm for math functions (pow, log, etc.) # Do not link on Apple. On macOS Big Sur, libm resolves to the SDK's tbd file, like: # /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/libm.tbd # Not all consumers can easily link to a tbd file (notably golang will reject a tbd suffix by default) # macOS includes libm as part of libSystem (along with libc). # It does not need to be explicitly linked. if (NOT APPLE) find_library (M_LIBRARY m) if (M_LIBRARY) set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} -lm") endif () endif () set_target_properties (mongocrypt PROPERTIES SOVERSION 0 VERSION "0.0.0" OUTPUT_NAME "mongocrypt" ) set_target_properties (mongocrypt_static PROPERTIES SOVERSION 0 VERSION "0.0.0" OUTPUT_NAME "mongocrypt-static" ) if (BUILD_TESTING) # Use C++ in the testing DLL to ensure we can load a library with the C++ runtime enable_language (CXX) add_library (test-dll MODULE test/test-dll.cpp) set_target_properties (test-dll PROPERTIES SUFFIX ".dll" PREFIX "" ) # Create two stubbed crypt_shared libraries add_library (stubbed-crypt_shared SHARED test/crypt_shared-stub.cpp) add_library (stubbed-crypt_shared-2 SHARED test/crypt_shared-stub.cpp) set_target_properties(stubbed-crypt_shared stubbed-crypt_shared-2 PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/src" LINK_LIBRARIES _mongocrypt::libbson_for_static COMPILE_FEATURES cxx_std_11 PREFIX "" ) set_target_properties(stubbed-crypt_shared-2 PROPERTIES SUFFIX ".dll") if (MONGOCRYPT_TESTING_CRYPT_SHARED_FILE) # Generate a target that copies the CSFLE library into the binary directory of test-mongocrypt set (stamp "${CMAKE_CURRENT_BINARY_DIR}/mongo_crypt_v1.copied.$.stamp") add_custom_command ( OUTPUT "${stamp}" COMMAND "${CMAKE_COMMAND}" -E copy "${MONGOCRYPT_TESTING_CRYPT_SHARED_FILE}" "$/mongo_crypt_v1${CMAKE_SHARED_LIBRARY_SUFFIX}" COMMAND "${CMAKE_COMMAND}" -E touch "${stamp}" DEPENDS "${MONGOCRYPT_TESTING_CRYPT_SHARED_FILE}" COMMENT "Getting mongo_crypt library" ) add_custom_target (copy-crypt_shared ALL DEPENDS "${stamp}") else () # The first stubbed crypt_shared library will take the place of the actual crypt_shared for testing message (STATUS "Generating a stubbed crypt_shared dynamic library for use in testing.") message (STATUS "Provide a MONGOCRYPT_TESTING_CRYPT_SHARED_FILE= to provide a crypt_shared for use in testing") set_target_properties (stubbed-crypt_shared PROPERTIES # Normalize the output name expected by libmongocrypt OUTPUT_NAME "mongo_crypt_v1" ) endif () endif () set (TEST_MONGOCRYPT_SOURCES test/test-gcp-auth.c test/test-mc-efc.c test/test-mc-fle2-find-equality-payload-v2.c test/test-mc-fle2-find-range-payload-v2.c test/test-mc-fle2-payload-iev.c test/test-mc-fle2-payload-iev-v2.c test/test-mc-fle2-payload-iup.c test/test-mc-fle2-payload-iup-v2.c test/test-mc-fle2-payload-uev.c test/test-mc-fle2-payload-uev-v2.c test/test-mc-fle2-rfds.c test/test-mc-range-edge-generation.c test/test-mc-range-mincover.c test/test-mc-rangeopts.c test/test-mc-reader.c test/test-mc-tokens.c test/test-mc-range-encoding.c test/test-mc-writer.c test/test-mongocrypt-assert-match-bson.c test/test-mongocrypt-buffer.c test/test-mongocrypt-cache.c test/test-mongocrypt-cache-oauth.c test/test-mongocrypt-ciphertext.c test/test-mongocrypt-compact.c test/test-mongocrypt-crypto.c test/test-mongocrypt-crypto-hooks.c test/test-mongocrypt-crypto-std-hooks.c test/test-mongocrypt-csfle-lib.c test/test-mongocrypt-ctx-decrypt.c test/test-mongocrypt-ctx-encrypt.c test/test-mongocrypt-ctx-rewrap-many-datakey.c test/test-mongocrypt-ctx-setopt.c test/test-mongocrypt-datakey.c test/test-mongocrypt-dll.c test/test-mongocrypt-endpoint.c test/test-mongocrypt-kek.c test/test-mongocrypt-key.c test/test-mongocrypt-key-broker.c test/test-mongocrypt-key-cache.c test/test-mongocrypt-kms-ctx.c test/test-mongocrypt-kms-responses.c test/test-mongocrypt-local-kms.c test/test-mongocrypt-log.c test/test-mongocrypt-marking.c test/test-mongocrypt-status.c test/test-mongocrypt-traverse-util.c test/test-mongocrypt-util.c test/test-mongocrypt.c ) # Define test-mongocrypt add_executable (test-mongocrypt ${TEST_MONGOCRYPT_SOURCES}) # Use the static version since it allows the test binary to use private symbols target_include_directories (test-mongocrypt PRIVATE ./src "${CMAKE_CURRENT_SOURCE_DIR}/kms-message/src") target_link_libraries (test-mongocrypt PRIVATE _mongocrypt::libbson_for_static mongocrypt_static mongo::mlib) target_include_directories (test-mongocrypt PRIVATE "${CMAKE_CURRENT_LIST_DIR}/test") target_compile_definitions (test-mongocrypt PRIVATE # Set a definition so that testcases can know where test-mongocrypt.exe was written to "TEST_MONGOCRYPT_OUTPUT_PATH=\"$\"" # Tell test-mongocrypt whether we have a real csfle library for testing TEST_MONGOCRYPT_HAVE_REAL_CRYPT_SHARED_LIB=$ ) add_test ( NAME mongocrypt COMMAND test-mongocrypt WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) foreach (test IN ITEMS path str) add_executable (mlib.${test}.test src/mlib/${test}.test.c) add_test (mlib.${test} mlib.${test}.test) target_link_libraries (mlib.${test}.test PRIVATE mongo::mlib) endforeach () if ("cxx_relaxed_constexpr" IN_LIST CMAKE_CXX_COMPILE_FEATURES) file (GLOB_RECURSE test_files CONFIGURE_DEPENDS src/*.test.cpp) foreach (file IN LISTS test_files) # Compute a nice test name file (RELATIVE_PATH relpath "${CMAKE_CURRENT_LIST_DIR}/src" "${file}") file (TO_CMAKE_PATH "${relpath}" relpath) string (REPLACE "src/" "" relpath "${relpath}") string (REPLACE "/" "." test_name "${relpath}") string (REGEX REPLACE "\\.test\\.cpp$" "" test_name "${test_name}") # Generate a test executable: set (exe_name "${test_name}.test") add_executable ("${exe_name}" "${file}") target_compile_features ("${exe_name}" PRIVATE cxx_relaxed_constexpr) target_link_libraries ("${exe_name}" PRIVATE mongocrypt mongo::mlib ${maybe_dfp_library} _mongocrypt::libbson_for_static ) add_test ("${test_name}" "${exe_name}") endforeach () endif () if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES) add_executable (csfle-markup src/csfle-markup.cpp) target_link_libraries (csfle-markup PRIVATE mongocrypt_static _mongocrypt::libbson_for_static mongo::mlib) target_compile_features (csfle-markup PRIVATE cxx_std_20) endif () # Exclude example-state-machine since it requires native crypto. if (NOT MONGOCRYPT_CRYPTO STREQUAL none) # Define example-state-machine add_executable (example-state-machine test/example-state-machine.c) target_link_libraries (example-state-machine PRIVATE mongocrypt _mongocrypt::libbson_for_shared) target_include_directories (example-state-machine PRIVATE ./src "${CMAKE_CURRENT_SOURCE_DIR}/kms-message/src") add_test ( NAME example-state-machine COMMAND example-state-machine WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" ) # Define example-state-machine-static add_executable (example-state-machine-static test/example-state-machine.c) target_link_libraries (example-state-machine-static PRIVATE mongocrypt_static _mongocrypt::libbson_for_static) target_include_directories (example-state-machine-static PRIVATE ./src) add_test ( NAME example-state-machine-static COMMAND example-state-machine-static WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" ) if (ENABLE_ONLINE_TESTS) message ("compiling utilities") add_executable (csfle test/util/csfle.c test/util/util.c) target_link_libraries (csfle PRIVATE mongocrypt_static) target_include_directories (csfle PRIVATE ${CMAKE_BINARY_DIR}/src) target_include_directories (csfle PRIVATE ./src) target_include_directories (csfle PRIVATE ./kms-message/src) target_link_libraries (csfle PRIVATE _mongocrypt::mongoc) endif () endif () if (ENABLE_STATIC) set (TARGETS_TO_INSTALL mongocrypt mongocrypt_static) else () set (TARGETS_TO_INSTALL mongocrypt) endif () install ( TARGETS ${TARGETS_TO_INSTALL} EXPORT mongocrypt_targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # This export set is not installed, and is only to allow export() of the mlib-using targets install (TARGETS _mongo-mlib EXPORT _exports_for_export) export (EXPORT _exports_for_export) install ( FILES ${MONGOCRYPT_PUBLIC_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/src/mongocrypt-config.h ${CMAKE_CURRENT_BINARY_DIR}/src/mongocrypt-export.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mongocrypt COMPONENT Devel ) set (PROJECT_VERSION "${BUILD_VERSION}") set (PROJECT_DESCRIPTION "The libmongocrypt client-side field level encryption library.") if (NOT ENABLE_BUILD_FOR_PPA) set (PKG_CONFIG_STATIC_REQUIRES "libbson-static-1.0") endif () if (USE_SHARED_LIBBSON) set (PKG_CONFIG_REQUIRES "libbson-1.0") set (PKG_CONFIG_STATIC_REQUIRES "libbson-1.0") endif () set (PKG_CONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}") set (PKG_CONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}/mongocrypt") set (PKG_CONFIG_LIBS "-L\${libdir} -lmongocrypt") if (ENABLE_BUILD_FOR_PPA) set (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} \${prefix}/${CMAKE_INSTALL_LIBDIR}/libbson-static-for-libmongocrypt.a") #librt needed for libbson on linux for clock_gettime find_library (RT_LIBRARY rt) if (RT_LIBRARY) set (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} ${RT_LIBRARY}") endif () set (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} -pthread") endif () if (MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM" AND MONGOCRYPT_ENABLE_DECIMAL128) get_property (SYSTEM_DFP_LOC TARGET intel_dfp PROPERTY IMPORTED_LOCATION) set (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} ${SYSTEM_DFP_LOC}") endif () set (PKG_CONFIG_CFLAGS "-I\${includedir}") set (PKG_CONFIG_STATIC_CFLAGS "${PKG_CONFIG_CFLAGS} -DMONGOCRYPT_STATIC_DEFINE -DKMS_MSG_STATIC") configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/libmongocrypt.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libmongocrypt.pc" ) configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/libmongocrypt-static.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libmongocrypt-static.pc" ) install ( FILES "${CMAKE_BINARY_DIR}/libmongocrypt.pc" DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) if (ENABLE_STATIC) install ( FILES "${CMAKE_BINARY_DIR}/libmongocrypt-static.pc" DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) endif () include (CMakePackageConfigHelpers) set (INCLUDE_INSTALL_DIRS "${CMAKE_INSTALL_INCLUDEDIR}/mongocrypt") set (LIBRARY_INSTALL_DIRS ${CMAKE_INSTALL_LIBDIR}) write_basic_package_version_file ( "${CMAKE_CURRENT_BINARY_DIR}/mongocrypt/mongocrypt-config-version.cmake" COMPATIBILITY AnyNewerVersion ) configure_file (cmake/mongocrypt-config.cmake "${CMAKE_CURRENT_BINARY_DIR}/mongocrypt/mongocrypt-config.cmake" @ONLY ) install (EXPORT mongocrypt_targets NAMESPACE mongo:: FILE mongocrypt_targets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mongocrypt ) install ( FILES "${CMAKE_CURRENT_BINARY_DIR}/mongocrypt/mongocrypt-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/mongocrypt/mongocrypt-config-version.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mongocrypt COMPONENT Devel ) libmongocrypt-1.8.4/CODEOWNERS000066400000000000000000000004671454530651600160270ustar00rootroot00000000000000# Code Owners will automatically be added as reviewers on PRs # NodeJS Bindings bindings/node @nbbeeken @durran @baileympearson @dariakp @addaleax # Python Bindings bindings/python @ShaneHarvey @blink1073 @juliusgeo # Java Bindings bindings/java @jyemin @rozza # CSharp Bindings bindings/cs @DmitryLukyanov libmongocrypt-1.8.4/Earthfile000066400000000000000000000311771454530651600162640ustar00rootroot00000000000000# Earthly Intro: https://docs.earthly.dev/ # Earthfile Reference: https://docs.earthly.dev/docs/earthfile # Quick notes: # • The shell script at ".evergreen/earthly.sh" can be used to automatically # download and use a fixed version of Earthly that is compatible with # this file version. Execute the shell script as if it were the Earthly # executable itself. # • In this file, the convention is to copy the source tree into /s/libmongocrypt # • Earthly copies the "build context" (working directory) into the local buildkit # daemon before each build execution. (Similar to the Docker build context). # If you have a large amount of data in the working directory, this could be # slow. The ".earthlyignore" file specifies patterns of files and directories # to exclude from the context upload. Modify it to suite your needs, if necessary. # • Only a subset of the source tree is COPY'd into the build environment. Files # outside of this set will not be available in the build. See the COPY_SOURCE # command for the list. # • Modification at any layer will invalidate caching on all subsequent build # layers. This is important and by-design in Earthly. Push infrequently-modified # operations to earlier in the process the pipeline to make better use of # the cache. # # This file has a few major sections: # - Setup COMMANDs # - Utility COMMANDs # - Environment targets # - Build/test/CI targets # # All environment targets begin with "env.". All build targets (should) accept an "env" # parameter that specifies the name of the environment to use for the task. The name # of an environment is specified following the "env." prefix. For example, the # Ubuntu 22.04 environment is named "u22", so its environment target is "env.u22", # and can be used i.e. "earthly +build --env=u22" # # The following environment are defined in this file: # • u22 - Ubuntu 22.04 # • u20 - Ubuntu 20.04 # • u18 - Ubuntu 18.04 # • u16 - Ubuntu 16.04 # • u14 - Ubuntu 14.04 # • rl8 - RockyLinux 8 - Stand-in for RHEL 8 # • c7 - CentOS 7 - Stand-in for RHEL 7 # • c6 - CentOS 6 - Stand-in for RHEL 6 # • amzn1 - AmazonLinux (2018.03) # • amzn2 - AmazonLinux 2 # • deb9 - Debian 9.2 # • deb10 - Debian 10.0 # • deb11 - Debian 11.0 # • sles15 - OpenSUSE Leap 15.0 # • alpine - Alpine Linux 3.18 # # When adding new environments, always pull from a fully-qualified image ID: # • DO NOT: "ubuntu" # • DO NOT: "ubuntu:latest" # • DO NOT: "ubuntu:22.10" # • DO: "docker.io/library/ubuntu:22.10" # ### VERSION --use-cache-command 0.6 FROM docker.io/library/alpine:3.16 WORKDIR /s init: # Special initializing target that sets up the base image and adds the "__install" # script. This scripts abstracts around the underlying package manager interface # to "do the right thing" when you want to install packages. Package names will # still need to be spelled correctly for the respective system. # # Invoke +init with a "--base" parameter that specifies the base image to pull ARG --required base FROM $base COPY etc/install-package.sh /usr/local/bin/__install RUN chmod +x /usr/local/bin/__install ENV USER_CACHES_DIR=/Cache # Environment setup commands below. Each provides the basic environment for a # libmongocrypt build. Additional packages and setup may be required for # individual tasks. DEBIAN_SETUP: # Setup for a debian-like build environment. Used for both Debian and Ubuntu COMMAND RUN __install build-essential g++ libssl-dev curl unzip python3 pkg-config \ git ccache findutils ca-certificates REDHAT_SETUP: # Setup for a redhat-like build environment. Used for CentOS and RockyLinux. COMMAND RUN __install epel-release && \ __install gcc-c++ make openssl-devel curl unzip git ccache findutils \ patch CENTOS6_SETUP: # Special setup for CentOS6: The packages have been moved to the vault, so # we need to enable the vault repos before we perform any __installs COMMAND RUN rm /etc/yum.repos.d/*.repo COPY etc/c6-vault.repo /etc/yum.repos.d/CentOS-Base.repo DO +REDHAT_SETUP AMZ_SETUP: # Setup for Amazon Linux. COMMAND # amzn1 has "python38", but amzn2 has "python3." Try both RUN __install python3 || __install python38 RUN __install gcc-c++ make openssl-devel curl unzip tar gzip \ openssh-clients patch git SLES_SETUP: # Setup for a SLES/SUSE build environment COMMAND RUN __install gcc-c++ make libopenssl-devel curl unzip tar gzip python3 \ patch git xz which ALPINE_SETUP: # Setup for an Alpine Linux build environment COMMAND RUN __install make bash gcc g++ unzip curl tar gzip git musl-dev \ linux-headers openssl-dev python3 # Environment targets are defined below. These do not have build outputs, but # are rather themselves the "outputs" to be used as the environment for subsequent # tasks env.c6: # A CentOS 6 environment. FROM +init --base=docker.io/library/centos:6 DO +CENTOS6_SETUP env.c7: # A CentOS 7 environment. FROM +init --base=docker.io/library/centos:7 DO +REDHAT_SETUP env.rl8: # CentOS 8 is cancelled. Use RockyLinux 8 for our RHEL 8 environment. FROM +init --base=docker.io/library/rockylinux:8 DO +REDHAT_SETUP # Utility command for Ubuntu environments ENV_UBUNTU: COMMAND ARG --required version FROM +init --base=docker.io/library/ubuntu:$version DO +DEBIAN_SETUP env.u14: # An Ubuntu 14.04 environment DO +ENV_UBUNTU --version 14.04 env.u16: # An Ubuntu 16.04 environment DO +ENV_UBUNTU --version 16.04 env.u18: # An Ubuntu 18.04 environment DO +ENV_UBUNTU --version 18.04 env.u20: # An Ubuntu 20.04 environment DO +ENV_UBUNTU --version 20.04 env.u22: # An Ubuntu 22.04 environment DO +ENV_UBUNTU --version 22.04 env.amzn1: # An Amazon "1" environment. (AmazonLinux 2018) FROM +init --base=docker.io/library/amazonlinux:2018.03 DO +AMZ_SETUP env.amzn2: # An AmazonLinux 2 environment FROM +init --base=docker.io/library/amazonlinux:2 DO +AMZ_SETUP # Utility command for Debian setup ENV_DEBIAN: COMMAND ARG --required version FROM +init --base=docker.io/library/debian:$version DO +DEBIAN_SETUP env.deb9: # A Debian 9.2 environment DO +ENV_DEBIAN --version 9.2 env.deb10: # A Debian 10.0 environment DO +ENV_DEBIAN --version 10.0 env.deb-unstable: DO +ENV_DEBIAN --version=unstable env.deb11: # A Debian 11.0 environment DO +ENV_DEBIAN --version 11.0 env.sles15: # An OpenSUSE Leap 15.0 environment. FROM +init --base=docker.io/opensuse/leap:15.0 DO +SLES_SETUP env.alpine: FROM +init --base=docker.io/library/alpine:3.17 DO +ALPINE_SETUP # Utility: Warm-up obtaining CMake and Ninja for the build. This is usually # very quick, but on some platforms we need to compile them from source. CACHE_WARMUP: COMMAND # Copy only the scripts that are strictly necessary for the operation, to # avoid cache invalidation later on. COPY .evergreen/setup-env.sh \ .evergreen/init.sh \ .evergreen/ensure-cmake.sh \ .evergreen/ensure-ninja.sh \ /T/ RUN bash /T/ensure-cmake.sh RUN env NINJA_EXE=/usr/local/bin/ninja \ bash /T/ensure-ninja.sh COPY_SOURCE: COMMAND COPY --dir \ .git/ \ cmake/ \ kms-message/ \ test/ \ debian/ \ src/ \ doc/ \ etc/ \ LICENSE \ .evergreen/ \ third-party/ \ CMakeLists.txt \ "/s/libmongocrypt" COPY --dir bindings/cs/ "/s/libmongocrypt/bindings/" BUILD_EXAMPLE_STATE_MACHINE: COMMAND COPY test/example-state-machine.c /s/ RUN pkg-config --exists libmongocrypt --print-errors && \ gcc /s/example-state-machine.c \ -o /s/example-state-machine \ $(pkg-config --cflags --libs libmongocrypt) COPY --dir test/example /s/test/example RUN cd /s && /s/example-state-machine rpm-build: FROM +init --base fedora:38 GIT CLONE https://src.fedoraproject.org/rpms/libmongocrypt.git /R # Install the packages listed by "BuildRequires" and rpm-build: RUN __install $(awk '/^BuildRequires:/ { print $2 }' /R/libmongocrypt.spec) \ rpm-build DO +COPY_SOURCE RUN cp -r /s/libmongocrypt/. /R RUN awk -f /R/etc/rpm/tweak.awk < /R/libmongocrypt.spec > /R/libmongocrypt.2.spec RUN rpmbuild -ba /R/libmongocrypt.2.spec \ -D "_topdir /X" \ -D "_sourcedir /R" SAVE ARTIFACT /X/RPMS / SAVE ARTIFACT /X/SRPMS / rpm-install-runtime: # Install the runtime RPM FROM +init --base fedora:38 COPY +rpm-build/RPMS /tmp/libmongocrypt-rpm/ RUN dnf makecache RUN __install $(find /tmp/libmongocrypt-rpm/ -name 'libmongocrypt-1.*.rpm') rpm-install-dev: # Install the development RPM FROM +rpm-install-runtime COPY +rpm-build/RPMS /tmp/libmongocrypt-rpm/ RUN dnf makecache RUN __install $(find /tmp/libmongocrypt-rpm/ -name 'libmongocrypt-devel-*.rpm') rpm-devel-test: # Attempt to build a small app using pkg-config and the dev RPM FROM +rpm-install-dev RUN __install gcc DO +BUILD_EXAMPLE_STATE_MACHINE SAVE ARTIFACT /s/example-state-machine / rpm-runtime-test: # Attempt to run a libmongocrypt-using app with the runtime RPM installed FROM +rpm-install-runtime COPY +rpm-devel-test/example-state-machine /s/ COPY --dir test/example /s/test/example RUN cd /s/ && /s/example-state-machine # A target to build the debian package. Options: # • --env=[...] (default: deb-unstable) # · Set the environment for the build. Affects which packages are available # for build dependencies. # NOTE: Uncommited local changes will be ignored and not affect the result! deb-build: ARG env=deb-unstable FROM +env.$env RUN __install git-buildpackage fakeroot debhelper cmake libbson-dev \ libintelrdfpmath-dev DO +COPY_SOURCE WORKDIR /s/libmongocrypt RUN git clean -fdx && git reset --hard RUN python3 etc/calc_release_version.py > VERSION_CURRENT RUN git add -f VERSION_CURRENT && \ git -c user.name=anon -c user.email=anon@localhost \ commit VERSION_CURRENT -m 'Set version' && \ env LANG=C bash debian/build_snapshot.sh && \ debc ../*.changes && \ dpkg -i ../*.deb SAVE ARTIFACT /s/*.deb /debs/ deb-install-runtime: # Install the runtime deb package FROM +init --base=docker.io/library/debian:unstable COPY +deb-build/debs/libmongocrypt0*.deb /tmp/lmc.deb RUN __install /tmp/lmc.deb deb-install-dev: # Install the development deb package FROM +deb-install-runtime COPY +deb-build/debs/libmongocrypt-dev*.deb /tmp/lmc-dev.deb RUN __install /tmp/lmc-dev.deb deb-dev-test: # Attempt to build a small app using pkg-config and the dev deb package FROM +deb-install-dev RUN __install pkg-config gcc DO +BUILD_EXAMPLE_STATE_MACHINE SAVE ARTIFACT /s/example-state-machine / deb-runtime-test: # Attempt to run a libmongocrypt-using app with the runtime DEB installed FROM +deb-install-runtime COPY +deb-dev-test/example-state-machine /s/ COPY --dir test/example /s/test/example RUN cd /s/ && /s/example-state-machine packaging-full-test: BUILD +deb-runtime-test BUILD +rpm-runtime-test check-format: FROM python:3.11.2-slim-buster RUN pip install pipx COPY etc/format* /X/etc/ COPY .evergreen/init.sh /X/.evergreen/ RUN /X/etc/format.sh # Does nothing, but warms the cache COPY --dir .clang-format src test /X/ RUN /X/etc/format-all.sh --dry-run -Werror --verbose # The main "build" target. Options: # • --env=[...] (default "u22") # · Set the environment for the build. Any name of and "env." targets # can be used. # • --persist_build={true,false} (default "true") # · Persist the build directory between executions. Enables incremental # compilation and reusing of configuration between builds. The build # directory is NOT shared between different "--env" environments, only # within a single environment. build: ARG env=u22 FROM +env.$env DO +CACHE_WARMUP DO +COPY_SOURCE WORKDIR /s ARG persist_build=true IF $persist_build CACHE /s/libmongocrypt/cmake-build END RUN env USE_NINJA=1 bash libmongocrypt/.evergreen/build_all.sh libmongocrypt-1.8.4/LICENSE000066400000000000000000000261341454530651600154400ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.libmongocrypt-1.8.4/README.md000066400000000000000000000251341454530651600157110ustar00rootroot00000000000000# libmongocrypt # The companion C library for client side encryption in drivers. # Bugs / Feature Requests # If you have encountered a bug, or would like to see a new feature in libmongocrypt, please open a case in our issue management tool, JIRA: - [Create an account and login](https://jira.mongodb.org). - Navigate to [the MONGOCRYPT project](https://jira.mongodb.org/projects/MONGOCRYPT). - Click **Create Issue** - Please provide as much information as possible about the issue type and how to reproduce it. ## Documentation ## See [The Integration Guide](integrating.md) to integrate with your driver. See [mongocrypt.h](src/mongocrypt.h) for the public API reference. The documentation can be rendered into HTML with doxygen. Run `doxygen ./doc/Doxygen`, then open `./doc/html/index.html`. ## Building libmongocrypt ## On Windows and macOS, libmongocrypt can use the platform's default encryption APIs as its encryption backend. On other systems, one will want to install the OpenSSL development libraries, which libmongocrypt will use as the default encryption backend. Then build libmongocrypt: ``` git clone https://github.com/mongodb/libmongocrypt cd libmongocrypt mkdir cmake-build && cd cmake-build cmake ../ make ``` This builds libmongocrypt.dylib and test-libmongocrypt, in the cmake-build directory. ## Installing libmongocrypt on macOS ## Install the latest release of libmongocrypt with the following. ``` brew install mongodb/brew/libmongocrypt ``` To install the latest unstable development version of libmongocrypt, use `brew install mongodb/brew/libmongocrypt --HEAD`. Do not use the unstable version of libmongocrypt in a production environment. ## Building libmongocrypt from source on macOS ## First install [Homebrew according to its own instructions](https://brew.sh/). Install the XCode Command Line Tools: ``` xcode-select --install ``` Then clone and build libmongocrypt: ``` git clone https://github.com/mongodb/libmongocrypt.git cd libmongocrypt cmake . cmake --build . --target install ``` Then, libmongocrypt can be used with pkg-config: ``` pkg-config libmongocrypt --libs --cflags ``` Or use cmake's `find_package`: ``` find_package (mongocrypt) # Then link against mongo::mongocrypt ``` ## Installing libmongocrypt on Windows ## For Windows, there is a fixed URL to download the DLL and includes directory: https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt.tar.gz To download the latest unstable release, download from this URL: https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt_unstable.tar.gz Do not use the unstable version of libmongocrypt in a production environment. ### Testing ### `test-mongocrypt` mocks all I/O with files stored in the `test/data` and `test/example` directories. Run `test-mongocrypt` from the source directory: ``` cd libmongocrypt ./cmake-build/test-mongocrypt ``` libmongocrypt is continuously built and published on evergreen. Submit patch builds to this evergreen project when making changes to test on supported platforms. The latest tarball containing libmongocrypt built on all supported variants is [published here](https://s3.amazonaws.com/mciuploads/libmongocrypt/all/master/latest/libmongocrypt-all.tar.gz). ### Troubleshooting ### If OpenSSL is installed in a non-default directory, pass `-DOPENSSL_ROOT_DIR=/path/to/openssl` to the cmake command for libmongocrypt. If there are errors with cmake configuration, send the set of steps you performed to the maintainers of this project. If there are compilation or linker errors, run `make` again, setting `VERBOSE=1` in the environment or on the command line (which shows exact compile and link commands), and send the output to the maintainers of this project. ### Design Principles ### The design of libmongocrypt adheres to these principles. #### Easy to integrate #### The main reason behind creating a C library is to make it easier for drivers to support FLE. Some consequences of this principle: the API is minimal, structs are opaque, and global initialization is lazy. #### Lightweight #### We decided against the "have libmongocrypt do everything" approach because it complicated integration, especially with async drivers. Because of this we decided no I/O occurs in libmongocrypt. ### Releasing ### #### Version number scheme #### Version numbers of libmongocrypt must follow the format 1.[0-9].[0-9] for releases and 1.[0-9].[0-9]-(alpha|beta|rc)[0-9] for pre-releases. This ensures that Linux distribution packages built from each commit are published to the correct location. #### Steps to release #### Do the following when releasing: - Update CHANGELOG.md with the version being released. - If this is a new minor release (e.g. `x.y.0`): - Update the Linux distribution package installation instructions in the below sections to refer to the new version x.y. - Commit these changes (on `master`) so that both the `master` branch and the new branch you are about to create refer to the new branch (note that this means you will commit changes to this file, and `CHANGELOG.md`) - Create a branch named `rx.y`. - Update the [libmongocrypt-release](https://evergreen.mongodb.com/projects##libmongocrypt-release) Evergreen project (requires auth) to set `Branch Name` to `rx.y`. - Commit, create a new git tag, like `1.0.0-rc123` or `1.0.0`, and push. - Push both the branch ref and tag ref in the same command: `git push origin master 1.0.0-rc123` or `git push origin r1.0 1.0.0` - Pushing the branch ref and the tag ref in the same command eliminates the possibility of a race condition in Evergreen (for building resources based on the presence of a release tag) - Note that in the future (e.g., if we move to a PR-based workflow for releases, or if we simply want to take better advantage of advanced Evergreen features), it is possible to use Evergreen's "Trigger Versions With Git Tags" feature by updating both `config.yml` and the project's settings in Evergreen - Ensure the version on Evergreen with the tagged commit is scheduled. The following tasks must pass to complete the release: - `upload-all` - `windows-upload`. It is scheduled from the `windows-upload-check` task. - Create the release from the GitHub releases page from the new tag. - Submit a PR to update the Homebrew package https://github.com/mongodb/homebrew-brew/blob/master/Formula/libmongocrypt.rb. ([Example](https://github.com/mongodb/homebrew-brew/pull/135)). - If this is a new minor release (e.g. `x.y.0`), file a DOCSP ticket to update the installation instructions on [Install libmongocrypt](https://www.mongodb.com/docs/manual/core/csfle/reference/libmongocrypt/). ([Example](https://jira.mongodb.org/browse/DOCSP-26877)) - Update the release on the [Jira releases page](https://jira.mongodb.org/projects/MONGOCRYPT/versions). ## Installing libmongocrypt From Distribution Packages ## Distribution packages (i.e., .deb/.rpm) are built and published for several Linux distributions. The installation of these packages for supported platforms is documented here. ### Unstable Development Distribution Packages ### To install the latest unstable development package, change `1.8` to `development` in the package URLs listed in the subsequent instructions. For example, `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.8` in the instructions would become `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/development`. Do not use the unstable version of libmongocrypt in a production environment. ### .deb Packages (Debian and Ubuntu) ### First, import the public key used to sign the package repositories: ``` sudo sh -c 'curl -s --location https://www.mongodb.org/static/pgp/libmongocrypt.asc | gpg --dearmor >/etc/apt/trusted.gpg.d/libmongocrypt.gpg' ``` Second, create a list entry for the repository. For Ubuntu systems (be sure to change `` to `xenial`, `bionic`, `focal`, or `jammy`, as appropriate to your system): ``` echo "deb https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.8 universe" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list ``` For Debian systems (be sure to change `` to `stretch`, `buster`, or `bullseye`, as appropriate to your system): ``` echo "deb https://libmongocrypt.s3.amazonaws.com/apt/debian /libmongocrypt/1.8 main" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list ``` Third, update the package cache: ``` sudo apt-get update ``` Finally, install the libmongocrypt packages: ``` sudo apt-get install -y libmongocrypt-dev ``` ### .rpm Packages (RedHat, Suse, and Amazon) ### #### RedHat Enterprise Linux #### Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository baseurl=https://libmongocrypt.s3.amazonaws.com/yum/redhat/$releasever/libmongocrypt/1.8/x86_64 gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/libmongocrypt.asc ``` Then install the libmongocrypt packages: ``` sudo yum install -y libmongocrypt ``` #### Amazon Linux 2023 #### Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2023/libmongocrypt/1.8/x86_64 gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/libmongocrypt.asc ``` Then install the libmongocrypt packages: ``` sudo yum install -y libmongocrypt ``` #### Amazon Linux 2 #### Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2/libmongocrypt/1.8/x86_64 gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/libmongocrypt.asc ``` Then install the libmongocrypt packages: ``` sudo yum install -y libmongocrypt ``` #### Amazon Linux #### Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2013.03/libmongocrypt/1.8/x86_64 gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/libmongocrypt.asc ``` Then install the libmongocrypt packages: ``` sudo yum install -y libmongocrypt ``` #### Suse #### First, import the public key used to sign the package repositories: ``` sudo rpm --import https://www.mongodb.org/static/pgp/libmongocrypt.asc ``` Second, add the repository (be sure to change `` to `12` or `15`, as appropriate to your system): ``` sudo zypper addrepo --gpgcheck "https://libmongocrypt.s3.amazonaws.com/zypper/suse//libmongocrypt/1.8/x86_64" libmongocrypt ``` Finally, install the libmongocrypt packages: ``` sudo zypper -n install libmongocrypt ``` libmongocrypt-1.8.4/bindings/000077500000000000000000000000001454530651600162225ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/000077500000000000000000000000001454530651600166275ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/.gitignore000066400000000000000000000001471454530651600206210ustar00rootroot00000000000000# C# binary directories bin/ obj/ # Rider settings .idea/ # VS settings .vs/ # Other /Scripts/Tools libmongocrypt-1.8.4/bindings/cs/CMakeLists.txt000066400000000000000000000021501454530651600213650ustar00rootroot00000000000000 configure_file(cs.sln cs.sln COPYONLY) configure_file(MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj COPYONLY) configure_file(MongoDB.Libmongocrypt/Package.include.template.csproj MongoDB.Libmongocrypt/Package.csproj.include) configure_file(MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj COPYONLY) configure_file(MongoDB.Libmongocrypt.Test/Package.include.template.csproj MongoDB.Libmongocrypt.Test/Package.csproj.include) configure_file(MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj COPYONLY) configure_file(MongoDB.Libmongocrypt.Test/Package.include.template.csproj MongoDB.Libmongocrypt.Test32/Package.csproj.include) configure_file(MongoDB.Libmongocrypt.Example/MongoDB.Libmongocrypt.Example.csproj MongoDB.Libmongocrypt.Example/MongoDB.Libmongocrypt.Example.csproj COPYONLY) configure_file(MongoDB.Libmongocrypt.Example/Package.include.template.csproj MongoDB.Libmongocrypt.Example/Package.csproj.include) libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Example/000077500000000000000000000000001454530651600243355ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Example/MongoDB.Libmongocrypt.Example.csproj000066400000000000000000000013771454530651600332750ustar00rootroot00000000000000 Exe net472;netcoreapp2.1 net472;netcoreapp2.1 netcoreapp2.1 AnyCPU false libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Example/Package.include.template.csproj000066400000000000000000000004741454530651600323530ustar00rootroot00000000000000 false @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt.Example libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Example/Program.cs000066400000000000000000000402051454530651600262740ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using MongoDB.Bson; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; using MongoDB.Libmongocrypt; using MongoDB.Driver; using System; using System.IO; using System.Net.Security; using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; namespace drivertest { class BsonUtil { public static BsonDocument ToDocument(Binary bin) { MemoryStream stream = new MemoryStream(bin.ToArray()); using (var jsonReader = new BsonBinaryReader(stream)) { var context = BsonDeserializationContext.CreateRoot(jsonReader); return BsonDocumentSerializer.Instance.Deserialize(context); } } public static byte[] ToBytes(BsonDocument doc) { BsonBinaryWriterSettings settings = new BsonBinaryWriterSettings() { // C# driver "magically" changes UUIDs underneath by default so tell it not to GuidRepresentation = GuidRepresentation.Standard }; return doc.ToBson(null, settings); } public static BsonDocument Concat(BsonDocument doc1, BsonDocument doc2) { BsonDocument dest = new BsonDocument(); BsonDocumentWriter writer = new BsonDocumentWriter(dest); var context = BsonSerializationContext.CreateRoot(writer); writer.WriteStartDocument(); foreach (var field in doc1) { writer.WriteName(field.Name); BsonValueSerializer.Instance.Serialize(context, field.Value); } foreach (var field in doc2) { writer.WriteName(field.Name); BsonValueSerializer.Instance.Serialize(context, field.Value); } writer.WriteEndDocument(); return writer.Document; } public static BsonDocument FromJSON(string str) { using (var jsonReader = new JsonReader(str)) { var context = BsonDeserializationContext.CreateRoot(jsonReader); return BsonDocumentSerializer.Instance.Deserialize(context); } } } class MongoCryptDController { MongoClient _clientCryptD; IMongoCollection _keyVault; Uri _kmsEndpoint; public MongoCryptDController(MongoUrl urlCryptD, IMongoCollection keyVault, Uri kmsEndpoint) { _clientCryptD = new MongoClient(urlCryptD); _keyVault = keyVault; _kmsEndpoint = kmsEndpoint; } public Guid GenerateKey(KmsCredentials credentials, KmsKeyId kmsKeyId) { var options = new CryptOptions(new[] { credentials }); BsonDocument key = null; using (var cryptClient = CryptClientFactory.Create(options)) using (var context = cryptClient.StartCreateDataKeyContext(kmsKeyId)) { key = ProcessState(context, _keyVault.Database, null); } _keyVault.InsertOne(key); Guid g = key["_id"].AsGuid; return g; } public BsonDocument EncryptCommand(KmsCredentials credentials, IMongoCollection coll, BsonDocument cmd) { var options = new CryptOptions(new[] { credentials }); using (var cryptClient = CryptClientFactory.Create(options)) using (var context = cryptClient.StartEncryptionContext(coll.Database.DatabaseNamespace.DatabaseName, command: BsonUtil.ToBytes(cmd))) { return ProcessState(context, coll.Database, cmd); } } public BsonDocument DecryptCommand(KmsCredentials credentials, IMongoDatabase db, BsonDocument doc) { var options = new CryptOptions(new[] { credentials }); using (var cryptClient = CryptClientFactory.Create(options)) using (var context = cryptClient.StartDecryptionContext(BsonUtil.ToBytes(doc))) { return ProcessState(context, db, null); } } public static bool ValidateServerCertificate( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (sslPolicyErrors == SslPolicyErrors.None) return true; Console.WriteLine("Certificate error: {0}", sslPolicyErrors); // Ignore certificate errors when testing against localhost return true; } void DoKmsRequest(KmsRequest request) { TcpClient tcpClient = new TcpClient(); Console.WriteLine("KMS: " + request.Endpoint); // change me to use the mock if (_kmsEndpoint != null) { tcpClient.Connect(_kmsEndpoint.DnsSafeHost, _kmsEndpoint.Port); } else { tcpClient.Connect(request.Endpoint, 443); } SslStream stream = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate)); stream.AuthenticateAsClient("localhost"); Binary bin = request.Message; stream.Write(bin.ToArray()); byte[] buffer = new byte[4096]; while (request.BytesNeeded > 0) { MemoryStream memBuffer = new MemoryStream(); int read = stream.Read(buffer, 0, buffer.Length); if (read > 0) { memBuffer.Write(buffer, 0, read); } request.Feed(memBuffer.ToArray()); } } private BsonDocument ProcessState(CryptContext context, IMongoDatabase db, BsonDocument cmd) { BsonDocument ret = cmd; while (!context.IsDone) { Console.WriteLine("\n----------------------------------\nState:" + context.State); switch (context.State) { case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: { var binary = context.GetOperation(); var doc = BsonUtil.ToDocument(binary); Console.WriteLine("ListCollections Query: " + doc); ListCollectionsOptions opts = new ListCollectionsOptions() { Filter = new BsonDocumentFilterDefinition(doc) }; var reply = db.ListCollections(opts); var replyDocs = reply.ToList(); Console.WriteLine("ListCollections Reply: " + replyDocs); foreach (var replyDoc in replyDocs) { Console.WriteLine("ListCollections Reply: " + replyDoc); context.Feed(BsonUtil.ToBytes(replyDoc)); } context.MarkDone(); break; } case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: { var binary = context.GetOperation(); var commandWithSchema = BsonUtil.ToDocument(binary); Console.WriteLine("MongoCryptD Query: " + commandWithSchema); var cryptDB = _clientCryptD.GetDatabase(db.DatabaseNamespace.DatabaseName); var reply = cryptDB.RunCommand(new BsonDocumentCommand(commandWithSchema)); Console.WriteLine("MongoCryptD Reply: " + reply); context.Feed(BsonUtil.ToBytes(reply)); context.MarkDone(); break; } case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS: { var binary = context.GetOperation(); Console.WriteLine("Buffer:" + BitConverter.ToString(binary.ToArray())); var doc = BsonUtil.ToDocument(binary); Console.WriteLine("GetKeys Query: " + doc); var reply = _keyVault.Find(new BsonDocumentFilterDefinition(doc)); var replyDocs = reply.ToList(); Console.WriteLine("GetKeys Reply: " + replyDocs); foreach (var replyDoc in replyDocs) { context.Feed(BsonUtil.ToBytes(replyDoc)); } context.MarkDone(); break; } case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS: { var requests = context.GetKmsMessageRequests(); foreach (var req in requests) { DoKmsRequest(req); } requests.MarkDone(); break; } case CryptContext.StateCode.MONGOCRYPT_CTX_READY: { Binary b = context.FinalizeForEncryption(); Console.WriteLine("Buffer:" + BitConverter.ToString(b.ToArray())); ret = BsonUtil.ToDocument(b); break; } case CryptContext.StateCode.MONGOCRYPT_CTX_DONE: { Console.WriteLine("DONE!!"); return ret; } case CryptContext.StateCode.MONGOCRYPT_CTX_ERROR: { throw new NotImplementedException(); } } } return ret; } } class Program { static IMongoCollection SetupKeyStore(MongoClient client) { var dbAdmin = client.GetDatabase("admin"); var collKeyVault = dbAdmin.GetCollection("datakeys"); // Clear the key vault collKeyVault.DeleteMany(new BsonDocumentFilterDefinition(new BsonDocument())); return collKeyVault; } static IMongoCollection SetupTestCollection(MongoClient client, Guid keyID) { var database = client.GetDatabase("test"); // Reset state database.DropCollection("test"); var s = new BsonDocument { { "$jsonSchema" , new BsonDocument { { "type", "object" }, { "properties" , new BsonDocument { { "ssn" , new BsonDocument { { "encrypt" , new BsonDocument { { "keyId" , new BsonArray( new BsonValue[] { keyID } ) }, { "bsonType" , "string"}, { "algorithm" , "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" }, } } } } } } } } }; database.CreateCollection("test", new CreateCollectionOptions() { Validator = new BsonDocumentFilterDefinition(s) }); return database.GetCollection("test"); } static string GetEnvironmenVariabletOrValue(string env, string def) { string value = Environment.GetEnvironmentVariable(env); if (value != null) { return value; } return def; } static void Main(string[] args) { // The C# driver transmutes data unless you specify this stupid line! BsonDefaults.GuidRepresentation = GuidRepresentation.Standard; Console.WriteLine("Using url: " + args); // or change me to use the mock Uri kmsURL = Environment.GetEnvironmentVariable("FLE_AWS_SECRET_ACCESS_KEY") != null ? null : new Uri("https://localhost:8000"); var cryptDUrl = new MongoUrl("mongodb://localhost:27020"); var client = new MongoClient("mongodb://localhost:27017"); IMongoCollection collKeyVault = SetupKeyStore(client); var controller = new MongoCryptDController(cryptDUrl, collKeyVault, kmsURL); var awsKeyId = new KmsKeyId( new BsonDocument { { "provider", "aws" }, { "region", "us-east-1" }, { "key", "arn:aws:kms:us-east-1:579766882180:key/0689eb07-d588-4bbf-a83e-42157a92576b" } }.ToBson()); var kmsCredentials = new KmsCredentials( new BsonDocument { { "aws", new BsonDocument { { "secretAccessKey", GetEnvironmenVariabletOrValue("FLE_AWS_SECRET_ACCESS_KEY", "us-east-1") }, { "accessKeyId", GetEnvironmenVariabletOrValue("FLE_AWS_ACCESS_KEY_ID", "us-east-1") } } } }.ToBson()); Guid keyID = controller.GenerateKey(kmsCredentials, awsKeyId); IMongoCollection collection = SetupTestCollection(client, keyID); var database = collection.Database; // Insert a document with SSN var insertDoc = new BsonDocument { { "ssn" , "123-45-6789" }, }; var insertDocCmd = new BsonDocument { { "insert" , "test" }, { "documents", new BsonArray(new BsonValue[] { insertDoc }) } }; var insertEncryptedDoc = new BsonDocument(controller.EncryptCommand(kmsCredentials, collection, insertDocCmd)); Console.WriteLine("Insert Doc: " + insertEncryptedDoc); insertEncryptedDoc.Remove("$db"); database.RunCommand(new BsonDocumentCommand(insertEncryptedDoc)); var findDoc = BsonUtil.FromJSON(@"{ 'find': 'test', 'filter' : { '$or': [{ '_id': 1},{ 'ssn': '123-45-6789'}]}, }"); var findCmd = new BsonDocumentCommand(controller.EncryptCommand(kmsCredentials, collection, findDoc)); Console.WriteLine("Find CMD: " + findCmd.Document); findCmd.Document.Remove("$db"); var commandResult = database.RunCommand(findCmd); Console.WriteLine("Find Result: " + commandResult); var decryptedDocument = controller.DecryptCommand(kmsCredentials, database, commandResult); Console.WriteLine("Find Result (DECRYPTED): " + decryptedDocument); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/000077500000000000000000000000001454530651600236615ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/BasicTests.cs000066400000000000000000001004301454530651600262520ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using MongoDB.Bson; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using Xunit; using System.Text; using FluentAssertions; using Xunit.Abstractions; using MongoDB.Libmongocrypt.Test.Callbacks; namespace MongoDB.Libmongocrypt.Test { public class BasicTests { private static ITestOutputHelper _output; private const string AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"; private const string AEAD_AES_256_CBC_HMAC_SHA_512_Random = "AEAD_AES_256_CBC_HMAC_SHA_512-Random"; public BasicTests(ITestOutputHelper output) { _output = output; } [Fact] public void EncryptQuery() { using (var cryptClient = CryptClientFactory.Create(CreateOptions())) using (var context = cryptClient.StartEncryptionContext("test", command: BsonUtil.ToBytes(ReadJsonTestFile("cmd.json")))) { var (_, bsonCommand) = ProcessContextToCompletion(context); bsonCommand.Should().Equal((ReadJsonTestFile("encrypted-command.json"))); } } [Fact] public void EncryptQueryStepwise() { using (var cryptClient = CryptClientFactory.Create(CreateOptions())) using (var context = cryptClient.StartEncryptionContext("test", command: BsonUtil.ToBytes(ReadJsonTestFile("cmd.json")))) { var (state, _, operationSent) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); operationSent.Should().Equal((ReadJsonTestFile("list-collections-filter.json"))); (state, _, operationSent) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); operationSent.Should().Equal(ReadJsonTestFile("mongocryptd-command.json")); (state, _, operationSent) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); operationSent.Should().Equal(ReadJsonTestFile("key-filter.json")); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); // kms fluent assertions inside ProcessState() (state, _, operationSent) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); operationSent.Should().Equal((ReadJsonTestFile("encrypted-command.json"))); } } [Fact] public void EncryptQueryWithSchemaStepwise() { var listCollectionsReply = ReadJsonTestFile("collection-info.json"); var schema = new BsonDocument("test.test", listCollectionsReply["options"]["validator"]["$jsonSchema"]); var options = new CryptOptions( new[] { CreateKmsCredentials("aws") }, BsonUtil.ToBytes(schema)); using (var cryptClient = CryptClientFactory.Create(options)) using (var context = cryptClient.StartEncryptionContext( db: "test", command: BsonUtil.ToBytes(ReadJsonTestFile("cmd.json")))) { var (state, _, operationSent) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); var mongoCryptdCommand = ReadJsonTestFile("mongocryptd-command.json"); mongoCryptdCommand["isRemoteSchema"] = false; operationSent.Should().Equal(mongoCryptdCommand); (state, _, operationSent) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); operationSent.Should().Equal(ReadJsonTestFile("key-filter.json")); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); // kms fluent assertions inside ProcessState() (state, _, operationSent) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); operationSent.Should().Equal((ReadJsonTestFile("encrypted-command.json"))); } } [Fact] public void DecryptQuery() { using (var cryptClient = CryptClientFactory.Create(CreateOptions())) using (var context = cryptClient.StartDecryptionContext(BsonUtil.ToBytes(ReadJsonTestFile("encrypted-command-reply.json")))) { var (_, bsonCommand) = ProcessContextToCompletion(context); bsonCommand.Should().Equal(ReadJsonTestFile("command-reply.json")); } } [Fact] public void DecryptQueryStepwise() { using (var cryptClient = CryptClientFactory.Create(CreateOptions())) using (var context = cryptClient.StartDecryptionContext(BsonUtil.ToBytes(ReadJsonTestFile("encrypted-command-reply.json")))) { var (state, _, operationProduced) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); operationProduced.Should().Equal(ReadJsonTestFile("key-filter.json")); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); // kms fluent assertions inside ProcessState() (state, _, operationProduced) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); operationProduced.Should().Equal(ReadJsonTestFile("command-reply.json")); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); } } [Fact] public void EncryptBadBson() { using (var cryptClient = CryptClientFactory.Create(CreateOptions())) { Func startEncryptionContext = () => cryptClient.StartEncryptionContext("test", command: new byte[] { 0x1, 0x2, 0x3 }); // Ensure if we encrypt non-sense, it throws an exception demonstrating our exception code is good var exception = Record.Exception(startEncryptionContext); exception.Should().BeOfType(); } } [Fact] public void EncryptExplicit() { var keyDoc = ReadJsonTestFile("key-document.json"); var keyId = keyDoc["_id"].AsBsonBinaryData.Bytes; BsonDocument doc = new BsonDocument() { { "v" , "hello" }, }; var testData = BsonUtil.ToBytes(doc); byte[] encryptedBytes; using (var cryptClient = CryptClientFactory.Create(CreateOptions())) using (var context = StartExplicitEncryptionContextWithKeyId(cryptClient, keyId, AEAD_AES_256_CBC_HMAC_SHA_512_Random, testData)) { var (encryptedBinary, encryptedDocument) = ProcessContextToCompletion(context); encryptedBytes = encryptedBinary.ToArray(); // need to copy bytes out before the context gets destroyed } using (var cryptClient = CryptClientFactory.Create(CreateOptions())) using (var context = cryptClient.StartExplicitDecryptionContext(encryptedBytes)) { var (decryptedResult, _) = ProcessContextToCompletion(context); decryptedResult.ToArray().Should().Equal(testData); } } [Fact] public void EncryptExplicitStepwise() { var keyDoc = ReadJsonTestFile("key-document.json"); var keyId = keyDoc["_id"].AsBsonBinaryData.Bytes; var doc = new BsonDocument("v", "hello"); var testData = BsonUtil.ToBytes(doc); using (var cryptClient = CryptClientFactory.Create(CreateOptions())) { byte[] encryptedResult; using (var context = StartExplicitEncryptionContextWithKeyId( cryptClient, keyId: keyId, encryptionAlgorithm: AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, message: testData)) { var (state, binaryProduced, operationProduced) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); operationProduced.Should().Equal(ReadJsonTestFile("key-filter.json")); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); // kms fluent assertions inside ProcessState() (state, binaryProduced, operationProduced) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); operationProduced.Should().Equal(ReadJsonTestFile("encrypted-value.json")); encryptedResult = binaryProduced.ToArray(); // need to copy bytes out before the context gets destroyed (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); } using (var context = cryptClient.StartExplicitDecryptionContext(encryptedResult)) { var (state, decryptedBinary, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); decryptedBinary.ToArray().Should().Equal(testData); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); } } } [Fact] public void TestAwsKeyCreationWithEndPoint() { var endpoint = "kms.us-east-1.amazonaws.com"; var keyId = CreateKmsKeyId("aws", endpoint); var key = CreateKmsCredentials("aws"); using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { var (_, dataKeyDocument) = ProcessContextToCompletion(context, isKmsDecrypt: false); dataKeyDocument["masterKey"]["endpoint"].Should().Be(endpoint); } } [Fact] public void TestAwsKeyCreationWithEndpointStepwise() { var endpoint = "kms.us-east-1.amazonaws.com"; var keyId = CreateKmsKeyId("aws", endpoint); var key = CreateKmsCredentials("aws"); using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { BsonDocument dataKeyDocument; var (state, _, _) = ProcessState(context, isKmsDecrypt: false); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); (state, _, dataKeyDocument) = ProcessState(context, isKmsDecrypt: false); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); dataKeyDocument["masterKey"]["endpoint"].Should().Be(endpoint); (state, _, _) = ProcessState(context, isKmsDecrypt: false); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); } } [Fact] public void TestAwsKeyCreationWithkeyAltNames() { var keyAltNames = new[] { "KeyMaker", "Architect" }; var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); var keyId = CreateKmsKeyId("aws", keyAltNameBuffers: keyAltNameBuffers); var key = CreateKmsCredentials("aws"); using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { var (_, dataKeyDocument) = ProcessContextToCompletion(context, isKmsDecrypt: false); dataKeyDocument.Should().NotBeNull(); var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); } } [Fact] public void TestAwsKeyCreationWithkeyAltNamesStepwise() { var keyAltNames = new[] { "KeyMaker", "Architect" }; var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); var keyId = CreateKmsKeyId("aws", keyAltNameBuffers: keyAltNameBuffers); var key = CreateKmsCredentials("aws"); using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { BsonDocument dataKeyDocument; var (state, _, _) = ProcessState(context, isKmsDecrypt: false); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); (state, _, dataKeyDocument) = ProcessState(context, isKmsDecrypt: false); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); dataKeyDocument.Should().NotBeNull(); var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); (state, _, _) = ProcessState(context, isKmsDecrypt: false); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); } } [Fact] public void TestLocalKeyCreationWithkeyAltNames() { var keyAltNames = new[] { "KeyMaker", "Architect" }; var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); var key = CreateKmsCredentials("local"); var keyId = CreateKmsKeyId("local", keyAltNameBuffers: keyAltNameBuffers); var cryptOptions = new CryptOptions(new[] { key }); using (var cryptClient = CryptClientFactory.Create(cryptOptions)) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { var (_, dataKeyDocument) = ProcessContextToCompletion(context); dataKeyDocument.Should().NotBeNull(); var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); } } [Fact] public void TestLocalKeyCreationWithkeyAltNamesStepwise() { var keyAltNames = new[] { "KeyMaker", "Architect" }; var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); var key = CreateKmsCredentials("local"); var keyId = CreateKmsKeyId("local", keyAltNameBuffers: keyAltNameBuffers); var cryptOptions = new CryptOptions(new[] { key }); using (var cryptClient = CryptClientFactory.Create(cryptOptions)) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { var (state, _, dataKeyDocument) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); dataKeyDocument.Should().NotBeNull(); var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); } } [Fact] public void TestLocalKeyCreation() { var key = CreateKmsCredentials("local"); var keyId = CreateKmsKeyId("local"); var cryptOptions = new CryptOptions(new[] { key }); using (var cryptClient = CryptClientFactory.Create(cryptOptions)) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { var (_, dataKeyDocument) = ProcessContextToCompletion(context); dataKeyDocument.Should().NotBeNull(); } } [Fact] public void TestLocalKeyCreationStepwise() { var key = CreateKmsCredentials("local"); var keyId = CreateKmsKeyId("local"); var cryptOptions = new CryptOptions(new[] { key }); using (var cryptClient = CryptClientFactory.Create(cryptOptions)) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { var (state, _, dataKeyDocument) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); dataKeyDocument.Should().NotBeNull(); (state, _, _) = ProcessState(context); state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); } } [Theory] [InlineData("aws")] [InlineData("azure")] #if NETCOREAPP3_0 [InlineData("gcp")] #endif [InlineData("kmip")] public void TestGetKmsProviderName(string kmsName) { var key = CreateKmsCredentials(kmsName); var keyId = CreateKmsKeyId(kmsName); var cryptOptions = new CryptOptions(new[] { key }); using (var cryptClient = CryptClientFactory.Create(cryptOptions)) using (var context = cryptClient.StartCreateDataKeyContext(keyId)) { var request = context.GetKmsMessageRequests().Single(); request.KmsProvider.Should().Be(kmsName); } } // private methods private static KmsCredentials CreateKmsCredentials(string kmsName) { BsonDocument kmsCredentialsDocument; switch (kmsName) { case "local": kmsCredentialsDocument = new BsonDocument { { "local", new BsonDocument { { "key", new BsonBinaryData(new byte[96]) } } } }; break; case "aws": kmsCredentialsDocument = new BsonDocument { { "aws", new BsonDocument { { "secretAccessKey", "dummy" }, { "accessKeyId", "dummy" } } } }; break; case "azure": kmsCredentialsDocument = new BsonDocument { { "azure", new BsonDocument { { "tenantId", "dummy" }, { "clientId", "dummy" }, { "clientSecret", "dummy" } } } }; break; case "gcp": kmsCredentialsDocument = new BsonDocument { { "gcp", new BsonDocument { { "email", "dummy" }, { "privateKey", SigningRSAESPKCSCallbackTests.PrivateKey } } } }; break; case "kmip": kmsCredentialsDocument = new BsonDocument { { "kmip", new BsonDocument { { "endpoint", "dummy" } } } }; break; default: throw new Exception($"Unsupported kms {kmsName}."); } return new KmsCredentials(kmsCredentialsDocument.ToBson()); } private static KmsKeyId CreateKmsKeyId(string kmsName, string endPoint = null, IEnumerable keyAltNameBuffers = null) { BsonDocument datakeyOptionsDocument; switch (kmsName) { case "local": datakeyOptionsDocument = new BsonDocument { { "provider", "local" }, }; break; case "aws": datakeyOptionsDocument = new BsonDocument { { "provider", "aws" }, { "key", "cmk" }, { "region", "us-east-1" }, { "endpoint", () => endPoint, endPoint != null } }; break; case "azure": datakeyOptionsDocument = new BsonDocument { { "provider", "azure" }, { "keyName", "dummy" }, { "keyVaultEndpoint", endPoint ?? "dummy.azure.net" } }; break; case "gcp": datakeyOptionsDocument = new BsonDocument { { "provider", "gcp" }, { "projectId", "dummy" }, { "location", "dummy" }, { "keyRing", "dummy" }, { "keyName", "dummy" }, { "endpoint", () => endPoint, endPoint != null } }; break; case "kmip": datakeyOptionsDocument = new BsonDocument { { "provider", "kmip" } }; break; default: throw new Exception($"Unsupported kms {kmsName}."); } return new KmsKeyId(datakeyOptionsDocument.ToBson(), keyAltNameBuffers); } private CryptOptions CreateOptions() { return new CryptOptions( new[] { CreateKmsCredentials("aws"), CreateKmsCredentials("local") }); } private (Binary binarySent, BsonDocument document) ProcessContextToCompletion(CryptContext context, bool isKmsDecrypt = true) { BsonDocument document = null; Binary binary = null; while (!context.IsDone) { (_, binary, document) = ProcessState(context, isKmsDecrypt); } return (binary, document); } /// /// Processes the current state, simulating the execution the operation/post requests needed to reach the next state /// Returns (stateProcessed, binaryOperationProduced, bsonOperationProduced) /// /// private (CryptContext.StateCode stateProcessed, Binary binaryProduced, BsonDocument bsonOperationProduced) ProcessState(CryptContext context, bool isKmsDecrypt = true) { _output.WriteLine("\n----------------------------------\nState:" + context.State); switch (context.State) { case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: { var binary = context.GetOperation(); var doc = BsonUtil.ToDocument(binary); _output.WriteLine("ListCollections: " + doc); var reply = ReadJsonTestFile("collection-info.json"); _output.WriteLine("Reply:" + reply); context.Feed(BsonUtil.ToBytes(reply)); context.MarkDone(); return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO, binary, doc); } case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: { var binary = context.GetOperation(); var doc = BsonUtil.ToDocument(binary); _output.WriteLine("Markings: " + doc); var reply = ReadJsonTestFile("mongocryptd-reply.json"); _output.WriteLine("Reply:" + reply); context.Feed(BsonUtil.ToBytes(reply)); context.MarkDone(); return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS, binary, doc); } case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS: { var binary = context.GetOperation(); var doc = BsonUtil.ToDocument(binary); _output.WriteLine("Key Document: " + doc); var reply = ReadJsonTestFile("key-document.json"); _output.WriteLine("Reply:" + reply); context.Feed(BsonUtil.ToBytes(reply)); context.MarkDone(); return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS, binary, doc); } case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS: { var requests = context.GetKmsMessageRequests(); foreach (var req in requests) { var binary = req.Message; _output.WriteLine("Key Document: " + binary); var postRequest = binary.ToString(); // TODO: add different hosts handling postRequest.Should().Contain("Host:kms.us-east-1.amazonaws.com"); // only AWS var reply = ReadHttpTestFile(isKmsDecrypt ? "kms-decrypt-reply.txt" : "kms-encrypt-reply.txt"); _output.WriteLine("Reply: " + reply); req.Feed(Encoding.UTF8.GetBytes(reply)); req.BytesNeeded.Should().Be(0); } requests.MarkDone(); return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS, null, null); } case CryptContext.StateCode.MONGOCRYPT_CTX_READY: { Binary binary = context.FinalizeForEncryption(); _output.WriteLine("Buffer:" + binary.ToArray()); var document = BsonUtil.ToDocument(binary); _output.WriteLine("Document:" + document); return (CryptContext.StateCode.MONGOCRYPT_CTX_READY, binary, document); } case CryptContext.StateCode.MONGOCRYPT_CTX_DONE: { _output.WriteLine("DONE!!"); return (CryptContext.StateCode.MONGOCRYPT_CTX_DONE, null, null); } case CryptContext.StateCode.MONGOCRYPT_CTX_ERROR: { // We expect exceptions are thrown before we get to this state throw new NotImplementedException(); } } throw new NotImplementedException(); } public CryptContext StartExplicitEncryptionContextWithKeyId(CryptClient client, byte[] keyId, string encryptionAlgorithm, byte[] message) { return client.StartExplicitEncryptionContext(keyId, keyAltName: null, queryType: null, contentionFactor: null, encryptionAlgorithm, message, rangeOptions: null); } static IEnumerable FindTestDirectories() { string[] searchPaths = new[] { Path.Combine("..", "test", "example"), Path.Combine("..", "test", "data") }; var assemblyLocation = Path.GetDirectoryName(typeof(BasicTests).GetTypeInfo().Assembly.Location); string cwd = Directory.GetCurrentDirectory(); // Assume we are in a child directory of the repo var searchDirectory = assemblyLocation ?? cwd; var testDirs = Enumerable.Range(1, 10) .Select(i => Enumerable.Repeat("..", i)) .Select(dotsSeq => dotsSeq.Aggregate(Path.Combine)) .SelectMany(previousDirectories => searchPaths.Select(searchPath => Path.Combine(searchDirectory, previousDirectories, searchPath))) .Where(Directory.Exists) .ToArray(); if (!testDirs.Any()) { throw new DirectoryNotFoundException("test/example"); } return testDirs; } static string ReadHttpTestFile(string file) { // The HTTP tests assume \r\n // And git strips \r on Unix machines by default so fix up the files var text = ReadTestFile(file); StringBuilder builder = new StringBuilder(text.Length); for (int i = 0; i < text.Length; i++) { if (text[i] == '\n' && text[i - 1] != '\r') builder.Append('\r'); builder.Append(text[i]); } return builder.ToString(); } static BsonDocument ReadJsonTestFile(string file) { var text = ReadTestFile(file); if (text == null) { throw new FileNotFoundException(file); } // Work around C# drivers and C driver have different extended json support text = text.Replace("\"$numberLong\"", "$numberLong"); return BsonUtil.FromJSON(text); } static string ReadTestFile(string fileName) { return FindTestDirectories() .Select(directory => Path.Combine(directory, fileName)) .Where(File.Exists) .Select(File.ReadAllText) .FirstOrDefault(); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/BsonUtil.cs000066400000000000000000000054621454530651600257560ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using MongoDB.Bson; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; using System.IO; namespace MongoDB.Libmongocrypt.Test { class BsonUtil { public static BsonDocument ToDocument(Binary bin) { MemoryStream stream = new MemoryStream(bin.ToArray()); using (var jsonReader = new BsonBinaryReader(stream)) { var context = BsonDeserializationContext.CreateRoot(jsonReader); return BsonDocumentSerializer.Instance.Deserialize(context); } } public static byte[] ToBytes(BsonDocument doc) { BsonBinaryWriterSettings settings = new BsonBinaryWriterSettings() { // C# driver "magically" changes UUIDs underneath by default so tell it not to GuidRepresentation = GuidRepresentation.Standard }; return doc.ToBson(null, settings); } public static BsonDocument Concat(BsonDocument doc1, BsonDocument doc2) { BsonDocument dest = new BsonDocument(); BsonDocumentWriter writer = new BsonDocumentWriter(dest); var context = BsonSerializationContext.CreateRoot(writer); writer.WriteStartDocument(); foreach (var field in doc1) { writer.WriteName(field.Name); BsonValueSerializer.Instance.Serialize(context, field.Value); } foreach (var field in doc2) { writer.WriteName(field.Name); BsonValueSerializer.Instance.Serialize(context, field.Value); } writer.WriteEndDocument(); return writer.Document; } public static BsonDocument FromJSON(string str) { var jsonReaderSettings = new JsonReaderSettings { GuidRepresentation = GuidRepresentation.Unspecified }; using (var jsonReader = new JsonReader(str, jsonReaderSettings)) { var context = BsonDeserializationContext.CreateRoot(jsonReader); return BsonDocumentSerializer.Instance.Deserialize(context); } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/CallbackUtils.cs000066400000000000000000000022521454530651600267260ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; namespace MongoDB.Libmongocrypt.Test { internal static class CallbackUtils { public static byte[] GetBytesFromHex(string hex) { if (hex.Length % 2 != 0) { throw new ArgumentException("Hex string must contain an even number of hex digits."); } int length = hex.Length; byte[] bytes = new byte[length / 2]; for (int i = 0; i < length; i += 2) bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); return bytes; } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/CipherCallbacksTests.cs000066400000000000000000000035571454530651600302570ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using FluentAssertions; using System.Security.Cryptography; using Xunit; namespace MongoDB.Libmongocrypt.Test { public class CipherCallbacksTests { [Theory] [InlineData(CipherMode.CBC, "671db60d464b09e9c3b03242dd29bdc5")] [InlineData(CipherMode.ECB, "ae6b200f30d6e8e424127e9c58affaf8")] public void CipherTest(CipherMode mode, string expectedHex) { var keyHex = "92faa793d717675e2be804584a8a98252083fe6bf16010546a92e2ef4bdd27fd"; var ivHex = "31164b2f661e41fed5df60bfcfa40baa"; var inputHex = "379ddb78c30e5e4bf19dd81ae705796f"; var keyBytes = CallbackUtils.GetBytesFromHex(keyHex); var ivBytes = CallbackUtils.GetBytesFromHex(ivHex); var inputBytes = CallbackUtils.GetBytesFromHex(inputHex); // decryptedBytes var expectedEncryptedBytes = CallbackUtils.GetBytesFromHex(expectedHex); var encryptedBytes = CipherCallbacks.AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Encrypt, mode); encryptedBytes.Should().Equal(expectedEncryptedBytes); var decryptedBytes = CipherCallbacks.AesCrypt(keyBytes, ivBytes, encryptedBytes, CryptMode.Decrypt, mode); decryptedBytes.Should().Equal(inputBytes); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/HashCallbackTests.cs000066400000000000000000000023251454530651600275350ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using FluentAssertions; using Xunit; namespace MongoDB.Libmongocrypt.Test { public class HashCallbackTests { [Fact] public void HashTest() { var inputHex = "74657374206f66206d6163"; var expectedHex = "9ff3e52fa31c9e0fa0b08e19c40591553ea64b73709633271975bfab2db9d980"; var inputBytes = CallbackUtils.GetBytesFromHex(inputHex); var expectedBytes = CallbackUtils.GetBytesFromHex(expectedHex); var resultBytes = HashCallback.CalculateHash(inputBytes); resultBytes.Should().Equal(expectedBytes); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/HmacShaCallbacksTests.cs000066400000000000000000000033161454530651600303420ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using FluentAssertions; using Xunit; namespace MongoDB.Libmongocrypt.Test { public class HmacShaCallbacksTests { [Theory] [InlineData(256, "74657374206f66206d6163", "37626663386235656333306537336439386565666133653263633334643635376535323734623537656633326661353862663638313534396535663737303138", "ebfaa874ff7fcf5b48637a4aff49ed60f48b53a0802719d6ad85f96d315b2df2")] [InlineData(512, "74657374206f6620686d61630a", "06645237ece5638d1dcb66c70d8158c6ba5922dce3ae9f95242147fce0f989d9", "c8bc88465593980da5ed9bd213dcc4594106f6573d08eddc2b7cead3a642ef37dd848e8901a8c340f2a5d909057d28b1355fc9c82e7f7710e688f8c0c7635e9a")] public void HmacShaTest(int bitness, string inputHex, string keyHex, string expectedHex) { var keyBytes = CallbackUtils.GetBytesFromHex(keyHex); var inputBytes = CallbackUtils.GetBytesFromHex(inputHex); var expectedBytes = CallbackUtils.GetBytesFromHex(expectedHex); var resultBytes = HmacShaCallbacks.CalculateHash(keyBytes, inputBytes, bitness); resultBytes.Should().Equal(expectedBytes); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj000066400000000000000000000022411454530651600321340ustar00rootroot00000000000000 net472;netcoreapp2.1;netcoreapp3.0 netcoreapp2.1;netcoreapp3.0 AnyCPU false . PreserveNewest libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/Package.include.template.csproj000066400000000000000000000014351454530651600316750ustar00rootroot00000000000000 false @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt.Test @CMAKE_CURRENT_BINARY_DIR@/MongoDB.Libmongocrypt.Test libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/SigningRSAESPKCSCallbackTests.cs000066400000000000000000000073761454530651600315420ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Text; using FluentAssertions; using Xunit; namespace MongoDB.Libmongocrypt.Test.Callbacks { public class SigningRSAESPKCSCallbackTests { private static string DataToSign = "data to sign"; public static string PrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJ" + "xCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xY" + "uXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/" + "kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CM" + "prqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrS" + "hXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqIm" + "RYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlx" + "dc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4u" + "mxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54" + "qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAx" + "bLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/" + "9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7" + "gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4V" + "nrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a"; private static string ExpectedSignature = "VocBRhpMmQ2XCzVehWSqheQLnU889gf3dhU4AnVnQTJjsKx/CM23qKDPkZDd2A/BnQsp99SN7ksIX5Raj0TPw" + "yN5OCN/YrNFNGoOFlTsGhgP/hyE8X3Duiq6sNO0SMvRYNPFFGlJFsp1Fw3Z94eYMg4/Wpw5s4+Jo5Zm/qY7aTJIqDKDQ3CNHLeJgcMUOc9sz01/GzoUYKDVODHSx" + "rYEk5ireFJFz9vP8P7Ha+VDUZuQIQdXer9NBbGFtYmWprY3nn4D3Dw93Sn0V0dIqYeIo91oKyslvMebmUM95S2PyIJdEpPb2DJDxjvX/0LLwSWlSXRWy9gapWoBk" + "b4ynqZBsg=="; [Fact] public void GetSignatureTest() { byte[] privateKeyBytes = Convert.FromBase64String(PrivateKey); var dataBytes = Encoding.ASCII.GetBytes(DataToSign); #if NETCOREAPP3_0 byte[] signature = SigningRSAESPKCSCallback.HashAndSignBytes(dataBytes, privateKeyBytes); string output = Convert.ToBase64String(signature); output.Should().Be(ExpectedSignature); #else var ex = Record.Exception(() => SigningRSAESPKCSCallback.HashAndSignBytes(dataBytes, privateKeyBytes)); ex.Should().BeOfType(); #endif } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/000077500000000000000000000000001454530651600246405ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/000077500000000000000000000000001454530651600262735ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/collection-info.json000066400000000000000000000017311454530651600322540ustar00rootroot00000000000000{ "type": "collection", "name": "test", "idIndex": { "ns": "test.test", "name": "_id_", "key": { "_id": { "$numberInt": "1" } }, "v": { "$numberInt": "2" } }, "options": { "validator": { "$jsonSchema": { "properties": { "ssn": { "encrypt": { "keyId": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "type": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/command-reply.json000066400000000000000000000002361454530651600317360ustar00rootroot00000000000000{ "cursor": { "firstBatch": [ { "_id": 1, "ssn": "457-55-5462" } ], "id": 0, "ns": "test.test" }, "ok": 1 } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command-reply.json000066400000000000000000000005251454530651600337320ustar00rootroot00000000000000{ "cursor" : { "firstBatch" : [ { "_id": 1, "ssn": { "$binary": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", "$type": "06" } } ], "id" : 0, "ns" : "test.test" }, "ok" : 1 }libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command.json000066400000000000000000000004101454530651600325720ustar00rootroot00000000000000{ "filter": { "ssn": { "$binary": { "base64": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", "subType": "06" } } }, "find": "test" } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-value.json000066400000000000000000000002461454530651600322770ustar00rootroot00000000000000{ "v": { "$binary": "AWFhYWFhYWFhYWFhYWFhYWECW+zDjR/69eS6VtuMD5+O2lZw6JyiWOw3avI7mnUkdpKzPfvy8F/nlZrgZa2cGmQsb0TmLZuk5trldosnGKD91w==", "$type": "06" } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-document.json000066400000000000000000000020731454530651600315740ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "masterKey": { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "provider": "aws" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": [ "altKeyName", "another_altname" ] } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-filter.json000066400000000000000000000003631454530651600312430ustar00rootroot00000000000000{ "$or": [ { "_id": { "$in": [ { "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", "$type": "04" } ] } }, { "keyAltNames": { "$in": [] } } ] }libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/list-collections-filter.json000066400000000000000000000000241454530651600337340ustar00rootroot00000000000000{ "name": "test" }libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/mongocryptd-command.json000066400000000000000000000006531454530651600331530ustar00rootroot00000000000000{ "find": "test", "filter": { "ssn": "457-55-5462" }, "jsonSchema": { "properties": { "ssn": { "encrypt": { "keyId": { "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", "$type": "04" }, "type": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "isRemoteSchema": true }libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test/xunit.runner.json000066400000000000000000000002071454530651600272320ustar00rootroot00000000000000{ "$schema": "https://xunit.github.io/schema/current/xunit.runner.schema.json", "appDomain": "denied", "shadowCopy": false } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test32/000077500000000000000000000000001454530651600240265ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test32/BasicTests.cs000066400000000000000000000032111454530651600264160ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using Xunit; using FluentAssertions; using MongoDB.Bson; namespace MongoDB.Libmongocrypt.Test32 { public class BasicTests { BsonDocument CreateAwsCredentialsDocument() => new BsonDocument { { "aws", new BsonDocument { { "secretAccessKey", "us-east-1" }, { "accessKeyId", "us-east-1" } } } }; CryptOptions CreateOptions() => new CryptOptions( new[] { new KmsCredentials(CreateAwsCredentialsDocument().ToBson()) } ); [Fact] public void CryptClientShouldFailToiInitializeWhenTargetingX86() { var exception = Record.Exception(() => CryptClientFactory.Create(CreateOptions())); exception.Should().BeOfType(); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj000066400000000000000000000027261454530651600324560ustar00rootroot00000000000000 net472;netcoreapp2.1;netcoreapp3.0 netcoreapp2.1;netcoreapp3.0 false . x86 x86 libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt.Test32/Package.include.template.csproj000066400000000000000000000014411454530651600320370ustar00rootroot00000000000000 false @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt.Test32 @CMAKE_CURRENT_BINARY_DIR@/MongoDB.Libmongocrypt.Test32 libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/000077500000000000000000000000001454530651600227435ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs000066400000000000000000000002471454530651600256700ustar00rootroot00000000000000using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test")] [assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test32")] libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/Binary.cs000066400000000000000000000073151454530651600245240ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.IO; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// A pointer and length pair the contains raw bytes to pass or retrive from libmongocrypt. /// /// public class Binary : IDisposable { private static readonly byte[] __empty = new byte[0]; private BinarySafeHandle _handle; internal Binary() { _handle = Library.mongocrypt_binary_new(); } internal Binary(BinarySafeHandle handle) { _handle = handle; } /// /// Gets the data. /// /// /// The data. /// public IntPtr Data { get { return Library.mongocrypt_binary_data(_handle); } } /// /// Gets the length. /// /// /// The length. /// public uint Length { get { return Library.mongocrypt_binary_len(_handle); } } internal BinarySafeHandle Handle => _handle; /// /// Converts to array. /// public byte[] ToArray() { if (Length > 0) { byte[] arr = new byte[Length]; Marshal.Copy(Data, arr, 0, arr.Length); return arr; } else { return __empty; } } /// /// Write bytes into Data. /// public void WriteBytes(byte[] bytes) { // The length of the new bytes can be smaller than allocated memory // because sometimes the allocated memory contains reserved blocks for future usage if (bytes.Length <= Length) { Marshal.Copy(bytes, 0, Data, bytes.Length); } else { // this code path is not expected, but it's worth doing it to avoid silent saving of corrupted data throw new InvalidDataException($"Incorrect bytes size {bytes.Length}. The bytes size must be less than or equal to {Length}."); } } /// /// Converts to string. /// /// /// A that represents this instance. /// public override string ToString() { return Marshal.PtrToStringAnsi(Data); } #region IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 if (_handle != null && !_handle.IsInvalid) { // Free the handle _handle.Dispose(); } } #endregion } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/BinarySafeHandle.cs000066400000000000000000000033221454530651600264310ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// SafeHandle to manage the lifetime of a mongocrypt_binary_t. /// /// internal class BinarySafeHandle : SafeHandle { private BinarySafeHandle() : base(IntPtr.Zero, true) { } private BinarySafeHandle(IntPtr ptr) : base(ptr, false) { } public static BinarySafeHandle FromIntPtr(IntPtr ptr) { return new BinarySafeHandle(ptr); } public override bool IsInvalid { get { return handle == IntPtr.Zero; } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] protected override bool ReleaseHandle() { // Here, we must obey all rules for constrained execution regions. Library.mongocrypt_binary_destroy(handle); return true; } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/CheckableSafeHandle.cs000066400000000000000000000026151454530651600270520ustar00rootroot00000000000000/* * Copyright 2010–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// SafeHandle to manage the lifetime of a mongocrypt_ctx_t. /// /// internal abstract class CheckableSafeHandle : SafeHandle { internal CheckableSafeHandle() : base(IntPtr.Zero, true) { } public override bool IsInvalid { get { return handle == IntPtr.Zero; } } public abstract void Check(Status status, bool success); [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] protected abstract override bool ReleaseHandle(); } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/CipherCallbacks.cs000066400000000000000000000140421454530651600263050ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Security.Cryptography; namespace MongoDB.Libmongocrypt { internal enum CryptMode { Encrypt, Decrypt } internal static class CipherCallbacks { public static bool EncryptCbc( IntPtr ctx, IntPtr key, IntPtr iv, IntPtr @in, IntPtr @out, ref uint bytes_written, IntPtr statusPtr) { using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) { try { var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); var outputBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); var ivBinary = new Binary(BinarySafeHandle.FromIntPtr(iv)); byte[] keyBytes = keyBinary.ToArray(); byte[] ivBytes = ivBinary.ToArray(); byte[] inputBytes = inputBinary.ToArray(); var outputBytes = AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Encrypt, CipherMode.CBC); bytes_written = (uint)outputBytes.Length; outputBinary.WriteBytes(outputBytes); return true; } catch (Exception e) { status.SetStatus(1, e.Message); return false; } } } public static bool DecryptCbc( IntPtr ctx, IntPtr key, IntPtr iv, IntPtr @in, IntPtr @out, ref uint bytes_written, IntPtr statusPtr) { using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) { try { var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); var outputBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); var ivBinary = new Binary(BinarySafeHandle.FromIntPtr(iv)); byte[] keyBytes = keyBinary.ToArray(); byte[] ivBytes = ivBinary.ToArray(); byte[] inputBytes = inputBinary.ToArray(); var outputBytes = AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Decrypt, CipherMode.CBC); bytes_written = (uint)outputBytes.Length; outputBinary.WriteBytes(outputBytes); return true; } catch (Exception e) { status.SetStatus(1, e.Message); return false; } } } public static bool EncryptEcb( IntPtr ctx, IntPtr key, IntPtr iv, IntPtr @in, IntPtr @out, ref uint bytes_written, IntPtr statusPtr) { using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) { try { var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); var outputBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); var ivBinary = new Binary(BinarySafeHandle.FromIntPtr(iv)); byte[] keyBytes = keyBinary.ToArray(); byte[] ivBytes = ivBinary.ToArray(); byte[] inputBytes = inputBinary.ToArray(); var outputBytes = AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Encrypt, CipherMode.ECB); bytes_written = (uint)outputBytes.Length; outputBinary.WriteBytes(outputBytes); return true; } catch (Exception e) { status.SetStatus(1, e.Message); return false; } } } public static byte[] AesCrypt(byte[] keyBytes, byte[] ivBytes, byte[] inputBytes, CryptMode cryptMode, CipherMode cipherMode) { using (var aes = new RijndaelManaged()) { aes.Mode = cipherMode; aes.Key = keyBytes; if (ivBytes.Length > 0) { aes.IV = ivBytes; } aes.Padding = PaddingMode.None; // mongocrypt level is responsible for padding using (var encrypto = CreateCryptoTransform(aes)) { byte[] encryptedBytes = encrypto.TransformFinalBlock(inputBytes, 0, inputBytes.Length); return encryptedBytes; } ICryptoTransform CreateCryptoTransform(RijndaelManaged rijndaelManaged) { switch (cryptMode) { case CryptMode.Encrypt: return rijndaelManaged.CreateEncryptor(); case CryptMode.Decrypt: return rijndaelManaged.CreateDecryptor(); default: throw new InvalidOperationException($"Unsupported crypt mode {cryptMode}."); // should not be reached } } } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/ContextSafeHandle.cs000066400000000000000000000030161454530651600266310ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Runtime.ConstrainedExecution; namespace MongoDB.Libmongocrypt { /// /// SafeHandle to manage the lifetime of a mongocrypt_ctx_t. /// /// internal class ContextSafeHandle : CheckableSafeHandle { private ContextSafeHandle() : base() { } public override void Check(Status status, bool success) { if (!success) { Library.mongocrypt_ctx_status(this, status.Handle); status.ThrowExceptionIfNeeded(); } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] protected override bool ReleaseHandle() { // Here, we must obey all rules for constrained execution regions. Library.mongocrypt_ctx_destroy(handle); return true; } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/CryptClient.cs000066400000000000000000000220061454530651600255320ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// CryptClient represents a session with libmongocrypt. /// /// It can be used to encrypt and decrypt documents. /// /// public class CryptClient : IDisposable, IStatus { private MongoCryptSafeHandle _handle; private Status _status; internal CryptClient(MongoCryptSafeHandle handle, Status status) { _handle = handle ?? throw new ArgumentNullException(paramName: nameof(handle)); _status = status ?? throw new ArgumentNullException(paramName: nameof(status)); } /// /// Gets the crypt shared library version. /// /// A crypt shared library version. public string CryptSharedLibraryVersion { get { var versionPtr = Library.mongocrypt_crypt_shared_lib_version_string(_handle, out _); var result = Marshal.PtrToStringAnsi(versionPtr); return result; } } /// /// Starts the create data key context. /// /// The key identifier. /// A crypt context for creating a data key public CryptContext StartCreateDataKeyContext(KmsKeyId keyId) { ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); keyId.SetCredentials(handle, _status); handle.Check(_status, Library.mongocrypt_ctx_datakey_init(handle)); return new CryptContext(handle); } /// /// Starts the encryption context. /// /// The database of the collection. /// The command. /// A encryption context. public CryptContext StartEncryptionContext(string db, byte[] command) { ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); IntPtr stringPointer = (IntPtr)Marshal.StringToHGlobalAnsi(db); try { unsafe { fixed (byte* c = command) { var commandPtr = (IntPtr)c; using (var pinnedCommand = new PinnedBinary(commandPtr, (uint)command.Length)) { // Let mongocrypt run strlen handle.Check(_status, Library.mongocrypt_ctx_encrypt_init(handle, stringPointer, -1, pinnedCommand.Handle)); } } } } finally { Marshal.FreeHGlobal(stringPointer); } return new CryptContext(handle); } /// /// Starts an explicit encryption context. /// public CryptContext StartExplicitEncryptionContext(byte[] keyId, byte[] keyAltName, string queryType, long? contentionFactor, string encryptionAlgorithm, byte[] message, byte[] rangeOptions, bool isExpressionMode = false) { var handle = Library.mongocrypt_ctx_new(_handle); if (keyId != null) { PinnedBinary.RunAsPinnedBinary(handle, keyId, _status, (h, pb) => Library.mongocrypt_ctx_setopt_key_id(h, pb)); } else if (keyAltName != null) { PinnedBinary.RunAsPinnedBinary(handle, keyAltName, _status, (h, pb) => Library.mongocrypt_ctx_setopt_key_alt_name(h, pb)); } if (rangeOptions != null) { PinnedBinary.RunAsPinnedBinary(handle, rangeOptions, _status, (h, pb) => Library.mongocrypt_ctx_setopt_algorithm_range(h, pb)); } handle.Check(_status, Library.mongocrypt_ctx_setopt_algorithm(handle, encryptionAlgorithm, -1)); if (queryType != null) { handle.Check(_status, Library.mongocrypt_ctx_setopt_query_type(handle, queryType, -1)); } if (contentionFactor.HasValue) { var contentionFactorInt = contentionFactor.Value; handle.Check(_status, Library.mongocrypt_ctx_setopt_contention_factor(handle, contentionFactorInt)); } PinnedBinary.RunAsPinnedBinary( handle, message, _status, (h, pb) => { if (isExpressionMode) { // mongocrypt_ctx_explicit_encrypt_expression_init shares the same code as mongocrypt_ctx_explicit_encrypt_init. // The only difference is the validation of the queryType argument: // * mongocrypt_ctx_explicit_encrypt_expression_init requires queryType of "rangePreview". // * mongocrypt_ctx_explicit_encrypt_init rejects queryType of "rangePreview". return Library.mongocrypt_ctx_explicit_encrypt_expression_init(h, pb); } else { return Library.mongocrypt_ctx_explicit_encrypt_init(h, pb); } }); return new CryptContext(handle); } /// /// Starts the decryption context. /// /// The bson document to decrypt. /// A decryption context public CryptContext StartDecryptionContext(byte[] buffer) { ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); unsafe { fixed (byte* p = buffer) { IntPtr ptr = (IntPtr)p; using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) { handle.Check(_status, Library.mongocrypt_ctx_decrypt_init(handle, pinned.Handle)); } } } return new CryptContext(handle); } /// /// Starts an explicit decryption context. /// /// The buffer. /// A encryption context public CryptContext StartExplicitDecryptionContext(byte[] buffer) { ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); unsafe { fixed (byte* p = buffer) { IntPtr ptr = (IntPtr)p; using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) { // Let mongocrypt run strlen handle.Check(_status, Library.mongocrypt_ctx_explicit_decrypt_init(handle, pinned.Handle)); } } } return new CryptContext(handle); } public CryptContext StartRewrapMultipleDataKeysContext(KmsKeyId kmsKey, byte[] filter) { var handle = Library.mongocrypt_ctx_new(_handle); kmsKey.SetCredentials(handle, _status); PinnedBinary.RunAsPinnedBinary(handle, filter, _status, (h, pb) => Library.mongocrypt_ctx_rewrap_many_datakey_init(h, pb)); return new CryptContext(handle); } void IStatus.Check(Status status) { Library.mongocrypt_status(_handle, status.Handle); } #region IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 if (_handle != null && !_handle.IsInvalid) { // Free the handle _handle.Dispose(); } // Free the status _status.Dispose(); } #endregion // private methods private void Check(bool success) { if (!success) { _status.Check(this); } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs000066400000000000000000000140041454530651600270610ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; namespace MongoDB.Libmongocrypt { /// /// A factory for CryptClients. /// public class CryptClientFactory { // MUST be static fields since otherwise these callbacks can be collected via the garbage collector // regardless they're used by mongocrypt level or no private static Library.Delegates.CryptoCallback __cryptoAes256EcbEncryptCallback = new Library.Delegates.CryptoCallback(CipherCallbacks.EncryptEcb); private static Library.Delegates.CryptoCallback __cryptoAes256CbcDecryptCallback = new Library.Delegates.CryptoCallback(CipherCallbacks.DecryptCbc); private static Library.Delegates.CryptoCallback __cryptoAes256CbcEncryptCallback = new Library.Delegates.CryptoCallback(CipherCallbacks.EncryptCbc); private static Library.Delegates.HashCallback __cryptoHashCallback = new Library.Delegates.HashCallback(HashCallback.Hash); private static Library.Delegates.CryptoHmacCallback __cryptoHmacSha256Callback = new Library.Delegates.CryptoHmacCallback(HmacShaCallbacks.HmacSha256); private static Library.Delegates.CryptoHmacCallback __cryptoHmacSha512Callback = new Library.Delegates.CryptoHmacCallback(HmacShaCallbacks.HmacSha512); private static Library.Delegates.RandomCallback __randomCallback = new Library.Delegates.RandomCallback(SecureRandomCallback.GenerateRandom); private static Library.Delegates.CryptoHmacCallback __signRsaesPkcs1HmacCallback = new Library.Delegates.CryptoHmacCallback(SigningRSAESPKCSCallback.RsaSign); /// Creates a CryptClient with the specified options. /// The options. /// A CryptClient public static CryptClient Create(CryptOptions options) { MongoCryptSafeHandle handle = null; Status status = null; try { handle = Library.mongocrypt_new(); status = new Status(); // The below code can be avoided on Windows. So, we don't call it on this system // to avoid restrictions on target frameworks that present in some of below if (OperatingSystemHelper.CurrentOperatingSystem != OperatingSystemPlatform.Windows) { handle.Check( status, Library.mongocrypt_setopt_crypto_hooks( handle, __cryptoAes256CbcEncryptCallback, __cryptoAes256CbcDecryptCallback, __randomCallback, __cryptoHmacSha512Callback, __cryptoHmacSha256Callback, __cryptoHashCallback, IntPtr.Zero)); handle.Check( status, Library.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( handle, __signRsaesPkcs1HmacCallback, IntPtr.Zero)); handle.Check( status, Library.mongocrypt_setopt_aes_256_ecb( handle, __cryptoAes256EcbEncryptCallback, IntPtr.Zero)); } foreach (var kmsCredentials in options.KmsCredentials) { kmsCredentials.SetCredentials(handle, status); } if (options.Schema != null) { PinnedBinary.RunAsPinnedBinary(handle, options.Schema, status, (h, pb) => Library.mongocrypt_setopt_schema_map(h, pb)); } if (options.EncryptedFieldsMap != null) { PinnedBinary.RunAsPinnedBinary(handle, options.EncryptedFieldsMap, status, (h, pb) => Library.mongocrypt_setopt_encrypted_field_config_map(h, pb)); } if (options.BypassQueryAnalysis) { Library.mongocrypt_setopt_bypass_query_analysis(handle); } if (options.CryptSharedLibPath != null) { Library.mongocrypt_setopt_set_crypt_shared_lib_path_override(handle, options.CryptSharedLibPath); } if (options.CryptSharedLibSearchPath != null) { Library.mongocrypt_setopt_append_crypt_shared_lib_search_path(handle, options.CryptSharedLibSearchPath); } Library.mongocrypt_setopt_use_need_kms_credentials_state(handle); Library.mongocrypt_init(handle); if (options.IsCryptSharedLibRequired) { var versionPtr = Library.mongocrypt_crypt_shared_lib_version_string(handle, out _); if (versionPtr == IntPtr.Zero) { throw new CryptException(Library.StatusType.MONGOCRYPT_STATUS_ERROR_CLIENT, uint.MaxValue, "CryptSharedLib is required, but was not found or not loaded."); } } } catch { handle?.Dispose(); status?.Dispose(); throw; } return new CryptClient(handle, status); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/CryptContext.cs000066400000000000000000000147121454530651600257450ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; namespace MongoDB.Libmongocrypt { /// /// A encryption or decryption session. It may not be reused. /// /// /// public class CryptContext : IDisposable, IStatus { /// /// States of the CryptContext state machine /// public enum StateCode { /// /// LibMongoCrypt hit an error /// MONGOCRYPT_CTX_ERROR = 0, /// /// LibMongoCrypt wants the collection information by running a OP_MSG command against the users' mongod. /// MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /// /// LibMongoCrypt wants a command to be run against mongocryptd. /// MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /// /// LibMongoCrypt wants a command to be run against mongod key vault. /// MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /// /// LibMongoCrypt wants a request sent to KMS. /// MONGOCRYPT_CTX_NEED_KMS = 4, /// /// LibMongoCrypt is ready to do encryption, call Finish(). /// MONGOCRYPT_CTX_READY = 5, /// /// LibMongoCrypt is complete. /// MONGOCRYPT_CTX_DONE = 6, /// /// LibMongoCrypt requires new credentials. /// MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7 } private ContextSafeHandle _handle; private Status _status; internal CryptContext(ContextSafeHandle handle) { _handle = handle; _status = new Status(); } /// /// Gets the state. /// /// /// The state. /// public StateCode State { get { return Library.mongocrypt_ctx_state(_handle); } } /// /// Gets a value indicating whether this instance is done. /// /// /// true if this instance is done; otherwise, false. /// public bool IsDone { get { return State == StateCode.MONGOCRYPT_CTX_DONE; } } /// /// Gets the operation. /// /// Binary payload to send to either KMS, mongod, or mongocryptd public Binary GetOperation() { Binary binary = new Binary(); Check(Library.mongocrypt_ctx_mongo_op(_handle, binary.Handle)); return binary; } /// /// Feeds the result from running a remote operation back to the libmongocrypt. /// /// The buffer. public void Feed(byte[] buffer) { unsafe { fixed (byte* p = buffer) { IntPtr ptr = (IntPtr)p; using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) { Check(Library.mongocrypt_ctx_mongo_feed(_handle, pinned.Handle)); } } } } /// /// Signal the feeding is done. /// public void MarkDone() { Check(Library.mongocrypt_ctx_mongo_done(_handle)); } /// /// Finalizes for encryption. /// /// The encrypted or decrypted result. public Binary FinalizeForEncryption() { Binary binary = new Binary(); Check(Library.mongocrypt_ctx_finalize(_handle, binary.Handle)); return binary; } /// /// Gets a collection of KMS message requests to make /// /// Collection of KMS Messages public KmsRequestCollection GetKmsMessageRequests() { var requests = new List(); for (IntPtr request = Library.mongocrypt_ctx_next_kms_ctx(_handle); request != IntPtr.Zero; request = Library.mongocrypt_ctx_next_kms_ctx(_handle)) { requests.Add(new KmsRequest(request)); } return new KmsRequestCollection(requests, this); } public void SetCredentials(byte[] credentials) { PinnedBinary.RunAsPinnedBinary(_handle, credentials, _status, (h, b) => Library.mongocrypt_ctx_provide_kms_providers(h, b)); } void IStatus.Check(Status status) { Library.mongocrypt_ctx_status(_handle, status.Handle); } #region IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 if (_handle != null && !_handle.IsInvalid) { // Free the handle _handle.Dispose(); } } #endregion internal void MarkKmsDone() { Check(Library.mongocrypt_ctx_kms_done(_handle)); } private void Check(bool success) { if (!success) { _status.Check(this); } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/CryptException.cs000066400000000000000000000021541454530651600262540ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; namespace MongoDB.Libmongocrypt { /// /// An exception from libmongocrypt. /// /// public class CryptException : Exception { private readonly uint _code; private readonly Library.StatusType _statusType; internal CryptException(Library.StatusType statusType, uint code, string message) : base(message) { _code = code; _statusType = statusType; } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/CryptOptions.cs000066400000000000000000000045411454530651600257530ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; namespace MongoDB.Libmongocrypt { /// /// Options to configure mongocrypt with. /// public class CryptOptions { public bool BypassQueryAnalysis { get; } public string CryptSharedLibPath { get; } public string CryptSharedLibSearchPath { get; } public byte[] EncryptedFieldsMap { get; } public bool IsCryptSharedLibRequired { get; } public IReadOnlyList KmsCredentials { get; } public byte[] Schema { get; } public CryptOptions(IEnumerable credentials) : this(credentials, null) { } public CryptOptions( IEnumerable credentials, byte[] schema) : this(credentials, null, schema, false, null, null, false) { } public CryptOptions( IEnumerable credentials, byte[] encryptedFieldsMap, byte[] schema, bool bypassQueryAnalysis, string cryptSharedLibPath, string cryptSharedLibSearchPath, bool isCryptSharedLibRequired) { BypassQueryAnalysis = bypassQueryAnalysis; CryptSharedLibPath = cryptSharedLibPath; CryptSharedLibSearchPath = cryptSharedLibSearchPath; IsCryptSharedLibRequired = isCryptSharedLibRequired; EncryptedFieldsMap = encryptedFieldsMap; KmsCredentials = new ReadOnlyCollection((credentials ?? throw new ArgumentNullException(nameof(credentials))).ToList()); Schema = schema; } // TODO: - add configurable logging support } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/HashCallback.cs000066400000000000000000000035201454530651600255720ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Security.Cryptography; namespace MongoDB.Libmongocrypt { internal static class HashCallback { public static bool Hash( IntPtr ctx, IntPtr @in, IntPtr @out, IntPtr statusPtr) { using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) { try { var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); var outBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); var outBytes = CalculateHash(inputBinary.ToArray()); outBinary.WriteBytes(outBytes); return true; } catch (Exception ex) { status.SetStatus(1, ex.Message); return false; } } } public static byte[] CalculateHash(byte[] inputBytes) { using (var sha256 = SHA256.Create()) { sha256.Initialize(); _ = sha256.TransformFinalBlock(inputBytes, 0, inputBytes.Length); return sha256.Hash; } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/HmacShaCallbacks.cs000066400000000000000000000060541454530651600264030ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Security.Cryptography; namespace MongoDB.Libmongocrypt { internal static class HmacShaCallbacks { public static bool HmacSha512( IntPtr ctx, IntPtr key, IntPtr @in, IntPtr @out, IntPtr statusPtr) { return Hmac(key, @in, @out, statusPtr, bitness: 512); } public static bool HmacSha256( IntPtr ctx, IntPtr key, IntPtr @in, IntPtr @out, IntPtr statusPtr) { return Hmac(key, @in, @out, statusPtr, bitness: 256); } public static byte[] CalculateHash(byte[] keyBytes, byte[] inputBytes, int bitness) { using (var hmac = GetHmacByBitness(bitness, keyBytes)) { hmac.Initialize(); _ = hmac.TransformFinalBlock(inputBytes, 0, inputBytes.Length); return hmac.Hash; } } private static HMAC GetHmacByBitness(int bitness, byte[] keyBytes) { switch (bitness) { case 256: return new HMACSHA256(keyBytes); case 512: return new HMACSHA512(keyBytes); default: throw new ArgumentOutOfRangeException($"The bitness {bitness} is unsupported."); // should not be reached } } private static bool Hmac( IntPtr key, IntPtr @in, IntPtr @out, IntPtr statusPtr, int bitness) { using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) { try { var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); var inBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); var outBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); var keyBytes = keyBinary.ToArray(); var inBytes = inBinary.ToArray(); var outBytes = CalculateHash(keyBytes, inBytes, bitness: bitness); outBinary.WriteBytes(outBytes); return true; } catch (Exception ex) { // let mongocrypt level to handle the error status.SetStatus(1, ex.Message); return false; } } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/IStatus.cs000066400000000000000000000015101454530651600246630ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace MongoDB.Libmongocrypt { /// /// Interface for checking the status of the various libmongocrypt options. /// internal interface IStatus { void Check(Status status); } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/KmsCredentials.cs000066400000000000000000000033631454530651600262070ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; namespace MongoDB.Libmongocrypt { /// /// KMS Credentials. /// public class KmsCredentials { private readonly byte[] _credentialsBytes; /// /// Creates a class. /// /// The byte representation of credentials bson document. public KmsCredentials(byte[] credentialsBytes) { _credentialsBytes = credentialsBytes ?? throw new ArgumentNullException(nameof(credentialsBytes)); } // internal methods internal void SetCredentials(MongoCryptSafeHandle handle, Status status) { unsafe { fixed (byte* p = _credentialsBytes) { IntPtr ptr = (IntPtr)p; using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)_credentialsBytes.Length)) { handle.Check(status, Library.mongocrypt_setopt_kms_providers(handle, pinned.Handle)); } } } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/KmsKeyId.cs000066400000000000000000000064431454530651600247610ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Collections.Generic; using System.Linq; namespace MongoDB.Libmongocrypt { /// /// Represent a kms key. /// public class KmsKeyId { private readonly IReadOnlyList _alternateKeyNameBytes; private readonly byte[] _dataKeyOptionsBytes; private readonly byte[] _keyMaterialBytes; /// /// Creates an class. /// /// The byte representation of dataOptions bson document. /// The byte representation of alternate keyName. public KmsKeyId( byte[] dataKeyOptionsBytes, IEnumerable alternateKeyNameBytes = null, byte[] keyMaterialBytes = null) { _dataKeyOptionsBytes = dataKeyOptionsBytes; _alternateKeyNameBytes = (alternateKeyNameBytes ?? Enumerable.Empty()).ToList().AsReadOnly(); _keyMaterialBytes = keyMaterialBytes; } /// /// Alternate key name bytes. /// public IReadOnlyList AlternateKeyNameBytes => _alternateKeyNameBytes; /// /// Data key options bytes. /// public byte[] DataKeyOptionsBytes => _dataKeyOptionsBytes; /// /// Key material bytes. /// public byte[] KeyMaterialBytes => _keyMaterialBytes; // internal methods internal void SetCredentials(ContextSafeHandle context, Status status) { if (_dataKeyOptionsBytes != null) { PinnedBinary.RunAsPinnedBinary(context, _dataKeyOptionsBytes, status, (h, pb) => Library.mongocrypt_ctx_setopt_key_encryption_key(h, pb)); } SetAlternateKeyNamesIfConfigured(context, status); SetKeyMaterialIfConfigured(context, status); } // private methods private void SetAlternateKeyNamesIfConfigured(ContextSafeHandle context, Status status) { foreach (var alternateKeyNameBytes in _alternateKeyNameBytes) { PinnedBinary.RunAsPinnedBinary(context, alternateKeyNameBytes, status, (h, pb) => Library.mongocrypt_ctx_setopt_key_alt_name(h, pb)); } } private void SetKeyMaterialIfConfigured(ContextSafeHandle context, Status status) { if (_keyMaterialBytes != null) { PinnedBinary.RunAsPinnedBinary(context, _keyMaterialBytes, status, (h, pb) => Library.mongocrypt_ctx_setopt_key_material(h, pb)); } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/KmsRequest.cs000066400000000000000000000070151454530651600254000ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// Contains a KMS request to make to a remote server. /// /// public class KmsRequest : IStatus { private readonly Status _status; private readonly IntPtr _id; internal KmsRequest(IntPtr id) { _id = id; _status = new Status(); } /// /// Gets the bytes needed from the remote side. No more data is need when this returns 0. /// /// /// The number of bytes needed. /// public uint BytesNeeded { get { return Library.mongocrypt_kms_ctx_bytes_needed(_id); } } /// /// Gets the endpoint. /// /// /// The endpoint. /// public string Endpoint { get { IntPtr stringPointer = IntPtr.Zero; Check(Library.mongocrypt_kms_ctx_endpoint(_id, ref stringPointer)); return Marshal.PtrToStringAnsi(stringPointer); } } /// /// Gets the kms provider name. /// /// /// The kms provider name. /// public string KmsProvider { get { var kmsProviderNamePointer = Library.mongocrypt_kms_ctx_get_kms_provider(_id, length: out _); return Marshal.PtrToStringAnsi(kmsProviderNamePointer); } } /// /// Gets the message to send to KMS. /// /// The message public Binary Message { get { Binary binary = new Binary(); Check(Library.mongocrypt_kms_ctx_message(_id, binary.Handle)); return binary; } } /// /// Feeds the response back to the libmongocrypt /// /// The response. public void Feed(byte[] buffer) { unsafe { fixed (byte* p = buffer) { IntPtr ptr = (IntPtr)p; using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) { Check(Library.mongocrypt_kms_ctx_feed(_id, pinned.Handle)); } } } } void IStatus.Check(Status status) { Library.mongocrypt_kms_ctx_status(_id, status.Handle); } private void Check(bool success) { if (!success) { _status.Check(this); } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/KmsRequestCollection.cs000066400000000000000000000034531454530651600274160ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; namespace MongoDB.Libmongocrypt { /// /// A collection of kms requests to make. /// /// When all requests are done, MarkDone most be called. /// /// public class KmsRequestCollection : IReadOnlyCollection { private List _requests; private CryptContext _parent; internal KmsRequestCollection(List requests, CryptContext parent) { _requests = requests; _parent = parent; } int IReadOnlyCollection.Count => _requests.Count; IEnumerator IEnumerable.GetEnumerator() { return _requests.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _requests.GetEnumerator(); } /// /// Marks alls the KMS requests as complete. /// public void MarkDone() { _parent.MarkKmsDone(); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/Library.cs000066400000000000000000001364111454530651600247040ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// The low-level interface to libmongocrypt. /// public class Library { static Library() { _mongocrypt_version = new Lazy( () => __loader.Value.GetFunction("mongocrypt_version"), true); _mongocrypt_new = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_new")), true); _mongocrypt_setopt_log_handler = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_log_handler")), true); _mongocrypt_init = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_init")), true); _mongocrypt_destroy = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_destroy")), true); _mongocrypt_status = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status")), true); _mongocrypt_setopt_kms_providers = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_kms_providers")), true); _mongocrypt_ctx_setopt_key_encryption_key = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_key_encryption_key")), true); _mongocrypt_setopt_aes_256_ecb = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_aes_256_ecb")), true); _mongocrypt_setopt_bypass_query_analysis = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_bypass_query_analysis")), true); _mongocrypt_setopt_crypto_hooks = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_crypto_hooks")), true); _mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5")), true); _mongocrypt_setopt_encrypted_field_config_map = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_encrypted_field_config_map")), true); _mongocrypt_setopt_schema_map = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_setopt_schema_map")), true); _mongocrypt_setopt_append_crypt_shared_lib_search_path = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_setopt_append_crypt_shared_lib_search_path")), true); _mongocrypt_setopt_set_crypt_shared_lib_path_override = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_setopt_set_crypt_shared_lib_path_override")), true); _mongocrypt_setopt_use_need_kms_credentials_state = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_setopt_use_need_kms_credentials_state")), true); _mongocrypt_crypt_shared_lib_version_string = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_crypt_shared_lib_version_string")), true); _mongocrypt_crypt_shared_lib_version = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_crypt_shared_lib_version")), true); _mongocrypt_status_new = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status_new")), true); _mongocrypt_status_destroy = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status_destroy")), true); _mongocrypt_status_type = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status_type")), true); _mongocrypt_status_code = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status_code")), true); _mongocrypt_status_message = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status_message")), true); _mongocrypt_status_ok = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status_ok")), true); _mongocrypt_status_set = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_status_set")), true); _mongocrypt_binary_new = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_binary_new")), true); _mongocrypt_binary_destroy = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_binary_destroy")), true); _mongocrypt_binary_new_from_data = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_binary_new_from_data")), true); _mongocrypt_binary_data = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_binary_data")), true); _mongocrypt_binary_len = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_binary_len")), true); _mongocrypt_ctx_new = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_new")), true); _mongocrypt_ctx_setopt_key_material = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_key_material")), true); _mongocrypt_ctx_setopt_masterkey_aws = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_masterkey_aws")), true); _mongocrypt_ctx_setopt_masterkey_aws_endpoint = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_masterkey_aws_endpoint")), true); _mongocrypt_ctx_setopt_masterkey_local = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_masterkey_local")), true); _mongocrypt_ctx_setopt_key_alt_name = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_key_alt_name")), true); _mongocrypt_ctx_setopt_key_id = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_key_id")), true); _mongocrypt_ctx_setopt_algorithm = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_algorithm")), true); _mongocrypt_ctx_setopt_algorithm_range = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_algorithm_range")), true); _mongocrypt_ctx_setopt_contention_factor = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_contention_factor")), true); _mongocrypt_ctx_setopt_query_type = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_query_type")), true); _mongocrypt_ctx_status = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_status")), true); _mongocrypt_ctx_encrypt_init = new Lazy( () => __loader.Value .GetFunction(("mongocrypt_ctx_encrypt_init")), true); _mongocrypt_ctx_decrypt_init = new Lazy( () => __loader.Value .GetFunction(("mongocrypt_ctx_decrypt_init")), true); _mongocrypt_ctx_explicit_encrypt_init = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_explicit_encrypt_init")), true); _mongocrypt_ctx_explicit_encrypt_expression_init = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_explicit_encrypt_expression_init")), true); _mongocrypt_ctx_explicit_decrypt_init = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_explicit_decrypt_init")), true); _mongocrypt_ctx_datakey_init = new Lazy( () => __loader.Value .GetFunction(("mongocrypt_ctx_datakey_init")), true); _mongocrypt_ctx_provide_kms_providers = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_provide_kms_providers")), true); _mongocrypt_ctx_state = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_state")), true); _mongocrypt_ctx_mongo_op = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_mongo_op")), true); _mongocrypt_ctx_mongo_feed = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_mongo_feed")), true); _mongocrypt_ctx_mongo_done = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_mongo_done")), true); _mongocrypt_ctx_next_kms_ctx = new Lazy( () => __loader.Value .GetFunction(("mongocrypt_ctx_next_kms_ctx")), true); _mongocrypt_ctx_rewrap_many_datakey_init = new Lazy( () => __loader.Value .GetFunction(("mongocrypt_ctx_rewrap_many_datakey_init")), true); _mongocrypt_kms_ctx_endpoint = new Lazy( () => __loader.Value .GetFunction(("mongocrypt_kms_ctx_endpoint")), true); _mongocrypt_kms_ctx_message = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_message")), true); _mongocrypt_kms_ctx_bytes_needed = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_kms_ctx_bytes_needed")), true); _mongocrypt_kms_ctx_feed = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_feed")), true); _mongocrypt_kms_ctx_status = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_status")), true); _mongocrypt_ctx_kms_done = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_kms_done")), true); _mongocrypt_ctx_finalize = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_finalize")), true); _mongocrypt_ctx_destroy = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_ctx_destroy")), true); _mongocrypt_kms_ctx_get_kms_provider = new Lazy( () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_get_kms_provider")), true); } /// /// Gets the version of libmongocrypt. /// /// /// The version. /// public static string Version { get { uint length; IntPtr p = mongocrypt_version(out length); return Marshal.PtrToStringAnsi(p); } } internal static Delegates.mongocrypt_version mongocrypt_version => _mongocrypt_version.Value; internal static Delegates.mongocrypt_new mongocrypt_new => _mongocrypt_new.Value; internal static Delegates.mongocrypt_setopt_log_handler mongocrypt_setopt_log_handler => _mongocrypt_setopt_log_handler.Value; internal static Delegates.mongocrypt_setopt_kms_providers mongocrypt_setopt_kms_providers => _mongocrypt_setopt_kms_providers.Value; internal static Delegates.mongocrypt_ctx_setopt_key_encryption_key mongocrypt_ctx_setopt_key_encryption_key => _mongocrypt_ctx_setopt_key_encryption_key.Value; internal static Delegates.mongocrypt_setopt_aes_256_ecb mongocrypt_setopt_aes_256_ecb => _mongocrypt_setopt_aes_256_ecb.Value; internal static Delegates.mongocrypt_setopt_bypass_query_analysis mongocrypt_setopt_bypass_query_analysis => _mongocrypt_setopt_bypass_query_analysis.Value; internal static Delegates.mongocrypt_setopt_crypto_hooks mongocrypt_setopt_crypto_hooks => _mongocrypt_setopt_crypto_hooks.Value; internal static Delegates.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 => _mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5.Value; internal static Delegates.mongocrypt_setopt_encrypted_field_config_map mongocrypt_setopt_encrypted_field_config_map => _mongocrypt_setopt_encrypted_field_config_map.Value; internal static Delegates.mongocrypt_setopt_schema_map mongocrypt_setopt_schema_map => _mongocrypt_setopt_schema_map.Value; internal static Delegates.mongocrypt_setopt_append_crypt_shared_lib_search_path mongocrypt_setopt_append_crypt_shared_lib_search_path => _mongocrypt_setopt_append_crypt_shared_lib_search_path.Value; internal static Delegates.mongocrypt_setopt_set_crypt_shared_lib_path_override mongocrypt_setopt_set_crypt_shared_lib_path_override => _mongocrypt_setopt_set_crypt_shared_lib_path_override.Value; internal static Delegates.mongocrypt_setopt_use_need_kms_credentials_state mongocrypt_setopt_use_need_kms_credentials_state => _mongocrypt_setopt_use_need_kms_credentials_state.Value; internal static Delegates.mongocrypt_crypt_shared_lib_version_string mongocrypt_crypt_shared_lib_version_string => _mongocrypt_crypt_shared_lib_version_string.Value; internal static Delegates.mongocrypt_crypt_shared_lib_version mongocrypt_crypt_shared_lib_version => _mongocrypt_crypt_shared_lib_version.Value; internal static Delegates.mongocrypt_init mongocrypt_init => _mongocrypt_init.Value; internal static Delegates.mongocrypt_destroy mongocrypt_destroy => _mongocrypt_destroy.Value; internal static Delegates.mongocrypt_status mongocrypt_status => _mongocrypt_status.Value; internal static Delegates.mongocrypt_status_new mongocrypt_status_new => _mongocrypt_status_new.Value; internal static Delegates.mongocrypt_status_destroy mongocrypt_status_destroy => _mongocrypt_status_destroy.Value; internal static Delegates.mongocrypt_status_type mongocrypt_status_type => _mongocrypt_status_type.Value; internal static Delegates.mongocrypt_status_code mongocrypt_status_code => _mongocrypt_status_code.Value; internal static Delegates.mongocrypt_status_message mongocrypt_status_message => _mongocrypt_status_message.Value; internal static Delegates.mongocrypt_status_ok mongocrypt_status_ok => _mongocrypt_status_ok.Value; internal static Delegates.mongocrypt_status_set mongocrypt_status_set => _mongocrypt_status_set.Value; internal static Delegates.mongocrypt_binary_new mongocrypt_binary_new => _mongocrypt_binary_new.Value; internal static Delegates.mongocrypt_binary_destroy mongocrypt_binary_destroy => _mongocrypt_binary_destroy.Value; internal static Delegates.mongocrypt_binary_new_from_data mongocrypt_binary_new_from_data => _mongocrypt_binary_new_from_data.Value; internal static Delegates.mongocrypt_binary_data mongocrypt_binary_data => _mongocrypt_binary_data.Value; internal static Delegates.mongocrypt_binary_len mongocrypt_binary_len => _mongocrypt_binary_len.Value; internal static Delegates.mongocrypt_ctx_new mongocrypt_ctx_new => _mongocrypt_ctx_new.Value; internal static Delegates.mongocrypt_ctx_setopt_key_material mongocrypt_ctx_setopt_key_material => _mongocrypt_ctx_setopt_key_material.Value; internal static Delegates.mongocrypt_ctx_setopt_masterkey_aws mongocrypt_ctx_setopt_masterkey_aws => _mongocrypt_ctx_setopt_masterkey_aws.Value; internal static Delegates.mongocrypt_ctx_setopt_masterkey_aws_endpoint mongocrypt_ctx_setopt_masterkey_aws_endpoint => _mongocrypt_ctx_setopt_masterkey_aws_endpoint.Value; internal static Delegates.mongocrypt_ctx_status mongocrypt_ctx_status => _mongocrypt_ctx_status.Value; internal static Delegates.mongocrypt_ctx_encrypt_init mongocrypt_ctx_encrypt_init => _mongocrypt_ctx_encrypt_init.Value; internal static Delegates.mongocrypt_ctx_decrypt_init mongocrypt_ctx_decrypt_init => _mongocrypt_ctx_decrypt_init.Value; internal static Delegates.mongocrypt_ctx_explicit_encrypt_init mongocrypt_ctx_explicit_encrypt_init => _mongocrypt_ctx_explicit_encrypt_init.Value; internal static Delegates.mongocrypt_ctx_explicit_encrypt_expression_init mongocrypt_ctx_explicit_encrypt_expression_init => _mongocrypt_ctx_explicit_encrypt_expression_init.Value; internal static Delegates.mongocrypt_ctx_explicit_decrypt_init mongocrypt_ctx_explicit_decrypt_init => _mongocrypt_ctx_explicit_decrypt_init.Value; internal static Delegates.mongocrypt_ctx_datakey_init mongocrypt_ctx_datakey_init => _mongocrypt_ctx_datakey_init.Value; internal static Delegates.mongocrypt_ctx_provide_kms_providers mongocrypt_ctx_provide_kms_providers => _mongocrypt_ctx_provide_kms_providers.Value; internal static Delegates.mongocrypt_ctx_setopt_masterkey_local mongocrypt_ctx_setopt_masterkey_local => _mongocrypt_ctx_setopt_masterkey_local.Value; internal static Delegates.mongocrypt_ctx_setopt_key_id mongocrypt_ctx_setopt_key_id => _mongocrypt_ctx_setopt_key_id.Value; internal static Delegates.mongocrypt_ctx_setopt_key_alt_name mongocrypt_ctx_setopt_key_alt_name => _mongocrypt_ctx_setopt_key_alt_name.Value; internal static Delegates.mongocrypt_ctx_setopt_algorithm mongocrypt_ctx_setopt_algorithm => _mongocrypt_ctx_setopt_algorithm.Value; internal static Delegates.mongocrypt_ctx_setopt_algorithm_range mongocrypt_ctx_setopt_algorithm_range => _mongocrypt_ctx_setopt_algorithm_range.Value; internal static Delegates.mongocrypt_ctx_setopt_contention_factor mongocrypt_ctx_setopt_contention_factor => _mongocrypt_ctx_setopt_contention_factor.Value; internal static Delegates.mongocrypt_ctx_setopt_query_type mongocrypt_ctx_setopt_query_type => _mongocrypt_ctx_setopt_query_type.Value; internal static Delegates.mongocrypt_ctx_state mongocrypt_ctx_state => _mongocrypt_ctx_state.Value; internal static Delegates.mongocrypt_ctx_mongo_op mongocrypt_ctx_mongo_op => _mongocrypt_ctx_mongo_op.Value; internal static Delegates.mongocrypt_ctx_mongo_feed mongocrypt_ctx_mongo_feed => _mongocrypt_ctx_mongo_feed.Value; internal static Delegates.mongocrypt_ctx_mongo_done mongocrypt_ctx_mongo_done => _mongocrypt_ctx_mongo_done.Value; internal static Delegates.mongocrypt_ctx_next_kms_ctx mongocrypt_ctx_next_kms_ctx => _mongocrypt_ctx_next_kms_ctx.Value; internal static Delegates.mongocrypt_ctx_rewrap_many_datakey_init mongocrypt_ctx_rewrap_many_datakey_init => _mongocrypt_ctx_rewrap_many_datakey_init.Value; internal static Delegates.mongocrypt_kms_ctx_endpoint mongocrypt_kms_ctx_endpoint => _mongocrypt_kms_ctx_endpoint.Value; internal static Delegates.mongocrypt_kms_ctx_message mongocrypt_kms_ctx_message => _mongocrypt_kms_ctx_message.Value; internal static Delegates.mongocrypt_kms_ctx_bytes_needed mongocrypt_kms_ctx_bytes_needed => _mongocrypt_kms_ctx_bytes_needed.Value; internal static Delegates.mongocrypt_kms_ctx_feed mongocrypt_kms_ctx_feed => _mongocrypt_kms_ctx_feed.Value; internal static Delegates.mongocrypt_kms_ctx_status mongocrypt_kms_ctx_status => _mongocrypt_kms_ctx_status.Value; internal static Delegates.mongocrypt_ctx_kms_done mongocrypt_ctx_kms_done => _mongocrypt_ctx_kms_done.Value; internal static Delegates.mongocrypt_ctx_finalize mongocrypt_ctx_finalize => _mongocrypt_ctx_finalize.Value; internal static Delegates.mongocrypt_ctx_destroy mongocrypt_ctx_destroy => _mongocrypt_ctx_destroy.Value; internal static Delegates.mongocrypt_kms_ctx_get_kms_provider mongocrypt_kms_ctx_get_kms_provider => _mongocrypt_kms_ctx_get_kms_provider.Value; private static readonly Lazy __loader = new Lazy( () => new LibraryLoader(), true); private static readonly Lazy _mongocrypt_version; private static readonly Lazy _mongocrypt_new; private static readonly Lazy _mongocrypt_setopt_log_handler; private static readonly Lazy _mongocrypt_setopt_kms_providers; private static readonly Lazy _mongocrypt_ctx_setopt_key_encryption_key; private static readonly Lazy _mongocrypt_setopt_aes_256_ecb; private static readonly Lazy _mongocrypt_setopt_bypass_query_analysis; private static readonly Lazy _mongocrypt_setopt_crypto_hooks; private static readonly Lazy _mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5; private static readonly Lazy _mongocrypt_setopt_encrypted_field_config_map; private static readonly Lazy _mongocrypt_setopt_schema_map; private static readonly Lazy _mongocrypt_setopt_append_crypt_shared_lib_search_path; private static readonly Lazy _mongocrypt_setopt_set_crypt_shared_lib_path_override; private static readonly Lazy _mongocrypt_setopt_use_need_kms_credentials_state; private static readonly Lazy _mongocrypt_crypt_shared_lib_version_string; private static readonly Lazy _mongocrypt_crypt_shared_lib_version; private static readonly Lazy _mongocrypt_init; private static readonly Lazy _mongocrypt_destroy; private static readonly Lazy _mongocrypt_status; private static readonly Lazy _mongocrypt_status_new; private static readonly Lazy _mongocrypt_status_destroy; private static readonly Lazy _mongocrypt_status_type; private static readonly Lazy _mongocrypt_status_code; private static readonly Lazy _mongocrypt_status_message; private static readonly Lazy _mongocrypt_status_ok; private static readonly Lazy _mongocrypt_status_set; private static readonly Lazy _mongocrypt_binary_new; private static readonly Lazy _mongocrypt_binary_destroy; private static readonly Lazy _mongocrypt_binary_new_from_data; private static readonly Lazy _mongocrypt_binary_data; private static readonly Lazy _mongocrypt_binary_len; private static readonly Lazy _mongocrypt_ctx_new; private static readonly Lazy _mongocrypt_ctx_setopt_key_material; private static readonly Lazy _mongocrypt_ctx_setopt_masterkey_aws; private static readonly Lazy _mongocrypt_ctx_setopt_masterkey_aws_endpoint; private static readonly Lazy _mongocrypt_ctx_status; private static readonly Lazy _mongocrypt_ctx_encrypt_init; private static readonly Lazy _mongocrypt_ctx_decrypt_init; private static readonly Lazy _mongocrypt_ctx_explicit_encrypt_init; private static readonly Lazy _mongocrypt_ctx_explicit_encrypt_expression_init; private static readonly Lazy _mongocrypt_ctx_explicit_decrypt_init; private static readonly Lazy _mongocrypt_ctx_datakey_init; private static readonly Lazy _mongocrypt_ctx_provide_kms_providers; private static readonly Lazy _mongocrypt_ctx_setopt_masterkey_local; private static readonly Lazy _mongocrypt_ctx_setopt_key_id; private static readonly Lazy _mongocrypt_ctx_setopt_key_alt_name; private static readonly Lazy _mongocrypt_ctx_setopt_algorithm; private static readonly Lazy _mongocrypt_ctx_setopt_algorithm_range; private static readonly Lazy _mongocrypt_ctx_setopt_contention_factor; private static readonly Lazy _mongocrypt_ctx_setopt_query_type; private static readonly Lazy _mongocrypt_ctx_state; private static readonly Lazy _mongocrypt_ctx_mongo_op; private static readonly Lazy _mongocrypt_ctx_mongo_feed; private static readonly Lazy _mongocrypt_ctx_mongo_done; private static readonly Lazy _mongocrypt_ctx_next_kms_ctx; private static readonly Lazy _mongocrypt_ctx_rewrap_many_datakey_init; private static readonly Lazy _mongocrypt_kms_ctx_endpoint; private static readonly Lazy _mongocrypt_kms_ctx_message; private static readonly Lazy _mongocrypt_kms_ctx_bytes_needed; private static readonly Lazy _mongocrypt_kms_ctx_feed; private static readonly Lazy _mongocrypt_kms_ctx_status; private static readonly Lazy _mongocrypt_ctx_kms_done; private static readonly Lazy _mongocrypt_ctx_finalize; private static readonly Lazy _mongocrypt_ctx_destroy; private static readonly Lazy _mongocrypt_kms_ctx_get_kms_provider; // nested types internal enum StatusType { MONGOCRYPT_STATUS_OK = 0, MONGOCRYPT_STATUS_ERROR_CLIENT, MONGOCRYPT_STATUS_ERROR_KMS } internal class Delegates { // NOTE: Bool is expected to be 4 bytes during marshalling so we need to overwite it // https://blogs.msdn.microsoft.com/jaredpar/2008/10/14/pinvoke-and-bool-or-should-i-say-bool/ public delegate IntPtr mongocrypt_version(out uint length); public delegate MongoCryptSafeHandle mongocrypt_new(); public delegate void LogCallback([MarshalAs(UnmanagedType.I4)] LogLevel level, IntPtr messasge, uint message_length, IntPtr context); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_setopt_log_handler(MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.FunctionPtr)] LogCallback log_fn, IntPtr log_ctx); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_setopt_kms_providers( MongoCryptSafeHandle handle, BinarySafeHandle kms_providers); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_key_encryption_key( ContextSafeHandle handle, BinarySafeHandle bin); [return: MarshalAs(UnmanagedType.I1)] public delegate bool HashCallback( IntPtr ctx, IntPtr @in, IntPtr @out, IntPtr status); [return: MarshalAs(UnmanagedType.I1)] public delegate bool CryptoHmacCallback( IntPtr ctx, IntPtr key, IntPtr @in, IntPtr @out, IntPtr status); /// /// typedef bool (*mongocrypt_crypto_fn) ( /// void *ctx, // mongocrypt_binary_t* key, // mongocrypt_binary_t *iv, // mongocrypt_binary_t*in, // mongocrypt_binary_t*out, // uint32_t* bytes_written, // mongocrypt_status_t *status); /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool CryptoCallback( IntPtr ctx, IntPtr key, IntPtr iv, IntPtr @in, IntPtr @out, ref uint bytes_written, IntPtr status); [return: MarshalAs(UnmanagedType.I1)] public delegate bool RandomCallback( IntPtr ctx, IntPtr @out, uint count, IntPtr statusPtr); /// /// bool mongocrypt_setopt_aes_256_ecb(mongocrypt_t* crypt, mongocrypt_crypto_fn aes_256_ecb_encrypt, void* ctx); /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_setopt_aes_256_ecb( MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.FunctionPtr)] CryptoCallback aes_256_ecb_encrypt, IntPtr ctx); /// /// void mongocrypt_setopt_bypass_query_analysis(mongocrypt_t* crypt); /// public delegate void mongocrypt_setopt_bypass_query_analysis(MongoCryptSafeHandle handle); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_setopt_crypto_hooks( MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.FunctionPtr)] CryptoCallback aes_256_cbc_encrypt, [MarshalAs(UnmanagedType.FunctionPtr)] CryptoCallback aes_256_cbc_decrypt, [MarshalAs(UnmanagedType.FunctionPtr)] RandomCallback random, [MarshalAs(UnmanagedType.FunctionPtr)] CryptoHmacCallback hmac_sha_512, [MarshalAs(UnmanagedType.FunctionPtr)] CryptoHmacCallback hmac_sha_256, [MarshalAs(UnmanagedType.FunctionPtr)] HashCallback mongocrypt_hash_fn, IntPtr ctx); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.FunctionPtr)] CryptoHmacCallback sign_rsaes_pkcs1_v1_5, IntPtr sign_ctx); /// /// bool mongocrypt_setopt_encrypted_field_config_map(mongocrypt_t* crypt, mongocrypt_binary_t* efc_map) /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_setopt_encrypted_field_config_map(MongoCryptSafeHandle handle, BinarySafeHandle efc_map); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_setopt_schema_map(MongoCryptSafeHandle handle, BinarySafeHandle schema); /// /// void mongocrypt_setopt_append_crypt_shared_lib_search_path(mongocrypt_t* crypt, const char* path); /// public delegate void mongocrypt_setopt_append_crypt_shared_lib_search_path(MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.LPStr)] string path); /// /// void mongocrypt_setopt_set_crypt_shared_lib_path_override(mongocrypt_t* crypt, const char* path); /// public delegate void mongocrypt_setopt_set_crypt_shared_lib_path_override(MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.LPStr)] string path); /// /// void mongocrypt_setopt_use_need_kms_credentials_state(mongocrypt_t* crypt); /// /// public delegate void mongocrypt_setopt_use_need_kms_credentials_state(MongoCryptSafeHandle handle); /// /// const char * mongocrypt_crypt_shared_lib_version_string(const mongocrypt_t* crypt, uint32_t *len); /// public delegate IntPtr mongocrypt_crypt_shared_lib_version_string(MongoCryptSafeHandle handle, out uint length); /// /// uint64_t mongocrypt_crypt_shared_lib_version(const mongocrypt_t* crypt); /// public delegate ulong mongocrypt_crypt_shared_lib_version(MongoCryptSafeHandle handle); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_init(MongoCryptSafeHandle handle); public delegate void mongocrypt_destroy(IntPtr ptr); public delegate bool mongocrypt_status(MongoCryptSafeHandle handle, StatusSafeHandle ptr); public delegate StatusSafeHandle mongocrypt_status_new(); public delegate void mongocrypt_status_destroy(IntPtr ptr); public delegate StatusType mongocrypt_status_type(StatusSafeHandle ptr); public delegate uint mongocrypt_status_code(StatusSafeHandle ptr); public delegate IntPtr mongocrypt_status_message(StatusSafeHandle ptr, out uint length); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_status_ok(StatusSafeHandle ptr); // currently it does nothing due to MONGOCRYPT-257 public delegate void mongocrypt_status_set(StatusSafeHandle ptr, int type, uint code, IntPtr msg, int length); public delegate BinarySafeHandle mongocrypt_binary_new(); public delegate void mongocrypt_binary_destroy(IntPtr ptr); public delegate BinarySafeHandle mongocrypt_binary_new_from_data(IntPtr ptr, uint len); public delegate IntPtr mongocrypt_binary_data(BinarySafeHandle handle); public delegate uint mongocrypt_binary_len(BinarySafeHandle handle); public delegate ContextSafeHandle mongocrypt_ctx_new(MongoCryptSafeHandle handle); /// /// bool mongocrypt_ctx_setopt_key_material(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* key_material) /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_key_material(ContextSafeHandle handle, BinarySafeHandle key_material); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_masterkey_aws(ContextSafeHandle handle, IntPtr region, int region_len, IntPtr cmk, int cmk_len); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_masterkey_aws_endpoint( ContextSafeHandle handle, IntPtr endpoint, int endpoint_len); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_status(ContextSafeHandle handle, StatusSafeHandle status); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_encrypt_init(ContextSafeHandle handle, IntPtr ns, int length, BinarySafeHandle binary); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_decrypt_init(ContextSafeHandle handle, BinarySafeHandle binary); /// /// bool mongocrypt_ctx_explicit_encrypt_init(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* msg) /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_explicit_encrypt_init(ContextSafeHandle handle, BinarySafeHandle binary); /// /// bool mongocrypt_ctx_explicit_encrypt_expression_init(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* msg) /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_explicit_encrypt_expression_init(ContextSafeHandle handle, BinarySafeHandle msg); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_explicit_decrypt_init(ContextSafeHandle handle, BinarySafeHandle binary); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_datakey_init(ContextSafeHandle handle); /// /// bool mongocrypt_ctx_provide_kms_providers(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* kms_providers_definition); /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_provide_kms_providers(ContextSafeHandle handle, BinarySafeHandle kms_providers_definition); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_schema_map(ContextSafeHandle handle, BinarySafeHandle binary); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_masterkey_local(ContextSafeHandle handle); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_key_alt_name(ContextSafeHandle handle, BinarySafeHandle binary); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_key_id(ContextSafeHandle handle, BinarySafeHandle binary); /// /// bool mongocrypt_ctx_setopt_algorithm(mongocrypt_ctx_t* ctx, const char* algorithm, int len); /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_algorithm(ContextSafeHandle handle, [MarshalAs(UnmanagedType.LPStr)] string algorithm, int length); /// /// bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* opts); /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_algorithm_range(ContextSafeHandle handle, BinarySafeHandle opts); /// /// bool mongocrypt_ctx_setopt_contention_factor(mongocrypt_ctx_t* ctx, int64_t contention_factor); /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_contention_factor(ContextSafeHandle ctx, long contention_factor); /// /// bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t* ctx, const char* query_type, int len) /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_setopt_query_type(ContextSafeHandle ctx, [MarshalAs(UnmanagedType.LPStr)] string query_type, int length); public delegate CryptContext.StateCode mongocrypt_ctx_state(ContextSafeHandle handle); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_mongo_op(ContextSafeHandle handle, BinarySafeHandle bsonOp); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_mongo_feed(ContextSafeHandle handle, BinarySafeHandle reply); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_mongo_done(ContextSafeHandle handle); public delegate IntPtr mongocrypt_ctx_next_kms_ctx(ContextSafeHandle handle); /// /// bool mongocrypt_ctx_rewrap_many_datakey_init(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* filter); /// [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_rewrap_many_datakey_init(ContextSafeHandle handle, BinarySafeHandle filter); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_kms_ctx_endpoint(IntPtr handle, ref IntPtr endpoint); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_kms_ctx_message(IntPtr handle, BinarySafeHandle binary); public delegate uint mongocrypt_kms_ctx_bytes_needed(IntPtr handle); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_kms_ctx_feed(IntPtr handle, BinarySafeHandle binary); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_kms_ctx_status(IntPtr handle, StatusSafeHandle status); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_kms_done(ContextSafeHandle handle); [return: MarshalAs(UnmanagedType.I1)] public delegate bool mongocrypt_ctx_finalize(ContextSafeHandle handle, BinarySafeHandle binary); public delegate void mongocrypt_ctx_destroy(IntPtr ptr); public delegate IntPtr mongocrypt_kms_ctx_get_kms_provider(IntPtr handle, out uint length); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs000066400000000000000000000223151454530651600260300ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// LibraryLoader abstracts loading C functions from a shared library across OS /// internal class LibraryLoader { private ISharedLibraryLoader _loader; public LibraryLoader() { if (!Environment.Is64BitProcess) { throw new PlatformNotSupportedException($"{this.GetType().Namespace} needs to be run in a 64-bit process."); } // Windows: // https://stackoverflow.com/questions/2864673/specify-the-search-path-for-dllimport-in-net // // See for better ways // https://github.com/dotnet/coreclr/issues/930 // https://github.com/dotnet/corefx/issues/32015 List candidatePaths = new List(); // In the nuget package, get the shared library from a relative path of this assembly // Also, when running locally, get the shared library from a relative path of this assembly var assembly = typeof(LibraryLoader).GetTypeInfo().Assembly; var location = assembly.Location; string basepath = Path.GetDirectoryName(location); candidatePaths.Add(basepath); switch (OperatingSystemHelper.CurrentOperatingSystem) { case OperatingSystemPlatform.MacOS: { string[] suffixPaths = new[] { "../../runtimes/osx/native/", "runtimes/osx/native/", string.Empty }; string path = FindLibrary(candidatePaths, suffixPaths, "libmongocrypt.dylib"); _loader = new DarwinLibraryLoader(path); } break; case OperatingSystemPlatform.Linux: { string[] suffixPaths = new[] { "../../runtimes/linux/native/", "runtimes/linux/native/", string.Empty }; string path = FindLibrary(candidatePaths, suffixPaths, "libmongocrypt.so"); _loader = new LinuxLibrary(path); } break; case OperatingSystemPlatform.Windows: { string[] suffixPaths = new[] { @"..\..\runtimes\win\native\", @".\runtimes\win\native\", string.Empty }; string path = FindLibrary(candidatePaths, suffixPaths, "mongocrypt.dll"); _loader = new WindowsLibrary(path); } break; default: // should not be reached. If we're here, then there is a bug in OperatingSystemHelper throw new PlatformNotSupportedException("Unsupported operating system."); } } private string FindLibrary(IList basePaths, string[] suffixPaths, string library) { var candidates = new List(); foreach (var basePath in basePaths) { foreach (var suffix in suffixPaths) { string path = Path.Combine(basePath, suffix, library); if (File.Exists(path)) { return path; } candidates.Add(path); } } throw new FileNotFoundException("Could not find: " + library + " --\n Tried: " + string.Join(",", candidates)); } public T GetFunction(string name) { IntPtr ptr = _loader.GetFunction(name); if (ptr == IntPtr.Zero) { throw new FunctionNotFoundException(name); } return Marshal.GetDelegateForFunctionPointer(ptr); } public class FunctionNotFoundException : Exception { public FunctionNotFoundException(string message) : base(message) { } } private interface ISharedLibraryLoader { IntPtr GetFunction(string name); } /// /// macOS Dynamic Library loader using dlsym /// private class DarwinLibraryLoader : ISharedLibraryLoader { // See dlfcn.h // #define RTLD_LAZY 0x1 // #define RTLD_NOW 0x2 // #define RTLD_LOCAL 0x4 // #define RTLD_GLOBAL 0x8 public const int RTLD_GLOBAL = 0x8; public const int RTLD_NOW = 0x2; private readonly IntPtr _handle; public DarwinLibraryLoader(string path) { _handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); if (_handle == IntPtr.Zero) { throw new FileNotFoundException(path); } } public IntPtr GetFunction(string name) { return dlsym(_handle, name); } #pragma warning disable IDE1006 // Naming Styles [DllImport("libdl")] public static extern IntPtr dlopen(string filename, int flags); [DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern IntPtr dlsym(IntPtr handle, string symbol); #pragma warning restore IDE1006 // Naming Styles } /// /// Linux Shared Object loader using dlsym /// private class LinuxLibrary : ISharedLibraryLoader { // See dlfcn.h // #define RTLD_LAZY 0x1 // #define RTLD_NOW 0x2 // #define RTLD_LOCAL 0x4 // #define RTLD_GLOBAL 0x100 public const int RTLD_GLOBAL = 0x100; public const int RTLD_NOW = 0x2; private readonly IntPtr _handle; public LinuxLibrary(string path) { _handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); if (_handle == IntPtr.Zero) { throw new FileNotFoundException(path); } } public IntPtr GetFunction(string name) { return dlsym(_handle, name); } #pragma warning disable IDE1006 // Naming Styles [DllImport("libdl")] public static extern IntPtr dlopen(string filename, int flags); [DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern IntPtr dlsym(IntPtr handle, string symbol); #pragma warning restore IDE1006 // Naming Styles } /// /// Windows DLL loader using GetProcAddress /// private class WindowsLibrary : ISharedLibraryLoader { private readonly IntPtr _handle; public WindowsLibrary(string path) { _handle = LoadLibrary(path); if (_handle == IntPtr.Zero) { var gle = Marshal.GetLastWin32Error(); // error code 193 indicates that a 64-bit OS has tried to load a 32-bit dll // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- throw new LibraryLoadingException(path + ", Windows Error: " + gle); } } public IntPtr GetFunction(string name) { var ptr = GetProcAddress(_handle, name); if (ptr == null) { var gle = Marshal.GetLastWin32Error(); throw new FunctionNotFoundException(name + ", Windows Error: " + gle); } return ptr; } [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/LibraryLoadingException.cs000066400000000000000000000021301454530651600300470ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; namespace MongoDB.Libmongocrypt { /// /// An exception that indicates that an error occured while loading a library. /// public class LibraryLoadingException : Exception { /// /// Initializes an instance of a /// /// The message. public LibraryLoadingException(string message) : base(message) { } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/License.txt000066400000000000000000000011151454530651600250640ustar00rootroot00000000000000/* Copyright 2010–present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/LogLevel.cs000066400000000000000000000015571454530651600250130ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace MongoDB.Libmongocrypt { public enum LogLevel { MONGOCRYPT_LOG_LEVEL_FATAL = 0, MONGOCRYPT_LOG_LEVEL_ERROR = 1, MONGOCRYPT_LOG_LEVEL_WARNING = 2, MONGOCRYPT_LOG_LEVEL_INFO = 3, MONGOCRYPT_LOG_LEVEL_TRACE = 4 }; } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/MongoCryptSafeHandle.cs000066400000000000000000000030101454530651600273000ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Runtime.ConstrainedExecution; namespace MongoDB.Libmongocrypt { /// /// SafeHandle to manage the lifetime of a mongocrypt_t. /// /// internal class MongoCryptSafeHandle : CheckableSafeHandle { private MongoCryptSafeHandle() : base() { } public override void Check(Status status, bool success) { if (!success) { Library.mongocrypt_status(this, status.Handle); status.ThrowExceptionIfNeeded(); } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] protected override bool ReleaseHandle() { // Here, we must obey all rules for constrained execution regions. Library.mongocrypt_destroy(handle); return true; } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj000066400000000000000000000103621454530651600303030ustar00rootroot00000000000000 net472;netstandard2.0;netstandard2.1 netstandard2.0;netstandard2.1 AnyCPU 7.3 true MongoDB.Libmongocrypt.ruleset MongoDB.Libmongocrypt MongoDB.Libmongocrypt MongoDB Inc. Copyright © 2019–present MongoDB Inc. Libmongocrypt wrapper for the .NET driver. MongoDB Inc. http://jobs.mongodb.org/files/logos/889002/889002.png true Libmongocrypt wrapper for the .NET driver. http://www.mongodb.org/display/DOCS/CSharp+Language+Center License.txt mongodb;mongo;nosql en-US true ../../../cmake-build/$(Configuration) ../../../cmake-build/RelWithDebInfo/ libmongocrypt.so Always libmongocrypt.dylib Always mongocrypt.dll Always mongocrypt.pdb Always true runtimes/win/native true runtimes/linux/native true runtimes/osx/native true $(PackageLicenseFile) true build 1.1.0 bin\x64\Debug\MongoDB.Libmongocrypt.xml true bin\x64\Release\MongoDB.Libmongocrypt.xml libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.ruleset000066400000000000000000000076261454530651600304770ustar00rootroot00000000000000 libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.targets000066400000000000000000000017241454530651600304560ustar00rootroot00000000000000 Always mongocrypt.dll Always libmongocrypt.so Always libmongocrypt.dylib libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/OperatingSystemHelper.cs000066400000000000000000000034231454530651600275710ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if !NET472 using System; using System.Runtime.InteropServices; #endif namespace MongoDB.Libmongocrypt { internal enum OperatingSystemPlatform { Windows, Linux, MacOS } internal static class OperatingSystemHelper { public static OperatingSystemPlatform CurrentOperatingSystem { get { #if NET472 return OperatingSystemPlatform.Windows; #else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return OperatingSystemPlatform.MacOS; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return OperatingSystemPlatform.Linux; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return OperatingSystemPlatform.Windows; } // should not be reached. If we're here, then there is a bug in the library throw new PlatformNotSupportedException($"Unsupported platform '{RuntimeInformation.OSDescription}'."); #endif } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/Package.include.template.csproj000066400000000000000000000032211454530651600307520ustar00rootroot00000000000000 false @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt PreserveNewest x64/native/linux/libmongocrypt.so true PreserveNewest x64/native/osx/libmongocrypt.dylib true PreserveNewest x64/native/windows/mongocrypt.dll true PreserveNewest x64/native/windows/mongocrypt.dll true libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/PinnedBinary.cs000066400000000000000000000031421454530651600256540ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; namespace MongoDB.Libmongocrypt { /// /// A handle to a binary that must be either in unsafe code or pinned by the GC. /// /// internal class PinnedBinary : Binary { #region static internal static void RunAsPinnedBinary(THandle handle, byte[] bytes, Status status, Func handleFunc) where THandle : CheckableSafeHandle { unsafe { fixed (byte* map = bytes) { var ptr = (IntPtr)map; using (var pinned = new PinnedBinary(ptr, (uint)bytes.Length)) { handle.Check(status, handleFunc(handle, pinned.Handle)); } } } } #endregion internal PinnedBinary(IntPtr ptr, uint len) : base(Library.mongocrypt_binary_new_from_data(ptr, len)) { } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/SecureRandomCallback.cs000066400000000000000000000032021454530651600272730ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Security.Cryptography; namespace MongoDB.Libmongocrypt { internal static class SecureRandomCallback { public static bool GenerateRandom( IntPtr ctx, IntPtr @out, uint count, IntPtr statusPtr) { using (var outBinary = new Binary(BinarySafeHandle.FromIntPtr(@out))) using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) { try { using (var randomNumberGenerator = RandomNumberGenerator.Create()) { var bytes = new byte[count]; randomNumberGenerator.GetBytes(bytes); outBinary.WriteBytes(bytes); return true; } } catch (Exception e) { status.SetStatus(1, e.Message); return false; } } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/SigningRSAESPKCSCallback.cs000066400000000000000000000047031454530651600275700ustar00rootroot00000000000000/* * Copyright 2020–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; #if NETSTANDARD2_1 using System.Security.Cryptography; #endif namespace MongoDB.Libmongocrypt { internal static class SigningRSAESPKCSCallback { public static bool RsaSign( IntPtr ctx, IntPtr key, IntPtr inData, IntPtr outData, IntPtr statusPtr) { using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) { try { var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(inData)); var outBinary = new Binary(BinarySafeHandle.FromIntPtr(outData)); byte[] inputBytes = inputBinary.ToArray(); byte[] keyBytes = keyBinary.ToArray(); // Hash and sign the data. var signedData = HashAndSignBytes(inputBytes, keyBytes); outBinary.WriteBytes(signedData); return true; } catch (Exception e) { // let mongocrypt level to handle the error status.SetStatus(1, e.Message); return false; } } } public static byte[] HashAndSignBytes(byte[] dataToSign, byte[] key) { #if NETSTANDARD2_1 using (var rsaProvider = new RSACryptoServiceProvider()) { rsaProvider.ImportPkcs8PrivateKey(key, out _); return rsaProvider.SignData(dataToSign, SHA256.Create()); } #else throw new System.PlatformNotSupportedException("RSACryptoServiceProvider.ImportPkcs8PrivateKey is supported only on frameworks higher or equal to .netstandard2.1."); #endif } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/Status.cs000066400000000000000000000053621454530651600245630ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// A LibMongoCrypt Status /// /// internal class Status : IDisposable { private StatusSafeHandle _handle; public Status() { _handle = Library.mongocrypt_status_new(); } public Status(StatusSafeHandle handle) { _handle = handle; } public void Check(IStatus status) { status.Check(this); ThrowExceptionIfNeeded(); } public void SetStatus(uint code, string msg) { IntPtr stringPointer = (IntPtr)Marshal.StringToHGlobalAnsi(msg); try { Library.mongocrypt_status_set(_handle, (int)Library.StatusType.MONGOCRYPT_STATUS_ERROR_CLIENT, code, stringPointer, -1); } finally { Marshal.FreeHGlobal(stringPointer); } } #region IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 if (_handle != null && !_handle.IsInvalid) { // Free the handle _handle.Dispose(); } } #endregion internal StatusSafeHandle Handle => _handle; internal void ThrowExceptionIfNeeded() { if (!Library.mongocrypt_status_ok(_handle)) { var statusType = Library.mongocrypt_status_type(_handle); var statusCode = Library.mongocrypt_status_code(_handle); uint length; IntPtr msgPtr = Library.mongocrypt_status_message(_handle, out length); var message = Marshal.PtrToStringAnsi(msgPtr); throw new CryptException(statusType, statusCode, message); } } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/StatusSafeHandle.cs000066400000000000000000000033221454530651600264700ustar00rootroot00000000000000/* * Copyright 2019–present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; namespace MongoDB.Libmongocrypt { /// /// SafeHandle to manage the lifetime of a mongocrypt_status_t. /// /// internal class StatusSafeHandle : SafeHandle { private StatusSafeHandle() : base(IntPtr.Zero, true) { } private StatusSafeHandle(IntPtr ptr) : base(ptr, false) { } public static StatusSafeHandle FromIntPtr(IntPtr ptr) { return new StatusSafeHandle(ptr); } public override bool IsInvalid { get { return handle == IntPtr.Zero; } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] protected override bool ReleaseHandle() { // Here, we must obey all rules for constrained execution regions. Library.mongocrypt_status_destroy(handle); return true; } } } libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/StyleCop.ruleset000066400000000000000000000007151454530651600261150ustar00rootroot00000000000000 libmongocrypt-1.8.4/bindings/cs/MongoDB.Libmongocrypt/stylecop.json000066400000000000000000000003731454530651600255030ustar00rootroot00000000000000{ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", "settings": { "layoutRules": { "newlineAtEndOfFile": "require" } } } libmongocrypt-1.8.4/bindings/cs/README.md000066400000000000000000000032411454530651600201060ustar00rootroot00000000000000# Requirements __All__ CMake 3.12 or later __Windows__ Visual Studio 2017 15.9+ __Linux, macOS__ dotnet 2.1+ # Quick Instructions *Requires:* Cygwin ``` 1. bash ./libmongocrypt/.evergreen/compile.sh ``` *Note*: You must call this from the parent directory of the libmongocrypt repo. It will not work within the repo directory ## Developer Instructions ### Windows To build libmongocrypt on Windows. This example assumes kms-message and the c driver are installed to "d:/usr" ``` 1. mkdir build 2. "C:\Program Files\CMake\bin\cmake.exe" -Thost=x64 -G "Visual Studio 15 2017 Win64" -DCMAKE_INSTALL_PREFIX=d:/usr -DCMAKE_PREFIX_PATH=d:/usr -DCMAKE_BUILD_TYPE=Debug "-DCMAKE_C_FLAGS=-Id:/usr/include" .. 3. msbuild libmongocrypt.sln 4. cd bindings/cs 5. msbuild cs.sln ``` ### Troubleshooting If you see `Windows Error: 126` during tests, like the example below, it means that `libbson-1.0.dll` is not in your path. ``` System.TypeInitializationException : The type initializer for 'MongoDB.Libmongocrypt.Library' threw an exception. ---- System.IO.FileNotFoundException : D:\repo\libmongocrypt\build\bindings\cs\MongoDB.Libmongocrypt.Test\bin\x64\Debug\netcoreapp2.1\mongocrypt.dll, Windows Error: 126 ``` ### Linux and macOS *Note* Only building from the cmake build directory is supported ``` 1. Build libmongocrypt with CMake 2. cd /bindings/cs 3. dotnet build cs.build ``` # Testing Do not modify xunit.runner.json - Be wary of https://github.com/xunit/xunit/issues/1654 ### Debugging on Linux To attach to a unit test with lldb, print the PID in the process and then attach. Tests always run in child processes and lldb, as of 7.0, cannot follow child processes. libmongocrypt-1.8.4/bindings/cs/Scripts/000077500000000000000000000000001454530651600202565ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/cs/Scripts/build.cake000066400000000000000000000201521454530651600222020ustar00rootroot00000000000000#addin nuget:?package=Cake.FileHelpers&version=3.3.0 #addin nuget:?package=Cake.Git&version=0.22.0 #addin nuget:?package=Cake.Incubator&version=5.1.0 #tool dotnet:?package=GitVersion.Tool&version=5.3.7 using System; using System.Linq; var target = Argument("target", "CreatePackage"); var configuration = Argument("configuration", "Release"); var gitVersion = GitVersion(); var buildDirectory = MakeAbsolute(Directory(GetSettingValue("buildDirectory", "c:\\build"))); var libmongocryptAllDirectory=buildDirectory.Combine("libmongocrypt-all"); var downloadedMongocryptDirectory=buildDirectory.Combine("downloadedMongocryptDirectory"); var localReleaseVersion = "local-0.0.0"; var releaseVersion = GetSettingValue("releaseVersion", localReleaseVersion); var fork = GetSettingValue("fork", "https://github.com/mongodb/libmongocrypt.git"); var branch = GetSettingValue("branch", "master"); // 1.8.0-alpha0 var libmongocryptAllUrl = GetSettingValue("url", "https://mciuploads.s3.amazonaws.com/libmongocrypt/all/1.8.0-alpha0/libmongocrypt-all.tar.gz"); var csharpBindingsGitTagName = $"csharp-v{releaseVersion}"; var csharpBindingsDirectory = buildDirectory.Combine(csharpBindingsGitTagName); var libmongocryptRelWithDebInfoDirectory = csharpBindingsDirectory.Combine("cmake-build").Combine("RelWithDebInfo"); var libmongocryptCsDirectory = csharpBindingsDirectory.Combine("bindings").Combine("cs"); var libmongocryptSolutionDirectory = libmongocryptCsDirectory.Combine("MongoDB.Libmongocrypt"); var libmongocryptSolutionFile = libmongocryptSolutionDirectory.CombineWithFilePath("MongoDB.Libmongocrypt.csproj"); var libmongocryptTestsSolutionDirectory = libmongocryptCsDirectory.Combine("MongoDB.Libmongocrypt.Test"); var artifactsDirectory = buildDirectory.Combine("artifacts"); Task("Prepare") .Does(() => { if (DirectoryExists(buildDirectory)) { DeleteDirectory( buildDirectory, new DeleteDirectorySettings { Recursive = true, Force = true }); } CreateDirectory(buildDirectory); Information($"Release version: {releaseVersion}"); Information($"Fork: {fork}"); Information($"Branch: {branch}"); Information($"Native libraries url: {libmongocryptAllUrl}"); Information("Downloading native libs.."); EnsureDirectoryExists(libmongocryptAllDirectory); var nativeLibrariesArchive = libmongocryptAllDirectory.CombineWithFilePath("libmongocrypt-all.tar"); DownloadFile(libmongocryptAllUrl, nativeLibrariesArchive); Information("Unzipping.."); UncompressToTheCurrentDirectory(nativeLibrariesArchive); Information("Cloning the libmongocrypt repo.."); GitClone( fork, csharpBindingsDirectory, new GitCloneSettings { BranchName = branch, Checkout = true, IsBare = false, RecurseSubmodules = true }); EnsureDirectoryExists(libmongocryptRelWithDebInfoDirectory); EnsureDirectoryExists(downloadedMongocryptDirectory); CopyFile( libmongocryptAllDirectory.Combine("windows-test").Combine("bin").CombineWithFilePath("mongocrypt.dll"), downloadedMongocryptDirectory.CombineWithFilePath("mongocrypt.dll")); CopyFile( libmongocryptAllDirectory.Combine("ubuntu1804-64").Combine("nocrypto").Combine("lib").CombineWithFilePath("libmongocrypt.so"), downloadedMongocryptDirectory.CombineWithFilePath("libmongocrypt.so")); CopyFile( libmongocryptAllDirectory.Combine("macos").Combine("nocrypto").Combine("lib").CombineWithFilePath("libmongocrypt.dylib"), downloadedMongocryptDirectory.CombineWithFilePath("libmongocrypt.dylib")); CopyDirectory(downloadedMongocryptDirectory, libmongocryptRelWithDebInfoDirectory); }); Task("Tests") .IsDependentOn("Prepare") .DoesForEach( () => { var monikersDetails = new List<(string Moniker, string Bitness)> { { ("net472", "x64") }, { ("netcoreapp2.1", "x64") }, { ("netcoreapp3.0", "x64") }, { ("net50", "x64") } }; return monikersDetails; }, (monikerInfo) => { Information($"Test running {monikerInfo.Moniker}.."); var settings = new DotNetCoreTestSettings { Configuration = configuration, Framework = monikerInfo.Moniker, ArgumentCustomization = args => args.Append($"-- RunConfiguration.TargetPlatform={monikerInfo.Bitness}") }; var projectFullPath = libmongocryptTestsSolutionDirectory.CombineWithFilePath("MongoDB.Libmongocrypt.Test.csproj").FullPath; Information(projectFullPath); DotNetCoreTest( projectFullPath, settings ); }) .DeferOnError(); Task("CreatePackage") .IsDependentOn("Tests") .Does(() => { var projectFullPath = libmongocryptSolutionFile.FullPath; Information($"Project path: {projectFullPath}. ReleaseVersion: {releaseVersion}"); var settings = new DotNetCorePackSettings { Configuration = configuration, OutputDirectory = artifactsDirectory, EnvironmentVariables = new Dictionary { { "Version", releaseVersion }, } }; DotNetCorePack( projectFullPath, settings); }); Task("NugetPush") .Does(() => { ThrowIfLocalRelease(); var nugetApi = GetSettingValue("NugetApiKey", null); var packageFilePath = artifactsDirectory.CombineWithFilePath($"{libmongocryptSolutionFile.GetFilenameWithoutExtension().ToString()}.{releaseVersion}.nupkg"); Information(packageFilePath); NuGetPush( packageFilePath, new NuGetPushSettings { ApiKey = nugetApi, Source = "https://api.nuget.org/v3/index.json" }); }); Task("CreateGitTag") .Does(() => { ThrowIfLocalRelease(); Information($"Directory: {libmongocryptSolutionDirectory}"); Information("Show origin:"); Git(libmongocryptSolutionDirectory, "remote -v"); Git(libmongocryptSolutionDirectory, $"tag -a {csharpBindingsGitTagName} -m {csharpBindingsGitTagName}"); Git(libmongocryptSolutionDirectory, $"push origin {csharpBindingsGitTagName}"); }); RunTarget(target); string GetSettingValue(string commandArgumentName, string defaultValue) { var optionValue = Argument(commandArgumentName, (string)null); if (optionValue != null) { return optionValue; } var environmentVariableName = $"LIBMONGOCRYPT_PACKAGING_{commandArgumentName.ToUpper()}"; var environmentVariable = Environment.GetEnvironmentVariable(environmentVariableName); if (environmentVariable == null) { if (defaultValue == null) { throw new Exception($"Neither {commandArgumentName} command argument nor {environmentVariableName} environmentVariable have been configured."); } else { return defaultValue; } } return environmentVariable; } void Git(DirectoryPath workingDirectory, string command) { CustomToolCall(workingDirectory, "git", command); } void UncompressToTheCurrentDirectory(FilePath archiveFilePath) { CustomToolCall(archiveFilePath.GetDirectory(), "tar", "xzvf", archiveFilePath.GetFilename().ToString()); } void CustomToolCall(DirectoryPath workingDirectory, string tool, params string[] arguments) { var argumentsBuilder = new ProcessArgumentBuilder(); foreach (var argument in arguments) { argumentsBuilder.Append(argument); } Information($"{tool} {string.Join(" ", arguments)}"); StartProcess(tool, new ProcessSettings { Arguments = argumentsBuilder, WorkingDirectory = workingDirectory }); } void ThrowIfLocalRelease() { if (releaseVersion == localReleaseVersion) { throw new Exception("Attempt to publish a local nuget."); } } libmongocrypt-1.8.4/bindings/cs/Scripts/build.ps1000066400000000000000000000216311454530651600220050ustar00rootroot00000000000000########################################################################## # This is the Cake bootstrapper script for PowerShell. # This file was downloaded from https://github.com/cake-build/resources # Feel free to change this file to fit your needs. ########################################################################## <# .SYNOPSIS This is a Powershell script to bootstrap a Cake build. .DESCRIPTION This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) and execute your Cake build script with the parameters you provide. .PARAMETER Script The build script to execute. .PARAMETER Target The build script target to run. .PARAMETER Configuration The build configuration to use. .PARAMETER Verbosity Specifies the amount of information to be displayed. .PARAMETER ShowDescription Shows description about tasks. .PARAMETER DryRun Performs a dry run. .PARAMETER SkipToolPackageRestore Skips restoring of packages. .PARAMETER ScriptArgs Remaining arguments are added here. .LINK https://cakebuild.net #> [CmdletBinding()] Param( [string]$Script, [string]$Target, [string]$Configuration, [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] [string]$Verbosity, [switch]$ShowDescription, [Alias("WhatIf", "Noop")] [switch]$DryRun, [switch]$SkipToolPackageRestore, [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] [string[]]$ScriptArgs ) # This is an automatic variable in PowerShell Core, but not in Windows PowerShell 5.x if (-not (Test-Path variable:global:IsCoreCLR)) { $IsCoreCLR = $false } # Attempt to set highest encryption available for SecurityProtocol. # PowerShell will not set this by default (until maybe .NET 4.6.x). This # will typically produce a message for PowerShell v2 (just an info # message though) try { # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48) # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is # installed (.NET 4.5 is an in-place upgrade). # PowerShell Core already has support for TLS 1.2 so we can skip this if running in that. if (-not $IsCoreCLR) { [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48 } } catch { Write-Output 'Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to upgrade to .NET Framework 4.5+ and PowerShell v3' } [Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null function MD5HashFile([string] $filePath) { if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) { return $null } [System.IO.Stream] $file = $null; [System.Security.Cryptography.MD5] $md5 = $null; try { $md5 = [System.Security.Cryptography.MD5]::Create() $file = [System.IO.File]::OpenRead($filePath) return [System.BitConverter]::ToString($md5.ComputeHash($file)) } finally { if ($file -ne $null) { $file.Dispose() } } } function GetProxyEnabledWebClient { $wc = New-Object System.Net.WebClient $proxy = [System.Net.WebRequest]::GetSystemWebProxy() $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials $wc.Proxy = $proxy return $wc } Write-Host "Preparing to run build script..." if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } if(!$Script){ $Script = Join-Path $PSScriptRoot "build.cake" } $TOOLS_DIR = Join-Path $PSScriptRoot "tools" $ADDINS_DIR = Join-Path $TOOLS_DIR "Addins" $MODULES_DIR = Join-Path $TOOLS_DIR "Modules" $NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" $CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" $NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" $PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" $PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" $ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config" $MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config" $env:CAKE_PATHS_TOOLS = $TOOLS_DIR $env:CAKE_PATHS_ADDINS = $ADDINS_DIR $env:CAKE_PATHS_MODULES = $MODULES_DIR # Make sure tools folder exists if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { Write-Verbose -Message "Creating tools directory..." New-Item -Path $TOOLS_DIR -Type Directory | Out-Null } # Make sure that packages.config exist. if (!(Test-Path $PACKAGES_CONFIG)) { Write-Verbose -Message "Downloading packages.config..." try { $wc = GetProxyEnabledWebClient $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch { Throw "Could not download packages.config." } } # Try find NuGet.exe in path if not exists if (!(Test-Path $NUGET_EXE)) { Write-Verbose -Message "Trying to find nuget.exe in PATH..." $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName } } # Try download NuGet.exe if not exists if (!(Test-Path $NUGET_EXE)) { Write-Verbose -Message "Downloading NuGet.exe..." try { $wc = GetProxyEnabledWebClient $wc.DownloadFile($NUGET_URL, $NUGET_EXE) } catch { Throw "Could not download NuGet.exe." } } # These are automatic variables in PowerShell Core, but not in Windows PowerShell 5.x if (-not (Test-Path variable:global:ismacos)) { $IsLinux = $false $IsMacOS = $false } # Save nuget.exe path to environment to be available to child processed $env:NUGET_EXE = $NUGET_EXE $env:NUGET_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) { "mono `"$NUGET_EXE`"" } else { "`"$NUGET_EXE`"" } # Restore tools from NuGet? if(-Not $SkipToolPackageRestore.IsPresent) { Push-Location Set-Location $TOOLS_DIR # Check for changes in packages.config and remove installed tools if true. [string] $md5Hash = MD5HashFile $PACKAGES_CONFIG if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { Write-Verbose -Message "Missing or changed package.config hash..." Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery | Remove-Item -Recurse -Force } Write-Verbose -Message "Restoring tools from NuGet..." $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" if ($LASTEXITCODE -ne 0) { Throw "An error occurred while restoring NuGet tools." } else { $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" } Write-Verbose -Message ($NuGetOutput | Out-String) Pop-Location } # Restore addins from NuGet if (Test-Path $ADDINS_PACKAGES_CONFIG) { Push-Location Set-Location $ADDINS_DIR Write-Verbose -Message "Restoring addins from NuGet..." $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`"" if ($LASTEXITCODE -ne 0) { Throw "An error occurred while restoring NuGet addins." } Write-Verbose -Message ($NuGetOutput | Out-String) Pop-Location } # Restore modules from NuGet if (Test-Path $MODULES_PACKAGES_CONFIG) { Push-Location Set-Location $MODULES_DIR Write-Verbose -Message "Restoring modules from NuGet..." $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`"" if ($LASTEXITCODE -ne 0) { Throw "An error occurred while restoring NuGet modules." } Write-Verbose -Message ($NuGetOutput | Out-String) Pop-Location } # Make sure that Cake has been installed. if (!(Test-Path $CAKE_EXE)) { Throw "Could not find Cake.exe at $CAKE_EXE" } $CAKE_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) { "mono `"$CAKE_EXE`"" } else { "`"$CAKE_EXE`"" } # Build an array (not a string) of Cake arguments to be joined later $cakeArguments = @() if ($Script) { $cakeArguments += "`"$Script`"" } if ($Target) { $cakeArguments += "--target=`"$Target`"" } if ($Configuration) { $cakeArguments += "--configuration=$Configuration" } if ($Verbosity) { $cakeArguments += "--verbosity=$Verbosity" } if ($ShowDescription) { $cakeArguments += "--showdescription" } if ($DryRun) { $cakeArguments += "--dryrun" } $cakeArguments += $ScriptArgs # Start Cake Write-Host "Running build script..." Invoke-Expression "& $CAKE_EXE_INVOCATION --bootstrap" Invoke-Expression "& $CAKE_EXE_INVOCATION $($cakeArguments -join " ")" exit $LASTEXITCODE libmongocrypt-1.8.4/bindings/cs/Scripts/build.sh000066400000000000000000000052551454530651600217200ustar00rootroot00000000000000#!/usr/bin/env bash # Define varibles SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) source $SCRIPT_DIR/build.config TOOLS_DIR=$SCRIPT_DIR/tools CAKE_EXE=$TOOLS_DIR/dotnet-cake CAKE_PATH=$TOOLS_DIR/.store/cake.tool/$CAKE_VERSION if [ "$CAKE_VERSION" = "" ] || [ "$DOTNET_VERSION" = "" ]; then echo "An error occured while parsing Cake / .NET Core SDK version." exit 1 fi # Make sure the tools folder exist. if [ ! -d "$TOOLS_DIR" ]; then mkdir "$TOOLS_DIR" fi ########################################################################### # INSTALL .NET CORE CLI ########################################################################### export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 export DOTNET_CLI_TELEMETRY_OPTOUT=1 export DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0 export DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2 DOTNET_INSTALLED_VERSION=$(dotnet --version 2>&1) if [ "$DOTNET_VERSION" != "$DOTNET_INSTALLED_VERSION" ]; then echo "Installing .NET CLI..." if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then mkdir "$SCRIPT_DIR/.dotnet" fi curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" https://dot.net/v1/dotnet-install.sh bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --channel 1.1 --install-dir .dotnet --no-path bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --channel 2.1 --install-dir .dotnet --no-path bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --version $DOTNET_VERSION --install-dir .dotnet --no-path export PATH="$SCRIPT_DIR/.dotnet":$PATH export DOTNET_ROOT="$SCRIPT_DIR/.dotnet" fi ########################################################################### # INSTALL CAKE ########################################################################### CAKE_INSTALLED_VERSION=$(dotnet-cake --version 2>&1) if [ "$CAKE_VERSION" != "$CAKE_INSTALLED_VERSION" ]; then if [ ! -f "$CAKE_EXE" ] || [ ! -d "$CAKE_PATH" ]; then if [ -f "$CAKE_EXE" ]; then dotnet tool uninstall --tool-path $TOOLS_DIR Cake.Tool fi echo "Installing Cake $CAKE_VERSION..." dotnet tool install --tool-path $TOOLS_DIR --version $CAKE_VERSION Cake.Tool if [ $? -ne 0 ]; then echo "An error occured while installing Cake." exit 1 fi fi # Make sure that Cake has been installed. if [ ! -f "$CAKE_EXE" ]; then echo "Could not find Cake.exe at '$CAKE_EXE'." exit 1 fi else CAKE_EXE="dotnet-cake" fi ########################################################################### # RUN BUILD SCRIPT ########################################################################### # Start Cake (exec "$CAKE_EXE" build.cake --bootstrap) && (exec "$CAKE_EXE" build.cake "$@") libmongocrypt-1.8.4/bindings/cs/cs.sln000066400000000000000000000124361454530651600177600ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDB.Libmongocrypt", "MongoDB.Libmongocrypt\MongoDB.Libmongocrypt.csproj", "{90EA4DBB-69E6-426D-985A-C66D65A2E63A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDB.Libmongocrypt.Test", "MongoDB.Libmongocrypt.Test\MongoDB.Libmongocrypt.Test.csproj", "{F2D29C5D-DA83-456D-994F-57AB43EA9470}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDB.Libmongocrypt.Example", "MongoDB.Libmongocrypt.Example\MongoDB.Libmongocrypt.Example.csproj", "{536E0590-7287-4D73-A5D7-5B8EFD2945B8}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDB.Libmongocrypt.Test32", "MongoDB.Libmongocrypt.Test32\MongoDB.Libmongocrypt.Test32.csproj", "{EBD0FAFF-4794-4346-9313-A286E278EDA7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Debug|Any CPU.Build.0 = Debug|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Debug|x64.ActiveCfg = Debug|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Debug|x64.Build.0 = Debug|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Debug|x86.ActiveCfg = Debug|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Debug|x86.Build.0 = Debug|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Release|Any CPU.ActiveCfg = Release|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Release|Any CPU.Build.0 = Release|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Release|x64.ActiveCfg = Release|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Release|x64.Build.0 = Release|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Release|x86.ActiveCfg = Release|Any CPU {90EA4DBB-69E6-426D-985A-C66D65A2E63A}.Release|x86.Build.0 = Release|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Debug|Any CPU.Build.0 = Debug|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Debug|x64.ActiveCfg = Debug|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Debug|x64.Build.0 = Debug|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Debug|x86.ActiveCfg = Debug|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Debug|x86.Build.0 = Debug|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Release|Any CPU.ActiveCfg = Release|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Release|Any CPU.Build.0 = Release|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Release|x64.ActiveCfg = Release|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Release|x64.Build.0 = Release|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Release|x86.ActiveCfg = Release|Any CPU {F2D29C5D-DA83-456D-994F-57AB43EA9470}.Release|x86.Build.0 = Release|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Debug|Any CPU.Build.0 = Debug|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Debug|x64.ActiveCfg = Debug|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Debug|x64.Build.0 = Debug|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Debug|x86.ActiveCfg = Debug|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Debug|x86.Build.0 = Debug|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Release|Any CPU.ActiveCfg = Release|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Release|Any CPU.Build.0 = Release|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Release|x64.ActiveCfg = Release|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Release|x64.Build.0 = Release|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Release|x86.ActiveCfg = Release|Any CPU {536E0590-7287-4D73-A5D7-5B8EFD2945B8}.Release|x86.Build.0 = Release|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Debug|Any CPU.Build.0 = Debug|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Debug|x64.ActiveCfg = Debug|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Debug|x64.Build.0 = Debug|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Debug|x86.ActiveCfg = Debug|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Debug|x86.Build.0 = Debug|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Release|Any CPU.ActiveCfg = Release|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Release|Any CPU.Build.0 = Release|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Release|x64.ActiveCfg = Release|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Release|x64.Build.0 = Release|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Release|x86.ActiveCfg = Release|Any CPU {EBD0FAFF-4794-4346-9313-A286E278EDA7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C644578D-7C87-4AC7-A3E2-AA124E0911B1} EndGlobalSection EndGlobal libmongocrypt-1.8.4/bindings/java/000077500000000000000000000000001454530651600171435ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/000077500000000000000000000000001454530651600213445ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/.evergreen/000077500000000000000000000000001454530651600234045ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/.evergreen/publish.sh000077500000000000000000000020531454530651600254110ustar00rootroot00000000000000#!/bin/bash # DO NOT ECHO COMMANDS AS THEY CONTAIN SECRETS! set -o errexit # Exit the script with error if any of the commands fail ############################################ # Main Program # ############################################ echo ${RING_FILE_GPG_BASE64} | base64 -d > ${PROJECT_DIRECTORY}/secring.gpg trap "rm ${PROJECT_DIRECTORY}/secring.gpg; exit" EXIT HUP export ORG_GRADLE_PROJECT_nexusUsername=${NEXUS_USERNAME} export ORG_GRADLE_PROJECT_nexusPassword=${NEXUS_PASSWORD} export ORG_GRADLE_PROJECT_signing_keyId=${SIGNING_KEY_ID} export ORG_GRADLE_PROJECT_signing_password=${SIGNING_PASSWORD} export ORG_GRADLE_PROJECT_signing_secretKeyRingFile=${PROJECT_DIRECTORY}/secring.gpg echo "Publishing snapshot with jdk8" export JAVA_HOME="/opt/java/jdk8" SYSTEM_PROPERTIES="-Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.internal.http.connectionTimeout=120000 -Dorg.gradle.internal.http.socketTimeout=120000" ./gradlew -version ./gradlew ${SYSTEM_PROPERTIES} --stacktrace --info publishToSonatype libmongocrypt-1.8.4/bindings/java/mongocrypt/.evergreen/test.sh000077500000000000000000000006161454530651600247250ustar00rootroot00000000000000#!/bin/bash # Test the Java bindings for libmongocrypt set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail if [ "Windows_NT" = "$OS" ]; then export JAVA_HOME=/cygdrive/c/java/jdk8 else export JAVA_HOME=/opt/java/jdk8 fi ./gradlew -version ./gradlew clean downloadJnaLibs check --info -DgitRevision=${GIT_REVISION} libmongocrypt-1.8.4/bindings/java/mongocrypt/.gitignore000066400000000000000000000005051454530651600233340ustar00rootroot00000000000000*~ .#* .git *# # os x stuff *Thumbs.db* *.DS_Store # Build artifacts build out # Eclipse files .classpath .project .settings # Intellij IDEA files *.ipr *.iws *.iml *.idea workspace.xml atlassian-ide-plugin.xml # gradle .gradle # local settings **/gradle.properties local.properties # jenv .java-version # bin ./bin libmongocrypt-1.8.4/bindings/java/mongocrypt/README.md000066400000000000000000000032441454530651600226260ustar00rootroot00000000000000# mongocrypt Java Wrapper # The Java wrapper for the companion C library for client side encryption in drivers. ### Testing ### `./gradlew check` runs the java test suite. By default it expects that libmongocrypt is in `./build/jnaLibs//` - where is the current platform architecture: eg: `linux-x86-64`. To test against a local build: `/gradlew check -DjnaLibsPath=../../../../libmongocrypt/cmake-build` Note: libmongocrypt and the java library are continuously built on evergreen. Submit patch builds to this evergreen project when making changes to test on supported platforms. ### Publishing #### First check the build artifacts locally (~/.m2/repository/org/mongodb/mongocrypt): `./gradlew clean downloadJnaLibs publishToMavenLocal` **Sonatype** `./gradlew publishToSonatype` Will push the latest snapshot or release version to sonatype repository. ### Custom gradle flags ### * `jnaLibsPath`: Custom local JNA library path for inclusion into the build (rather than downloading from s3)
Usage: `./gradlew publishToSonatype -DjnaLibsPath=../../../cmake-build-nocrypto` * `gitRevision`: Sets the Git Revision to download the built resources for from s3.
Usage: `./gradlew publishToSonatype -DgitRevision=` These flags can be combined with the `downloadJnaLibs` task: * Test without compiling libmongocrypt locally:
`./gradlew clean downloadJnaLibs test -DgitRevision=` * Test using a custom libmongocrypt path:
`./gradlew clean test -DjnaLibsPath=` ### Debugging errors ### * Use the info and jna debug flags to output debugging information when running tasks:
`./gradlew --info -Djna.debug_load=true` libmongocrypt-1.8.4/bindings/java/mongocrypt/build.gradle.kts000066400000000000000000000257401454530651600244330ustar00rootroot00000000000000/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import de.undercouch.gradle.tasks.download.Download import java.io.ByteArrayOutputStream import java.net.URI buildscript { repositories { mavenCentral() google() } dependencies { "classpath"(group = "net.java.dev.jna", name = "jna", version = "5.11.0") } } plugins { `java-library` `maven-publish` signing id("de.undercouch.download") version "5.0.5" id("biz.aQute.bnd.builder") version "6.2.0" } repositories { mavenCentral() google() } group = "org.mongodb" version = "1.8.1-SNAPSHOT" description = "MongoDB client-side crypto support" java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } val bsonRangeVersion = "[3.10,5.0)" dependencies { api("org.mongodb:bson:$bsonRangeVersion") api("net.java.dev.jna:jna:5.11.0") implementation("org.slf4j:slf4j-api:1.7.36") // Tests testImplementation(platform("org.junit:junit-bom:5.8.2")) testImplementation("org.junit.jupiter:junit-jupiter") testRuntimeOnly("ch.qos.logback:logback-classic:1.2.11") } /* * Git version information */ // Returns a String representing the output of `git describe` val gitDescribe by lazy { val describeStdOut = ByteArrayOutputStream() exec { commandLine = listOf("git", "describe", "--tags", "--always", "--dirty") standardOutput = describeStdOut } describeStdOut.toString().trim() } val isJavaTag by lazy { gitDescribe.startsWith("java") } val gitVersion by lazy { gitDescribe.subSequence(gitDescribe.toCharArray().indexOfFirst { it.isDigit() }, gitDescribe.length).toString() } val defaultDownloadRevision: String by lazy { val gitCommandLine = if (gitVersion == version) { listOf("git", "rev-list", "-n", "1", gitVersion) } else { listOf("git", "rev-parse", "HEAD") } val describeStdOut = ByteArrayOutputStream() exec { commandLine = gitCommandLine standardOutput = describeStdOut } describeStdOut.toString().trim() } /* * Jna copy or download resources */ val jnaDownloadsDir = "$buildDir/jnaLibs/downloads/" val jnaResourcesDir = "$buildDir/jnaLibs/resources/" val jnaLibPlatform: String = if (com.sun.jna.Platform.RESOURCE_PREFIX.startsWith("darwin")) "darwin" else com.sun.jna.Platform.RESOURCE_PREFIX val jnaLibsPath: String = System.getProperty("jnaLibsPath", "${jnaResourcesDir}${jnaLibPlatform}") val jnaResources: String = System.getProperty("jna.library.path", jnaLibsPath) // Download jnaLibs that match the git to jnaResourcesBuildDir val downloadRevision: String = System.getProperties().computeIfAbsent("gitRevision") { k -> defaultDownloadRevision }.toString() val downloadUrl: String = "https://mciuploads.s3.amazonaws.com/libmongocrypt/java/$downloadRevision/libmongocrypt-java.tar.gz" val jnaMapping: Map = mapOf( "rhel-62-64-bit" to "linux-x86-64", "rhel72-zseries-test" to "linux-s390x", "rhel-71-ppc64el" to "linux-ppc64le", "ubuntu1604-arm64" to "linux-aarch64", "windows-test" to "win32-x86-64", "macos" to "darwin" ) tasks.register("downloadJava") { src(downloadUrl) dest("${jnaDownloadsDir}/libmongocrypt-java.tar.gz") overwrite(true) } tasks.register("unzipJava") { outputs.upToDateWhen { false } from(tarTree(resources.gzip("${jnaDownloadsDir}/libmongocrypt-java.tar.gz"))) include(jnaMapping.keys.flatMap { listOf("${it}/nocrypto/**/libmongocrypt.so", "${it}/nocrypto/**/libmongocrypt.dylib", "${it}/nocrypto/**/mongocrypt.dll" ) }) eachFile { path = "${jnaMapping[path.substringBefore("/")]}/${name}" } into(jnaResourcesDir) mustRunAfter("downloadJava") doLast { println("jna.library.path contents: \n ${fileTree(jnaResourcesDir).files.joinToString(",\n ")}") } } tasks.register("downloadJnaLibs") { dependsOn("downloadJava", "unzipJava") } tasks.test { systemProperty("jna.debug_load", "true") systemProperty("jna.library.path", jnaResources) useJUnitPlatform() testLogging { events("passed", "skipped", "failed") } doFirst { println("jna.library.path contents:") println(fileTree(jnaResources) { this.setIncludes(listOf("*.*")) }.files.joinToString(",\n ", " ")) } mustRunAfter("downloadJnaLibs", "downloadJava", "unzipJava") } tasks.withType { description = """$description | System properties: | ================= | | jnaLibsPath : Custom local JNA library path for inclusion into the build (rather than downloading from s3) | gitRevision : Optional Git Revision to download the built resources for from s3. """.trimMargin() } tasks.withType { sourceSets["main"].resources.srcDirs("resources", jnaResourcesDir) } /* * Publishing */ tasks.register("sourcesJar") { description = "Create the sources jar" from(sourceSets.main.get().allJava) archiveClassifier.set("sources") } tasks.register("javadocJar") { description = "Create the Javadoc jar" from(tasks.javadoc) archiveClassifier.set("javadoc") } tasks.jar { manifest { attributes( "-exportcontents" to "com.mongodb.crypt.capi.*;-noimport:=true", "Automatic-Module-Name" to "com.mongodb.crypt.capi", "Import-Package" to """org.bson.*;version="$bsonRangeVersion"""", "Build-Version" to gitVersion, "Bundle-Version" to gitVersion, "Bundle-Name" to "MongoCrypt", "Bundle-SymbolicName" to "com.mongodb.crypt.capi", "Private-Package" to "" ) } } publishing { publications { create("mavenJava") { artifactId = "mongodb-crypt" from(components["java"]) artifact(tasks["sourcesJar"]) artifact(tasks["javadocJar"]) pom { name.set("MongoCrypt") description.set(project.description) url.set("http://www.mongodb.org") licenses { license { name.set("The Apache License, Version 2.0") url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") } } developers { developer { id.set("Various") organization.set("MongoDB") } } scm { url.set("https://github.com/mongodb/libmongocrypt") connection.set("scm:https://github.com/mongodb/libmongocrypt") developerConnection.set("scm:git@github.com:mongodb/libmongocrypt") } } } } repositories { maven { val snapshotsRepoUrl = URI("https://oss.sonatype.org/content/repositories/snapshots/") val releasesRepoUrl = URI("https://oss.sonatype.org/service/local/staging/deploy/maven2/") url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl credentials { val nexusUsername: String? by project val nexusPassword: String? by project username = nexusUsername ?: "" password = nexusPassword ?: "" } } } } signing { sign(publishing.publications["mavenJava"]) } tasks.javadoc { if (JavaVersion.current().isJava9Compatible) { (options as StandardJavadocDocletOptions).addBooleanOption("html5", true) } } tasks.register("publishToSonatype") { group = "publishing" description = """Publishes to Sonatype. | | - If the version string ends with SNAPSHOT then publishes to the Snapshots repo. | Note: Uses the JNA libs from the current build. | | - If is a release then publishes the release to maven central staging. | A release is when the current git tag is prefixed with java (eg: java-1.7.0) | AND the git tag version matches the version the build.gradle.kts. | Note: Uses the JNA libs from the associated tag. | Eg: Tag java-1.7.0 will use the JNA libs created by the 1.7.0 release tag. | | To override the JNA library downloaded use -DgitRevision= """.trimMargin() val isSnapshot = version.toString().endsWith("-SNAPSHOT") val isRelease = isSnapshot || (isJavaTag && gitVersion == version) doFirst { if (isSnapshot && isJavaTag) { throw GradleException(""" | Invalid Release | =============== | | Version: $version | GitVersion: $gitVersion | isJavaTag: $isJavaTag | |""".trimMargin()) } if (isRelease) { println("Publishing: ${project.name} : $gitVersion") } else { println(""" | Not a Java release: | | Version: | ======== | | $gitDescribe | | The project version does not match the git tag. |""".trimMargin()) } } if (isRelease) { dependsOn("downloadJnaLibs") finalizedBy(tasks.withType()) tasks.withType().forEach { t -> t.mustRunAfter("downloadJnaLibs", "downloadJava", "unzipJava") } } } /* For security we allow the signing-related project properties to be passed in as environment variables, which Gradle enables if they are prefixed with "ORG_GRADLE_PROJECT_". But since environment variables can not contain the '.' character and the signing-related properties contain '.', here we map signing-related project properties with '_' to ones with '.' that are expected by the signing plugin. */ gradle.taskGraph.whenReady { if (allTasks.any { it is Sign }) { val signing_keyId: String? by project val signing_secretKeyRingFile: String? by project val signing_password: String? by project allprojects { signing_keyId?.let { extra["signing.keyId"] = it } signing_secretKeyRingFile?.let { extra["signing.secretKeyRingFile"] = it } signing_password?.let { extra["signing.password"] = it } } } } libmongocrypt-1.8.4/bindings/java/mongocrypt/gradle/000077500000000000000000000000001454530651600226025ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/gradle/wrapper/000077500000000000000000000000001454530651600242625ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.jar000066400000000000000000001545001454530651600277010ustar00rootroot00000000000000PK A META-INF/PK Am±>=@?META-INF/MANIFEST.MFóMÌËLK-.Ñ K-*ÎÌϳR0Ô3àåòÌ-ÈIÍMÍ+I, ê†d–ä¤Z)¸%¦ä¤*„%¤ñrñrPK Aorg/PK A org/gradle/PK Aorg/gradle/wrapper/PK AªÙfØê -org/gradle/wrapper/BootstrapMainStarter.classV[WWþŽ™d`c@ƒŠƒ7.‰µÖV°´J½ -lDÛÉ!ŒNfÒÉÄKï{ý¾ö¥O]«} ´®ÚÕ×þ‹þ‹>i÷™É@‚«,Ö™3ûìÛ÷í}öäïg¿?p ?(ˆâ‚‚LÊxKÆE½¸¤à2®(˜ÂU±L+!£`³b¹ÖëBòvæddeŒ(輌g±(ãÆNÄðŽŒ\n wKb¹%–ÛxWÁ{x_†Þe±Í+8„‚ Î9gX†;ÁJ$¤I»@Ò®ŒañÙji™;óú²I’hÆÎëæ¢îâ½.”ÜU£ÂÌØN1]tô‚ÉÓ÷½\æNú‚m»—^ftÃʺºãrgœ!\[†c‰¥Ìýžž6u«˜ÎºŽaÇ}‰a§/&÷òÑ"EØÛF™AñC^±K”Ëîfc†NÿôªîPöyÛrùwÒÔ+•Œ­8 ã¾…ÅÝôÂ\¦áH—(kOݧ!¶'¡Åù wWíC_ƒ‚ÃWLžwÓþiö6÷°ku{nh‚ôwWù»3zÙS“±BÁ.>Èó²kØVEF‘ª³bX…Œ^µò«Üñðõ'Z¨k%CZ1„³Ur–µ«Nž 9QЮJ)a«âŽª8‡×ömÃÚx¢ÂÀwU˜(ɰTØ(«ø@,GàȨ¨pQUq÷)eê™”_¢”YÇ’ºì½‹\T<ÀCÊ[ðLˆ[¨Rñ!>bèÞ_[¾C´«øŸPÅô“¦]á‚GŸâhoêyÓX¹}¦âs|¡âK|Ehý¤Fƒ¤FSC·ˆÊÿ‘Нñ Õ{3ì\Õrß(ÃÅI»j4Ëv5“*ïrÍ]åšL |jWÏÏi†ˆ ÕÀX® ÚàñÊ`JÅ·øN¤ö=Ãàÿ¼] û·ëCºA›G Év-µ6Jص榈ÚD²ñzL7{ª®™Ù¢™!Íž–rí+r7û°âòRóE <´Zx·˜»×u‡[43’ÁÌ"mc%GCk̯:\' v嫎p¼ÇšÂúR‘|…»“mÆE_âá:MÚ×çÅñÄÖaµ`ZPž7ÛØ,m±I¾hÐD ëž}—ºúl£/ÿ^4ùª‹’[ETÔ¼¸1 G[JDjj\q.¦d"¹¥™dB8«‹éÜÌõÆïn•‘MIwéŠÇžv<Þ$ +¶CJ-@ÛÖèFä¶Îé“<@ßfñ#Öcô–¦'£gxh ìWÚìÀqZ#žp?NЪú D‚žÔ­"-2f¤'“Œ¬aÇì„rÒr¡ÑÂ5D²ëkèXC瘴%.Õ°3.EÕv…ãáènÒîÊ…¢ÝÙöŒEâF‚h.4Lï{oÄ¥¿{,Ì~CƒHNò’;NZû(øÂqÃôÑ?~\Âa,@ÃmÂZ ‘ü?Ázòb7ŒÇ(R$B¿Ò´ ‘ÅœÄKå4­§ð2>OãÒ:S§Â?{•Î^#I?Øs &ËÑ-£×ûÉè’é÷ 0æeÍ0N‘è›SgýgÊ*BÏé'èÍ G÷­a ñ™‘§¡3RtèGé‘N ’j苨áàcDâá_Iì§çÿ<Á¡\´?àj‡× ýé•VÐÓK© ’4=J°OÒþ Áth¤£¡XhMo3íÑÁNŒiL’Æ9ž&Z7 MÓïÛ–P6î¹(  Kü›8æ2À$‹6V]šîSä¡G …ÿ»L†ì‰±S‰™‘M3dzĈÇõ`³ÛÒb—aÂÌEIBê.ò_€hÆõRþlˆáÉà?R3§cdBËrƒ«5¥8™Húùí2CnH‰í²™ðôˆ61O¯Æ…ù°Ì A/€N­4Œ­ÀúJ ú÷‚q f>=<\¥5‰,r}ò+Šš\îï¼ä!ƼqÏ>Dê.Àùr"ç Ø'ÙOtþLûÒ¹#i¦1Õ—~J«Õ÷ņûÊú¾Ìî:¦{´=ü ®ôJ[Ôz—áàšeRPK A5¶<›Àœ!org/gradle/wrapper/Download.classY |\ÇYÿÒî¾§ÕÓáõ¹¾²NìXÖi;ŽˉK¾dË’¬•äÊv∠~'ˆßÅïñ ~_5 xþP5Äü±/ø“ –ãOƒáÏ‚x_TÓ_RÍŸ›ø‹ Þ¿TÍ_ø²úþuÏáo‚ø[|E5WEioâ‚øGü“6ñz›ñ/~¨õ€‰¯ñ¯ø·jü;þ#ˆgñŸ&þKQþ[íô5Eùš¯+}þG5ÿ«šÿSÍ7Tó†j¾©šo)nšB³úEL©0¥Ò_ûñYSüüJ€,b¨žI7IU]4¥:ˆkb™RcH­"Õ™RoÊ2O ÊrYaÊJµë*CV²Æ”°)k YgÊú †dƒ)M¹Eí¡&²É”[M¹Í”ͦl1åvS¶šÒ 6ØfH£!M«+‘pÜθJ9)A¨ÏM^ž9ö&„µ½¤+¨ì9ÞÓ{ªçÜСþhWoÙºÏÛí¶¸˜h‹zn,1±OPÓ™L¤<;á Ùñ´cJ³ ¶¯¿÷Hÿ¡hô\çQn"®JåkAuÇàáÇúÏE»NªH Ä“å­ëNºm®=wÚ.¹öô´ã¶uëIŠ18î±§ú—½!ÇMÅ’ Aý´›œpTª;–òœ„Ú§¥Ü>“—ñ¤=Ö·€;îŽ%bÞ~AGÃ,6}1eÛÀ×™£’uݱ„Ó“žqÜ{$î(ç%GíøíÆÔ8Gôy“1úÃR*SÅä’š}7æ¾Y3Ö&㱉´ë,L íöÊÅTõìÑ 'ìéœ5æXN¬à–†ì¾ ÇkìïÊI‰%ÛÇ⎖`ØccJ5¦K)+³dÌIy±DNVméZ&À¡Ë£Î´šäâú¼Ì®„ç¸ ;NåÒn|Á®Ý\V›N9î '—© üHz|\eLÅ™ê“HOõ;J÷ÚNoyÝNb›d,ó9Ö™L+!Ìçcä"ÞÍWù¸ŠÚ®)ËÚH8£JU*P™L{‚UszÓÞtÚ£Ó{ŠÓ1._Y˜íJÌOÒbH«!m†l7d‡!;©oÊwݘ`ã_o[èO:$fÈ”MŸwØ©ØèÂxn+®ÅF¨ÀG c†\9µ+1ž$¦ŒØ)g÷®C‰Q]·7”ɬrR?áxÙEî Ç›LÒ—k‹ø\g#ø ’÷2fØ>ÌÑ üðñ[ÕØ$Í-³õ6hÆ ¶›`âV¼•½Æ,#¾oÓ?ëUiA¢{JT…î)a•ZÄ£9ïäŒú!pcã,*›®¡²±å|aß5ø›¯!À c^îF l¦´-ÜïvÔb+V ŽØ† ÔBé²+»cA—]6j3+tÏÓº¨žÒÊG*Q9­zµ–ÀŠyU7P;‡à°Ì¢ú:,¥K¥Ö¥V¯o¡Z±Ûµl+».'ûíšW–“øxEd½Z©Ö5gP“Aí©Æ¦æYÔÍÛ˜Ý÷ý;õ¾‘ì’‚Mu¸‚Ô²êðCÚ‹?̾”(ûïÊ «Ü„€þÙ¯†£vÓuÔg°¬=0‡Ðð–SðŠY¬ì 2XÕîkl ûf±š._Ón„}¡pØÈ`mØ—Áºvÿ²|Êl7ÕhÃî`Õžêª=5aØÌ`ãðç1u·dy +?†M¡[3¸m›‡C[fqûË«jVV]±÷Ô¬ªÖßêUÕ+°uªê=Ï¡©ñ¨ mË ñ”&:{ªI Ü@H}šV¯¬ªù$šh ›•+«2h~áæ»õš– ZÃþ0Ãþ ÚZn ‘”í/à¶öºòó†š×½ü¢NºÏãuºìu|U³!}/Ó ØËù}万îßϹ—ÔûÐŒ؉Ît²=ˆ.FŽÐáG1ÄÑޱúŽ3º™Þ= K/ž ÇÓ8‰¢%çÇ1€WqвOã 8ƒ/á,¾Œðœ£§ñuÒÞÀY< ~œ“*ØbaD§ÀR›Z¼‚wãGÔx3q J¾Â¹'˜.²ÖŒU”ú6ü8{AÊ|?ŸD5u¼Œ÷°WCk^ÃOÑVŸJŒ|J±—K)ö²)U!ÕxïC¥¨´Î®ð‹‰§h“_'÷«¨ºÉk ¬7°ÃÀ3ž5ð~ÏxÞ@¿åÜd.Å%šëè¸IM‹ Q7iMÉ ] |à& ®~ÑLþØÜ¤=e÷-*Sý¸‘«Òãô¢*¯MsØ1ܘÁNasÿvñïNþíæßžYÜuµP·½àBlÂÏÒ¥ó">HÎáÃ9¿˜ƒ×ýM³ØÛÓò|/†Ú›(+ƒ}OÃÒI|7“¸9tÏöÏâÞÐ}h$wð›A'«s²Ø˜¤ÓtÕCtd «‰s¢Þ=ĽyœÞ_À‘ýÙ`: wáç46¾]cvŨfŒVŒØL&¾ï³P)q pæqºã`‡N4‡gp$t´òÓèÊàXOsè¸wû8® ˆ’ØîkÎ÷dÐÛîûÂ~Nö W6…ú28I†ÞWЕ+ÔÊÁÒ•aŸ”ãn÷Íah8tJØ[^¦Š&‹à$ƒÚOKå7ë£Fz´ÙdНa’·Ò¬½ÄË“,«~Ô$KéQÓc,$寳ôÀrüË·’Ü·1j¥ö’úKøeFp’>ÎÒcÔ¯âEöú cOaöã_?®ýÊ+埠ŽÊÃM¨¸Iñ•:7Y ×TJGoò\ñH$h*—d0›;¤žæHsGh˜‡Ô‰Ði¶=Í7p ‘n]._xĨoÏàLK6_®2»Î^-dÌ*}R¾—|’º¿eôaLÙQÐ~‡Îe^a¨ñu}¢[’O2¥òM4k}û9ùærz~‘BTbÞºŸv‡ÐÚžSÚ†dÛî Ùêã¨O 4Zoê3ÿ}Ña?þè0Ó$:³g„Ña³):\hfc´D¯cl¾ ³Uð<õüÔ¯•!–t˜ºGX}[Y}ʶ£Y…r¶ÈŸÒ‘±ˆOkÛB€ÏhÛ„ú—õ !Â*z…=?÷Ù_a/@ÎWµä_Å„¾FU`\ÿ_MêÿEN"ømPK AyL¢¡Ê1org/gradle/wrapper/DownloadProgressListener.classuÁ ‚@Eï+ÓjDËöEÐ@Û–EERûI¦ˆ#3cþ[‹> Š4Úv‡»9œ×ûñ°ÂÀƒç¡O˜Äª.r%ãÐJ[™ÍM Ç„ñ,Èä]Š‚­8Ÿökߟ_ÃPU:â]š3aºý©G­ÍÆ©±\°^¶&a¡t"-ãœE­eY²ÿÂè›Ë›¼8\3ެK tÐŽBNûÐkØûPK A!9|¶„ 3org/gradle/wrapper/ExclusiveFileAccessManager.class•WÛsWÿYÒÚ«u|iªVÍMNZ*;±•JŠlB×NåKœÆŽ[—t-دvÅjÇÜSšB[(·¶ÐP`x¡ 3íL«$x†ô©Ì0à }á…0¿³+9¾%L=öÙs¾óÝ¿ß÷íúOÿýýÁ¯t<ŠgZ ãYµÌjxNG_ÔpNGϨ×Ô Íx^mMEœSKA-EµH ›1¯¶ ::`éÔvIÃb3lIÅžDIGŽºqu”ñåfxJ_¥~O¡ªc—u,áJ ê§íÄñ–ñ _Õð5öñÉ¡± #ùñá SgGFòÏ tŽ_2/›YÛtæ³S¾g9óý­C®SñMÇŸ1íªhñ­’t«þDE@äv”]ÛÎ;¾ô.›¶"Æ,Çò Ä2ù|÷Œ@tÈ-R°mÜrä©jiNzÓæœ-•=·`Ú3¦g©sõ,jÉŽ»Þ|vÞ3‹¶Ì.yf¹,½ìð•‚]­X—åˆeËÁBAV*¦cÎKŽÆÍ€ 0˜ ã°Ü¬âëOUß²³×)T=O:~vÈ´me±¿{]Ô“s—dÁWÊ䕲å-3ÄQºd»…EÝ!£C½…Óq¤] 0ŠE•(¹Þ;&f£*2³B5ûþ?ÍÊ^¨¤£±}Òò虫\j÷L§è–ÂøC¶‡ÖlÙtGuZÝÛ5Ó[" äMn,Ér¹Q–‡ïíõÀôtÿ1•„)ß,,N˜å@LÃ×5|CÃ75|K@gùdÙ·ˆ'ÂhÊšwL¿êQ÷ÄÀtnkŽ}¢2†ts¥óÒŸ&J',ÛVXjÊt³Š%syNÙnE>]µ¤o3•É;6‚‹ÄlK¡q¸oF3åV½B½ÖûîŽÌ>%l W Ä!½8$`¬ÍÀ ø¶À›»ïDÕ²‹Ò3ð"®x ßèýD]AÌõÙ…EßU úð²Wðªï©åûx•À¹cóLÕQ­½V$ÃCnÕ.¦×O#€&¤A7zxŠ N5@¸ïT3„Ï(ïúåz˜§Yò4©}Ï ˆž] Ò³û4½?ˆE¹vqÝÀ<Ì ŠáÓøLø¥˜ÁNŠpÿ8>K.š‰ü1´â‰DgÖ[A|ö4n›khéLp©Á¸ÖS½¼ÍESÑv\ÇcêÙöêÙ~]+蘭ËvvRˆÜ÷5dwÞ¹˜ÈÅÊý=ï#rÍ<ª‰\KªåT´¤öúÛ8º‚äloç7ð`.–ŠÕÊÅSñ WÿšŠßÄ®TŒ U4]»‰Ýï¬~¨Tô®7½‡6•‰övîãþà7ÝBZ §§Hè Ò«@'¼c ¥¿›KlÏ“¸3Ö1·™ÿ¿ãcÑÆ¶‰õDQDDwp>¨žäPõzp}”ÕÊ@8B gmγ*& _$W™Ô ëö+ôkôŽrÖ}¿F¿A?~‹Ô(µ‚AZÆÇ8‰ðÃñŸü:üưŠqÁ¤Ð8­ Ó›“"‰¼Ø…Q±câï?… z5)“çqj…™sDP·hí hô F›9Òˆ‹ޏë§uì>cÄÑ~êþiMȈvz5ÀHMü¾ ªŠø †ð$?b‡)n¬IŽPò$)SÐþƒã¢üݳŠhÑ ǧB¢†¤†<£À¿q¢ÏÒ0¶Ê.Ò¶åƒÃx½dÐ(§øÇWW½§Žw@óMì߉¥ß­5S< Ÿ ’a„<õÀuõ.«ËŸç3ôäGhí¹…GÞAtü=’£dl¥Ù¦@]± …ùßéçysŽýùü:õmŒšO• ‘ ²¼8x4ó?PK Aì„,y†-org/gradle/wrapper/GradleUserHomeLookup.classSÛNÛ@= $vŒÔ”K J)$´ÄÚÒ E¢`@"\”@¤Õ-Þsc-ÂÄg¥ØOˆN™QMž} (1ŠáìÁ#Šj€ RŽ`뛿Í€i­õm¹õßP/ÊQ«ðWM:‡Ü‰â;"¢¬+) Q¤gc@'Q„)‹f! Ip @"p€å´Hw·bo’8=N%ŤډÓ;RN² ½8½÷êôÞCÇÉ?»§Ó•éË÷¡¹7oþWç½yüá+V‰ ž¡b3ž©Bųäðl9Ü­à9**$¹ÏUð<Ï÷ã~¼PΫx^ìÇKüx©‚{TÔJÆZ\‹/Sñr¼BÁ+UÌtɯRñjÜ+aï“ÃkäðZ÷ãu ^ïÇüx£ 7)x³Š…x‹Šx«‚·©X,îÇ ôãí*Âx‡Šwâ]òëÝrxÞëÇE?.©¨Äûäüý*>€ªÈ`XÅRñ0F|HÁeëqEÅ]¸êÇ‡å†øñQ“Ÿ—‹ŸPñI|ª ŸÆg<"9?+!Iþ>/‡/¨ø"¾¤âËøŠ‚¯ªØŽ¯ ÌêØÛÒi?²¯§}ï‘ÎîíGºw÷vuïDNè§õ¦¸žhê±­Xr`ƒÀÔV3™²õ¤½_§ PÉö¶öÞ–®H{[§.˲g_W{oŽ:¯€Z²©bc,³7 ”…ö øZÍ~J«‰Ä’Æ®tâ˜aõêÇâ†TÒŒêñýº“ó,ÑgÆRK"¦5Ð4`éýq£éŒ¥ VS‡3=àÎvê±$ò%ø+03|¨ÔdGºn ¯ÎcY@Í"o×-j—#f6m‹Å ®VY&협’Å2M»-FÞŠ!ÝJüX˜¯g4kj5 =Ù/Ýíð¨2j&OHnX[¼¡ç\Ê6»s¢òZǶC1‡ìãç!Ò‘ÓŸ·ìÓRE°t‘k_ÚŽÅ›ÆéÒNk•í4´³"n HeçzE!â,r_M–Ò~Öˆ¦m“ü‹¼ørI··Ÿ®9 ¾ÎàèýýÅn¸)\™Œ­êJr•^PÄÞPÎÚ¬Bù2¦…KØüqf¥Ô-—IÃnÚ··‹k‚ræ{Î%mýlÎò„òm—Ù×S©6ãø63ìo·,Çþ©=¶=¹Srr^Á7V…'Žj‰ª[&µéF!T{Ì´5ÜôžYr¾VHLˆ6óL2nêýö¢GÑÖ`#¥á(è×ÐD§BÃ7ñ-ú¿øP2‡&sð ²NsÙ–§ ¸|Y áÛøŽ‚ïjø¾OžSå§Ò1ÃXý; ?À5ü?Vð â§Ì¢ñCÔ©§D ?ÃÏüBÃ/ñ+ 1àš˜kŠ˜©‰Yb63R1Gs%qžÌB¯{(¥Ìù,‰ã2ò\£å;NÖÍxÜ<³/y2ÉÃØ=Ö…&Ó”*Ì,è:ÏÖyˆî\©›ˆ‡)2¨§Z¬tÂHÚ©–Õýòxl m19—Ô¸Rcd/(w:òd­ñl™yÛœâÀB=`ØùíböX»(m¢J¶Ç lDUÎCaÙÐP4˜î%FÞ;Òv‹¬p1}°pâîKx wB·¬)i¡“jç…õ˜Ò`xßÓj‹e“vø†À^u¬+y®”OG€b8VÐôC^iã)­ٞk^%בs‹çU¦ØÅmª“—W³:¦æÄw¦ÒÄrRZ·xݘWææLº±ô.¼%+dÙ¥Ë;–fCq]Þ¬ùׇ']/ÌúÉm¥WjÆ©N­uM§Ñ6Ë4ëE›é¾Ž)ŸbH­˜}®©˜gÃXé¾.‡ëù^qïE|ê” Ž¯oöõÖXùˆÉ]%sM·xG6ó ˜m:E½ˆS^;gç;«wÐ2ÏÈ{£ã¾žè á\ÛSi=NÍÈçwûÙ††ƒdàÑOè ÜíÞ?ä±Ç+r3<öJMÜŽ•dæÉÆì6ªR6`8u¿Ð¤1 ó™ (¥RiÛ̾¾œL•¤â¾SR_éö±ä©1ݱы>aíÎu©%“ãä‹‚ŠgŸÜ^µŽ‚×WÄ4O¦‡x½ lØ›!ÿ—ð!ˆvB`gSPÅywÞ\ã|wÞ¼†ó=yóiðó›7u޽¤4ñWð·¼qS.9,û8V8ÄösÔ\Àø[‰>$7‹{¨TiWGPY:ßNå»FQÑ7 ¥Ùôeà?ô•_Fe_Y ª§ÏÐz2˜šAõ8¹F’§IòQÔrg ¹€A(”u¯Ž‡ÇóÔâNíõ‹#Áp$9&¿ùöÈF9J¬)Ò2:rá¾Æ@Ã0G°”>Ì’–æ‘ÆRMÅ€m¨C–Ð|iÔL •€óuÔ1J•/¾¬ÀµÙ´ªbü–¹ÿ.%׎¼äªrüBØ9ˆ–,ß,Gá –óoE )°2ƒ[‡±ª®;nVޝÑ,Ü£tÔ»7 f°:ƒ5¬Íà¶`jdëû–ãö«ÑØÁÆû0[›|—±¹¯¬±g[†qÇU:¨å!l¸ɪÕ6Œö‹r “g6Ñ[ ™£ÛüªaʨaOÑ<ž 0ù‰ÚuPÏNYêÞÈÀÕpßiœá¬Ž;Ïâµï¤Ugñ$~Ícª¹«Oæ_-|{¬{ • î u)ªÊGgÖà>'€ª ¶Ý‹énä9éÈ Sª=‚.鯲¼P÷S¬9̵qw.prÐZ1‡bø¢ÍŠYŸS=ŠíD¯¡¨aì(ŽÎÉ<¸ê,œ`*K®§ÿPK AúâæªÛ"org/gradle/wrapper/IDownload.classEÁ Â0 †ÿÌéæ¼ ^õbÁë®* AÑ{ÝÊØ(í¨Óùl|JìTf $_òçÏóuX ï¡ë! ø‰®”ÔêóÎìn6›mlýaßó{<ïû}¾ßwöµ¿ð"€MxkC6Ge““ͤlLÙ‹a3¦X1¨˜V`ÇÔœ8r”WñÙ»r¥ O6EÙ!ƒ1œÄ)÷ʕʕ©ø¸TùD ÷á“råSÍø4>#î—ÓÏ6ã0>׌q|^6_PñE¹ü¥¾Œ¯Äp§t–ÁWe󀂯©øºŠU|CÅ7cèķ䯷¥µïÄx€‡<¬`FÁ#­Çuk­ådtkÜÌï7-CàŠô1ý¸ž2”œïh–2Y³àõ™®À••™kN=Ó±G\«ªd^jd¨ŸJ+¤XÆ±š¹¢«K9δãæR9WÏZFê„«çó†› úÞZQêÇëÝ Oê›¶l.N ´Î,ÝÎ¥†)`ç¨õ&ÍÂÚ «yé· žnYRn§i›ÞnûK .¼„F³ÊY/ùP‹QwŽ „{,o}yÚ´Áâô„áÒ'dÚÒ2,£ºkÊyy1,O) õÛ6Í[z¡`pzí'Y»‘‡Ó£Ôšè¬nÌ›ÎWCÊÊ ŽVVåúì;™1òå°Ä¦uwÊpñÛ0²…>ç„m9z–Šã¤GA?jôÕÓCóœ|Ú8nX¤ñ¶Ö¹o¥Ò”•]ÇñÚúT¾rðŽ:• ²›&Z†==35 ç}*xLÁã]=AAÁWU®ÁʼncFFBX6lælÝ+ºt·w±@ ò:St]ÃöR½¼X鮞ذSt3FpWZ9ÝRŒáÞgg,§@ Þ¤“Uð¤†ïâ{vã [°UÃ6Ù¼Û5ô`‡†Ø¥a¾O[µ®4üýWדëÖ¢ie WÃñ# Oá4ÃÛíLixZÎ÷àÇ~‚ŸjxF6?“k?dz ÎhxÏ Dºóºëiø…Ü>‹Yz­šÆ;¤Å’‚sæp^à ¸ à—~…5¼„—5ü¿Ñð ~«áwÒ«¸›Üè3,Óêä¯ÔqOÑÐïñÔðþ¤áuüYÃ_ðW 7 ™Óë­l‡íxEû^3ßAætx;Ñ- zÁ±{hõ y¢7ñ7 —þo“w´z©,¡íú ¬Y2æ•H”+«àBŽ2‡çú=ƒuÀq+'óýԜ욋ƒ#•2®¡{~^ loX¸–œEéJÈšÓ’3¼ƒºø#鉯˜|©¸G?Mo#"ýˆ·.@=œ<‹¦–]@ìð943­„–¶+Ø”°ü?ª¸*aÅ Ö¬/¡mí\r1ظrW 4Û>phçá9¬\=ƒ©%ý´Wýô„ãᮓÖçðž²h[œ]%\C¡V›«¥ùxø<Ö„Ö®«ÀšÃu=þ.ŸïžHHN>DVž%S^%WÞ GþAÍwÐ'Ö`ŸX‡ý"‰ÛD/nC8HËi1†ñų8 žÇxÃâuobÔgá,£Ý[ðAfA˜–ÖãvŽ¢Ô»‹þÈ?²¯ÌÑ„xƒÜ8"Nâ’¥Y‘ÇD"’bÃÓÇ ¢\#ÔÒ(ìÒÃWn€úÒ Ô–=â]xBÁïb¥‚à Æÿ…Þc :ß&°»(–ÎZ÷2%îR)?EÀü*a㙆™¥eÔU3l?äË÷ø½Ž /ÃÞÏQŒR›ü\ÄPK AT¨,-t+ org/gradle/wrapper/Install.classY |TÕÕ?'³¼ÉðØ! 눲‡ ˆ„$H4 HXŒáeæ%™%μ! µj-Vkµ­[-Zתh¥UP ŠkÕZܪ­ÚM«¶ÖªŸ¶ýýЦÿóÞÌd’ ò#÷½w—sÏò?˽óÜÑþÈMÛy¸4#¤)Í(iFg£É‘fŒ|ŽuS!ç*<ÎFüêcnrsžŒ—Æãæ Gánªê+ùk.Þ$çJ3GáÍnjä- knnfŸ4~7­“ÝMMœëây¶J3ÇÍmpñy.Þ*l³9Äa.ââvyž//’·‹Å4)üM&µ6Ö£UA-ÓcLžêš•ëêÖn®®m\»¦vùºµµ«6¯®\»’)§î¥±M›3Ac<Ä4:(¢W§ *ü-t× îfšwL-O² ;+²su šbª_fÕÜüœ@»|C—À‰Þ.Ëb ï€Y0è‹¡Þ4†§ ¤R˜É{lmz'ðW K¶˜ä³Bp‰ÉÖô˜î‹GFWy=° VZõ˜!+[Ä蹩=jÃíqtu-„Q†œÍñ–zÖÆåð¶æ.X_34¦lljqÀ4~WËÍUbèFCóm­×ÚMœ)|©ÂßVè> ­U7*Ãþõz4ÐÒ•®Ä5‘À5kàCå‚©¼t£Wë1_4ÐnÙÒîD!ç(kƃåuSãúBW{Ò¼ƒæ.¸ÛÒÅ _†åÛ,öžYÕ¦û¶ÆÄnó †2|Là´JȲô«ùŒ¸4Q‹Ä£>ÝÄú0½³]÷ºßq-¸A:of¨ôK«ðå Õh kF<ªÕñàCd†¥cºQÓ 8¢¦Õz4ˆÅÂp¢ÁÔ N–Àk|ªßB…î_£k~+Æ $n¤ hn½" i†aN°½@§½‘8Me«£‰«Ëã E‰Û™Æ #ú„¯J¹Ý┕͵al·CµéSÜVX Îpë£* iaø—Š‘h«þôˆm„‘” ¸­ ðȉ5h²8Û¯u žÑ ÊÂD%7“XÆ—Ë×Ù¢:à;fcF¯¨z‹Éo@ü©]&Ý=lD»R1µ¥åˆI52"A æHÅñ$‘Uiýç„T@’}^±šp<¤§µÍdËî×%[(Û“/oèî&‡ _¡ðw¾!ÞiïJ FLeƒTfö,èAs6\¶ hÑ­™Ú>kÖ,¦ºŒ¹+™èN8ôduÎ’f¶4sú·š-[eN“É­2&¾Tu“$4G-9qBéÕO’ÖÜcÓ:F é§5Oh•ž­súÏ—ÅgÇâ ¢YsûwY »,>as§»M’Ô–V7š±Û‚¾š˜W&ÓTzšžQézW¥^zX¥ßÓTzœžPéú–JÓ7UzRér¾ ŸP©)‹¾§Ò·é2•v²î÷Uþ_­ò5|­Â×ÉÇõ*ÿoPùG|ÒñÑ…š>[ˆíTùF¾ "¤K·n\YYŠjEåóÍðíôÑ4GÈÊ·ð­*߯·«|ÿÑ%sÙ ð*ßÅw«¼‹ïQù^þ©4÷©¼›¯UùgôrAÿÊ5ñ°驘ʹåtSoz=à™›éõGô˜71¼(? -öjá.L‹"¡F$š•ykÙÕkD¼-ä^½‰8Øåš×U†R¢ÿUÍç¡[åŸóý¢§TÞÃ÷0m:*‰½cØ"â }5TÞ˪t+ݦòC¼Oånh…ÛÌj*à3°7ÒâÍÄC‹ÓøOÊ燛͌sBZ—·MÛ¦{›u=ì5´P»¤moGÀh+Ë›y4ä5Ú4ܞémF°ÐèòBÓ]²—°ÒÀÊãÛ+E«7ƒr¢"# ã—%^- ÖA 1·K,÷¶D#!¯æ5¢ñ˜èË*’ÊD0ozAéEÝTáÍ凓ÑÐ+UŸ YÝ)ûõ[…i(ñVšEØ•{Äö«|€*Ü«òÃbøGø²u´¬ŒFµ. ™*?Jo¨ü?®òòö$lF¯ ’ÝÍpÂñ>O!;­Ì»dííðµ…"(El çÏWùðPyZågøY•)H—¹üÂ1=CFµÆT~Ž%„Kóü¡Rå™Ê/ðµÈï¢Bÿ‹ÉiË,•_’iS¾¼ÒRøe•ͯ¨üª»¼¡‘!¡‚¢ªH<è7µ(œ#YŒzÛû«QoK$Zᕨñ…«òküñê ®ÅN^9ìŠëÁ¶p¬@‹ µ-lˆÓÅ1G`–pŒuµðw%+ £ŠSùu~Cáß©ü{þƒÊä?a¬Ã*øT~“ßRùÏü6 ÎŒ%ŽJïó;*¿+ø ÿ5iš!u˜ÊïI¤û›àcÒ`ë­P O¸éCb¸÷ÅŽWéŸô/•?à«TþoGðâ|l•ävrB·æ–ãV6Ç"Á¸¡‹+ L¸]¨2à6ä®ô…Õà¦ÿ\<&C7ÔÑ._A¹ŠÒ;¦A-ãËŒ²Ùr#X4/R ‡Ä¸aXu²ø š¶;ùØWdØbdªÒ‘0Ê %Ô¸‚  f¨œ£¦&ÓÙ•¢thùaÙDZÍK oÇg>¹Ë~cú‡WBÒ뿨3ï}–œf†ÜIªO^¨¥™1Þt½á WO~ ¼Vïb¹ÓI,æñï¸\"y/å9êñ^î%"­V Y(”™fýÅIq¬Ä(qZnÉÖ5¦~_IXl‰ºH¢$êŸþ=ÒçdÜCAa£w®j9ŠÖš÷s1 0ï¨<é¦x;4²M‹ÕG¢zMPÁþ°°Þi$>#åÍ Ôeݧ9C[­{]O?Œ†\•§Ë:à®ëhxuø‚Ñ’£Q[§“h;‘ƒ^T¼”¢’}ä,*ÝG#ö˜;|ír¢†•^K'ƒ‡é4…òñ6ƒ®ÄH‘E“®¢ï™o›oÂU–ù&|ÙÐû}úz„›ýä&Ï¥ÅÝ4²ͨ†¢‡h^FWØ=önÊ©pÈcL…ýÃ=Î^ÛTäqz%Å¥=”ÛM㣼ñY‹@¹¼–ÒD*ç³L>WZ»¥ø\JWÓ5àÈA‹èZºTÜ4®‡~mX[D?¤l"休n¬i4‰~Œ7'ÝŒÕv¬¼kpüµäá ÐçÆÈ¥9ã÷“§¾—&4÷ÐÄÛûèQô°«Â‘kϺ•&•zÝ4i=×~Kß'%‡-BNÞÕ÷nI7M©€”S›zÈ[¡Ø¸r]ç¡;hÖhêó8s]s/ÜO'Ud{²»išý6æQFÍꦓ7xéš¾a‡‹wõ½àQº)_Ôb3Õ²‚F£Ý¶Ï¥‘´ÐØj4•ši&ù (?B­PG€N§óh mÅŒ ¾Bt>E¨ }QÔTa ”Õ·CIÙtͧ;è'ä¡Sj½”î„’àXuÝ åŒ¤m´‹î?9£{±ÂAú)ݵ.Å®»ñæÄs)ýŒ~3Ý:¥äèÃ4§BÛÊSè…ö°B{‰¦|A£ñ¢ÐT>B3ªüŒ†°ÉƒôPc¿1AgCLáh(=@3fßK3›r ìPa“­¤q?Á!ŠÅh ÂÉ­‰áÒÁöT–E ÌÙÓ0×¶bvç_â. *xh¿o4¤”Ó`b‰Í·}PbV®¤nêrö£W5'=Ð#jȦ¬#4]¡ƒSˆØK'D| :&jJŸ¦ª¢’*¯°—Šß̺‘æR³7äÌQLIŠ›ìè˜ÛØä(mlrzì"Y…c/ÍDηï§{R°)2±| 6ÜAÃ`Ô±ˆ(Ä”ðß¹xžßY¿©†Ÿ\iz“}*=©X±ˆáM¤¯II_CšÑKÞÄ“²Ì·ÇL»ßŒoüoL—óqz"!ç«xŠWöÒB8È)1í¤¹xT4”Z`·-päÂÅî oi®cN…Óãì¦Å;I-ñ8Ð’,Ú°Ã÷x³¤ßzSL‚;àa½›¨\ÍÂö‹ð~@ž´`\èNÓó±}JšÊ„-]˜/ÌJYÐê9€‘j"ÙúФ€|P¡'J˜ü)~Ê _¿ÀßÓôŒ¦³†c£lôìNE ÚÓKyMÅ9K{è´znè¥eMÎG¨²É–³Í©‚9aÕêÆª±âæ ÄMôô´¢—V6õRm“|ŸÑCgöPD˜z(°¡B ­jªp=My%gµ…w«±›ÎÚ€x$dMÃ.šd‘]‹WDæý´¾›6HÇÙ €\!b³ÒKM xNÎÆnúš nÚÔMçÊ`Îf¼ì„¹€ÑåÔh>¯¥u  Kyhï‚)î†âîAʺ3îÈvSâÁrD„ PäڃȴQå!¬ï¥nh«pìµýÜ`Žƒ0Ûàöpsîÿ˜iÄvróYú%t»Éë934´Ñd: ø¹°Ûzž^€±+èLzÑôª+0÷eú5ú®‡Y_¦WL8Nà00)ƒcÂ9üü6çr¹ú°¯+iyü¯Th™B¯)´R¡z¢#4}}’—Ó'-W¨ñ …Ö /Ù×éDo×xÍ„œ-ûIÛKÍÝä«+Îñw“žu'9ì»m»Sœc²û$XŠÆbã0QÆ8‹BB •FÐïL¯–]„:^8È’Ÿ»î‡"x.,6=ª –zÛÒÉ%ÈM'™è,™<ðì!»äµÉaÛ½Ã&Þ†©³ûYšfæ Ñüalü<‚Ê °Å‹p²—‡ž§9О°8ÛåcÖéObªäÖÌ 7é-S€…);,¤?›v†“ís¡ÐÛ<ù3É’Ÿ6ùùel.nuM/µJfn³`¬pžd…^¶2 ´(´“òD¸ùC¼nŠÀ/^é¥v8ÕùMÆz(ÚC1”*»tgÅÅÁ¶í¢á–«mó(îê»N6íN—ùæq=ºBnBš‚»(æÓ  Kwª·ËR lØ–qC5£  ”1Þ†òÞ¡S!é2z”Þ­º?¥•>DFúô>F,ÿÔ>†â>AõóSÙk —ét6ý…þ mBaðý …¼ö>ý;Cg)e_ŠV»tôWãËšç†S~DÿiÄ)ŸÓ(…>V¨õ•+ì£Ù¤¤á\FЭ€dö|FÙY}°º#5­æP,ç´[$3E#Øø'ý+‘)nFŸÀ5´eWCq)Ê­¦ö›hDI©YluîêûÀìB¨ÚÖŸñ¬\þßhÿñþST{ÿFÅ‹äKŸ§@ ¢)Mäcî=¦&òé 1ÉåSÍ¢ÆÈæÑÿš…Îý¦!‡#þï=B¹ÜÏô(vú4Át V‰¦•¢bäpWYë4·˜h²àµ¦Ðg úÿ„10+åD*w‚ø0n9p9ž2Ë!ñ83iÕš`‘Æâ/¨/Ãbçq-Æ|N,®H,§Y€e^m$gJ*§%èd±-ûî¤cgGBÍ«¡ ‹.¨‡ÛžŒ”¬²Í•¢ä%«pqAÏVáâb§éÓ4Î »2š3+ó6_nΛÒÌ ¬p6»3)ƒ3Ó>Š2(‹‡É|VQ©JŽÈB¶þÝÀ“éGÄÿPK Að¿:öo4org/gradle/wrapper/Logger.class…“koÒ`Çÿ—UncŒá@Ø&s*]7¼‹11$KHð’°`²wÏÊ“®³´¬_ÅO¡Fgâ ?€ÊxžRŽ5KÓÓçrÎÿw.éï??h G ·b¸‚Û1TP£†º4w¤¹+ͶUÁŽ‚]†èÉØ.;`XxfX†ûœ!R9¨öèÓ²û‚!Ý1,ñj<8Î>?4éd¹ckÜìqÇ{ÿ0â#†bÇvtUwxßꇇÂQ;¶® §É6m!Wéó÷\5¹¥«]×1,½)Ê@ŒF\÷s ©®Ëµw/ùÐ'.Hq«Ï°3«×:âNWœŒ…¥‰fuæâ…ç-Ce"Úè„!ÇÐÔl·U£#—;²›m"x©*­@o¦ÑÛbˆwí±£‰=C•˜ôj[Æ$‘B#‰’ î%qŸc”‰±I![3ŒÌ”‘¡JgŒ´ÇXó&Õ¡ovÂHIFií ó” Qª¤V÷(µIØ”’õ)rµŽ /‡,®Ó*üœñÈåàꊧPæ¹*qw(¤PÝ&nü_Ý–7Û›PK Aon¶`8org/gradle/wrapper/PathAssembler$LocalDistribution.class•R[KAþÎf³«éV㪽ÙK¢>Äõ²EúÖRŠP¶ÐâCß&ÉL\wÃd£ø¯ Búú£JÏLB1V}˜3çöï›Ãüúýã'€}lÌ£ˆ%xX3ÞKc^ùxã£BðÛjW}ÂB£'ÎE¬²øH%òý¤t¨4ÁË»j°ù–°ÞÈt'îhÑNd|¡E¿/uüEäÝú` Ïš‰ÔŒó>¨Tå õÚìöiÒéhë„àdmIXl¨TÏšR $„¬%’¡•‰'I×%,ÙÚ!Ëת9ÌU–‚Oi*õA"˜š[ÞÍ”¶ùÏ~[Ø‘ùÝ”]O¹¶uw%îã­šˆƒ¯ÙP·ä8§Hö .@ ¨˜Ç\s>Ö ûÿ¯‘ÕX)‰H;ñçfO¶rB¡fVY™5 Uþÿ™B£½ÐÊe#ÑVx“xÌv£.¸|¯DÛ#Pt 'Ú¡íŽà^sÞÁ¢azOê1êËHPæL4Æb‰¬g8Èz†Õ±žÑaXWñdÂómºŠÑ Wi<›Ôvt0n˜Œ&<}ìÞ_>vðÌÚ第¸òšßDPK AJØâ[&org/gradle/wrapper/PathAssembler.class•VicW=cKYÇŽb'µcÅ1­,Ù 4@ܼ5QkÙÁ[qÒÖ[yy¤ŽF‰ e)–})P(”²CÙ]h¤PýÎob;wf,Ù®LÛzï¾§ûî9wy÷Í?ÿóÆ?œÅß#r-ˆc=×#”nÈ—aC…%ÛYU<A9Ù±E*…áÈ\Ž@ÅMÙ¾%Ã¦Š­Žá|Rþ‹ã™0>Á§ñ™t|V¤gU|NæÏGp_á¶ŠçT<Æ#ˆáKa|Y”¿"ÃWÅÐ×DúºŠo„ñM¿Æ a|;‚ïໂÿbß ãûrøE/)8:]XÓó“fɱÍÕ²c,ZÚ² {"¯—JFIÁ‰‹sc“ÓS+‹óSs+—f3S+ó s陋 ¢Ó×õ›z*¯[¹Ô< X¹Qm«äè–³¤çˆ‚#—çf™šX¨:’³õlÞX,ö¥Â†hxfÌBêa3oÐDèAÓ2 šãƒK …,ÕÚ§M˘)o¬ö‚¾š7_È/é¶)k3ଛdÝ?]°s)*uËÖ‹EÃN]Öõ1zµAM›@Gãû¡­=g8ûã±odë1o¦·×Ì\ÙÖEwtðmQÞp‰ÙÚ^+ ši¨ ¼ª—Œ]ÎÒ¬'¶Ú…ݰ½•*påKWÌ¢‚Ùø[³÷.ülyµlç/é¥uJŒ¡'Ý×¥áá¶ £TÒsƤ™3JŽ‚>O©d¬•mÓÙJeöþMýàê–#ÕÙtu\B»öXÚ\3Š~|B%‚ó޾v#£ýBi·ÂMcjÓ1¬’ö€åFKat”4cèW‚Ã~ßËpR‹séCB á]´óµ¢ÞÕ¦ñ"Ë@ÅDhwœIsÒx€ê" 9æÁùBÙ^3d“Å¿¯¬F䄆Q<¨áÃ8¯â‡&ð²†Çñ„†cVCÓ¼Û{-kø^ѰŠ5Þòƒ,ÆËf>kØ~,:?ÁO””†ŸÉj?×ð ‘~‰Wœ}÷E/6~¥â×f0Ë‹ž™|@Å«~ƒßjø~¯áø£‚N—Õm¥ÆÍ\ÚrŒœPú“(Œb[輦àXƒÌ+è©ïΕ-ÇÜ0öüÙ;Q(ç³1«àÄÖY¨1Ó*–˜W*#bûÏt—Â_ðº†;¨h¨Š»w.övî*è8Ø35ÜÅ_Y~3ä]-³ÿdM[Åv$A£øËU*ã|ŒÕ3K±²uÃ*Ü"ߎº3³«×5gßÖ¼_â÷¿ÃûËÃñÁƒzì@ãwk®3Þ°Ð*‹ÿ$/PVVÁð;ºö~‰Is »>œ>ГZòîÛ˜ÇÑ_xÆvëý¿ÂÞ7@Û'ÿO+òÚDÚ}òÖÈåÌážÚËÂÒ¼vˆJC •‹YÝ¡¹`üê¸0 e}´P<íítÅÓ 3“hÔ×ë; ëvá–4@×ÑV>ò$Ÿ56g¯‰ÉÜéK©¼ºÛEÇÓq¥çûU`<]Öó¥ö¼²¼²¿r·Jޱáñ²]`ªœ­Cˆ,á¿’Îò‹¬Ýxç àƒ\5aëíY'ùc¤æ{"LJ¸z?g…s0Q…òš«zc„3ЇîÅG(iž>Š1Îb`Ü7ð05E7"É;hª[9BZàwU€4[ÐïZ:îiû–DZBb“¾ÍÿIå|;‘¬ ¹Š@&1TEp&1œ¬"t>°uYþ WѲƒÈr­\i´Epèp¨ ½ŠŽóÁ]Ý£ût£ût]i¨~(´ƒcˉî`w¨ŠÎíš;=qŒÓ•A´#Œê†°‰a×µKéšk·1Åð°Vð .2M@ÿCèÅe|Œø­ŒÏæyö4å,ºÞŒÔØ`Éeÿå”U•8Mò¤û¬¯ó¤”^g2zº‚‡z_F0¹lî­à½ÛîmNQ׳G™µi¢dýY—KÌ;[CëIJ‹¦Rã ®ÉÇýÚøµ%ß>î³<)6{§û2C’š }Úê g:Ɔ¾ÏÙV¹¥K9#½ªÛ]QÛ¶ìÎÍ”nv¦-m•¾Î½†v^g-£*6`Ja©Èà#Y­" GANÅ lª¸‰”Š-|,Ðûì÷ƒg+[ò *øDŧøLÅ縥â |©â+|­â|+ÐXyvyÊ) î'ð1MnÄBʶ6‹w{/(æè¶æX,£Ö(~> WÙ¹Ê## IŽÀ±=×þ›(¾DÚÊÊWFîÙ$v tð$õ0;©À/èÓð~Ç*˜x¤BDôV©`ª -nýµ|/âº#·¿ÿŽÐ)ãÚÅøy­eðǤ2FIiÙý&Ñ^ÓÊ«,=A•5ò²ñÙ¶ì’áð¾´Tã‘mªMëfRص/}6·’-Æ·„bU ñ$eñgþ‡èRevXà|ø3%Àóò_ ๡~Šcg5hçOÈW‚ò -aŽ‚£¯÷Äï.¤›²Ö5¢T ô —cúÐOƒÅ_ð ü¶‹šå{ðLõæáý¾¾»»ðÑP;½ e™™ý3ýyÔñ؆:â•JÐ{3»P—wÑ@ô¡æÃy42ESÍ÷pä~GwÐ"03°ƒV;¸L¥M`Äôæq¬¹=çî ¿4éÈãøˆ/è£öZú‚>×u‚Þœô`iûÑNß]xÈG7Yø κcÃA=·#7?£”ÇáÇ ÆI4¹lv1ê4ýÝ$ Ĩn¼Ìq˜³R!9K€MÏ-²z›™À9üBÔ¯r‰œäWÊ)´5È"è î,µÛìÊ9z|Œ~…_=/±’ÊÈ!Ž~üLë0›Ä÷8WIþH±-_„Ú÷{ÉÿM F1µWÁU>…Ë ¯=€ÿ’‚úއ¨SpñL<`¦×Ý–_b†qW»üPK Aª=©°?-org/gradle/wrapper/WrapperConfiguration.class“mOAÇg¡ôÚãJKŸ|iᤠ" HULCß-œåH¹’»«&~*M$&¾ðø¡Œ3w ”e›˜&3³3óŸýíîõÏß_¿ Ë:¤ÀÒàaæ’`@EƒG xLá<™2OÈ<%³¨Á’ÏŽxN£8m—ÁPíˆæ–kÖöÖÖ3Ýõ5îÛ ²QO‹»M«Ž5·)÷½çÁ!ƒBwª~È+ó õÎ1í«sM¢(ê/;®¬0è/•wÄ^´°ž®9®ý®sܰ½¼Ñ ÷nïóÖ÷Z‹d,8t|åZÛkZM´lë‹ÇONlÏÚü‹¶ûÉiv,.âsñmâìî£nsúô =ÌN æN8¡u‰ Ñ½ÐÆØq$&ƒL*AîÂ=HL)£ÆìBCO*A4dF r_ ¢É s¨©ôÉ )%È  2¯)©AeEÔ,õÉ ²$!ƒÂçX Ìþywã ¬âyõ%^}9„¯°úÏ3à 2¦y~žÉOȸ¨`;¾Êä¯)Hãƒ^V0ƒYWðõ^”а¿;98ÐÝ14ØÝß724Ð3’èOt K÷×Njí-;Þž´-#;¾[ÂüN3›·µ¬}HËt eû’]„rbbßàAqy1ypßÈ–mÛG’C½–éNŒ$ûº*=” 8%g™9ݲ =/a©£zÁ62í‰â9©¿ ÄuÀÈþ NÃlç=qÔ¤Ìì˜1.aCi·[Z:£·Ÿ²´Ýk?ìÌ‚§`i¶aféRݘi‘œãzÊÞoX4šÖ”„­ÑrðÛ!vÖSºF`N3Mš-ì1²z_arT·µQÖ5Üc¦´Ì!Í2xï²Ý®\ò)éá&* Ÿ´µÔ‰^-çÞ«Ùcd {¯„õZú»nÃ! ]«÷$E×锞s=°' r|Ë™¸4gé9ÍÒ÷yJ¬Ñƒ Y†„EÑ Ž€¬n· ts@òfÁJ•BU¢(Eò2æÈDK×ÒÒ²2t!cjé„'-BF–Y×&‹vÑÝÙ\ÁvŽwËø†Œ—d¼Lî×m¯z¤”^B<úÿd‰¬ )G£Go..?¤n.¶LÆ—Öaš6é§åz5¶K³lÝq hÖ8Y[ç#ƒ”0H M·(aɨþ-ÊÂW ÃvМ$›ç‘ûÜ`Pm¬‹Þ¬Ü?}U·b§ú4FÙásïN‘Òú˜VÈÜè\;ïéˆ/TÈÒ,P¡§©(ŽHždHW)¯(±MËî5òyb-Ù«$E;µ¸¤¢"6² Íÿ»vÈ o±JˆVð;Û6w»±ÔîT â›$Ú¯º™ö-†T|ß¡Æ]²y µI½XjZ]"%ðÈ)Y¿6¿>’6i›5íˆ~šªg#•M «”;•Šïâ{,í5Ÿ;¬¯ÃëUÀkUD· u=‚£*®ãû$$í)Õ-¯«ø^Q‘ÇI?dIe ÍžPñ#æø1ë½Ää„F/Q²0©â'Æi?e6õ!#—¤(莄Ÿ1õçeøLø%ê|º%y°Ó,dÒÂKÜ¢"§|j™“¡ÙS¿RqŒmý5ÿ¿Uñ;^ýG©Q¥Ëšh†&Ÿ…}#YÜŽI¯§7w<}EüAÅñ'æLÇQQñWüMÆßUüÿ”°¯ÏŒˆDœ2ì‰È }ʉx>§§Œ1COGŒ¬¯)7rƒ’a…W¡äTÖÖN{üRçÓ“Ë|88a™§œ÷«ÄÛïAXTY¬Öø¾oeÝ‚zfu”Ç‘´y±¥º®¡çtR³ý{…·»:‰íßvêý:ÉZ˜¯|`GË_8檫x†8󨊣¾¢êò~Ì•œ£7ó:§Ë+x‹µ@¤ü-I Ý:bäqJÞ»q(¸Kq6±Û·ßb¤…j &™šÐù˜Ïï};dm§?JßpõEö¤“›)º@a Ú¦¨ƒÅ•führ%’•Qßæ¦2&ÛÔxëg“lL¿->lDÚÜé×ÁM6øuF¿g–ôÊÛºߊ C±šþ!Ì£BµhÀ^ÜG»×Ю ›h¿Ï³_FûÏ~í;=ûU´ßïÙ7Ӿ˳_‹0·kZ‡¹c‹™z8ÍóIvz‰³v¨¡Ð0ixUñpõ,sÏ¢fò´€ë§Ña\‡ªs oе(ŽC´ÖØ BÏbùj‡ÃJà%Ì®Ž%¯@Åü«,,V.£ZÈX@3#Œ8šÐæ‘Õêš‘¼RMô`:B¥ûéB€N¦c³X@À xÑe,޵^F8¿Œº8isOÆ[¯`IìQfQ?ƒ¥b^ÆÓ –Ï¢aÎÙ ç¬Iœ­tÎV9gw‘‡"3Xí6;‡kc‹s¶Ö9['ÎÖ_@cŸpÃÇ qvCÛ,bW/’þ<…guÐE4n"kÖÐÿÅÍXBÿ™èeÛ(¦Û‰rÅ}îÇNLbÅnº¿—öà<îÅ ÿ„pa€öKq‡…K§éÆ0 VìHI¬8Cª„K—¢ê?RMÁ“Q%Ó¿Vš£tʯ<Z‹0«hn!çÅ{È£­×9o(g.¡nmt²‘rgíÓñRHÃ"2„¸ü ÑLòŽDÆrõ â.<€7’^¬MÒ«h–Éî7Ñ.@§#Ä}¬¨Éâ "áð¦l¾%Þ4‹-‡çp÷°XnŶÊÌê%úPG ”2kµ«‚›Yu™ è¸2Ÿ&"[²rÛ‡É÷ôÆ[g°ƒ~;/@éã¹M´–dÕ客ÔäT­¥P, Ia’UOs#ÍMä\Ö#"t[éf8¯80Œ´£HyCTÏ!âøÈHsˆôš¢ºcô£/··ÐÌÖ…œTÜUYÇÇ<¹0ýßîÞòýÊËãžËÁâåã8áú*C9ö­ŽôÝ»mñÊŒ=‹HN@N3XL¹Ìˆ[[Å\ mRH # SdL9¾\ö¸ÙŠÅ¥l¥ 9O†ŠC(ˆ.ÊH']¤„Tí µú!Ùž ތīS´ª˜§]ÌçhµDL…³yW !p 5 éÖk¶N¯<ÚXœzZ*%q3a0LQwxˆ|q†,8‹åx˜’é¢?æñcKQ—–¢.-®.¼š"öc#ÞLg‘d ª_EXÆ™`-q-z3AiÌ·šD#»7è6²á×þ¶^á—Ç=n*êÒäê"á-‚ÿáÿPK AÔe‹ #gradle-wrapper-classpath.properties+(ÊÏJM.)¶M/JLÉIÕMÎÉä**Í+ÉÌMµåPK A)gradle-wrapper-parameter-names.propertiesPK Aorg/gradle/cli/PK AÕÜ?®<S1org/gradle/cli/AbstractCommandLineConverter.class•T]oA= ‹ëÚ"¶µ~C?”R*O¦Òh4!­ÒÄÇaY×m`— C£Âߢ/4ÑÄà2ÞP–´ôaçÞ9{ï¹sæÞÝ?þPFÙ@;:v D°c@ÇóÀ{xY9y†xÕõ\Ycˆfs§ Ú‘ß±V®g{m[´x»KHªá[¼{Ê…ì' &?»†bÃNɼӵKV×-ÕÛ)¸%ü^{€ìÈ÷Îm!mQaظÌõµÿŸ¯|¢j«U©›n†Ãl㌟óR—{Né…¬•ì¤}f[²’ C¤… ‡´¬-¢ k’ôÚ–Á=,È÷¹Ø‚ak^ÀÌÁß«Š^tÊê Ö”Âõ¥-JŒ×_,»/]ßèØc¸ÕtË¡ +;Xš¨rŠîCµuVQ CWˆ uÁhúCaÙoÜ ™«ú¶Ô1aà6Cúºë2Qľ‰LÜÃK†Â &„!9¯‰a{ Qá23Quá {¶'§M¡†Ð~rÕÝìõ3|i153 ¯mnžDevf¨èÎ߆J…£–š~-C…Hý;"d©9´š´«“edcù °äDq‡Ö¸SX¡Õ`I²w/!)²Œ:·FyÝ7²ÙÍ_ˆ|¼@ô8_AË #ÄöFˆŸVX! ÊK`öªR~œ;©xëô†)ï>=ŠNâRnpŽ´âØœœcÿhÿ˜âŸ¯òÏ”ô4=c/ƒ-e·ÿPK A׃µ³Xì ;org/gradle/cli/AbstractPropertiesCommandLineConverter.class­V[WUþN2ÉÀ0å H¡°Ô„¤ÄKKµIQJ©†‹¦‚Ø;L†0fâÌáOøîZ¾ûZ_¢t­ºúìÿñA—·}N.iÊ2Y9çì}öÞç;ûvòëßOð6¾Q0Œ÷e| `ó|¸£`w,â'?ä«û ÒøHÁÇÈô` Ë=˜Å V»ð‰>íB¶ƒxÀ‰Ïø°&cë.cCÆ Á”i™Þƒ?]cì¼ÁЗ1-c¹¼·i8´Í"qB[׊kšcrºÆ”¼mÓe¸™±B¢àhù¢‘Ћfb~ÓõM÷V»d8ži¸ öÞžfå¹ÙÛÚ'¦á$ F]èp¥ä™¶Å0‰fv´}-QÔ¬B"ë9¦U ёѻ†§™E#Ï0ÖfÏÕ³f±[·­-³PvòTä4ØÐV5Ç%\ÜÁ’X3L¾Xž¤íÚQgIW‘‘´¬W]Àp§0™?¡•¬:£ì™ÅÄ’VJFOѹ’MA`i Ò®q¸¦ËÆâAÉ1\W@ µó¦\ì¶AÜŠ€A)5"É“ã4‚¡æä8,ÕäF³hªJ+gŽ ^Èzš¾KÂŽŒ‡añ@7ª e<¢ fÍ‚¥y"¨ß¾´;D='þûš+›;†î%£­,†üW»’J /G¬dí²£÷L¶Xg<Ãm©x# ý§íªx ã*&0.ãKo 'ã+A“|gºŒ<ß¡o©(`[†©b»*ŠØSaÁ¦¼¾­¢„¯ Â«ÂC™û”%M—UÅ4¥Ü¹zÝù%ÜLEu|tššg·1qBuÞ)”÷ Ëk$1Ãø‹ú 5ÖÈÃÖxE;i1g¯÷Yu[së°¨ª¯D:2ÜKZMÍu6ò?Al©†T'¶[ô'\íL’z ½¢o’B‘“EŸ1]^„½Í†.³õ¡&…z6ðK®Z6<ñ¶ÒS+Y‚h~ßu.›VÞ8XÙb·»uš÷ù2©¿iÕî°•t»ežÔd£N§Û¾³áH;¾4A†Á?2/y/• ™jéŸÀ~¤…£43Œ1𺸄ˀ$ñ¾ æ‰Ú<Ég’yWjFK$í§ùj,ð ¾ ÿtþì†D“”­ °¯ ¸'R® kýøÔ$G è}/aŠNäƫ֪ÄjŠ~Œäú¨ýDH›ñæARüôßèô ͹?·‚î ”#ô0,_;‚Êðiqá9|·¤)Ô[Aßl øq"û0àÇú%ÊT‘Âéq¯Ô¶þù9þ„NêËäR7¦È3ä…wÈó„oƒ="\ü× Ó bôÓjŠèkDóÛæ·ÊQ0Þ¾Îá-úé#KuïsÎuâÜQ‘þÄ€ŒÙ¿ác¿cøÚº)Q‚á=áÐ[ýótx’V¿p¢2‹?Ç`á'g[©:¶é«YMᶘçþPK A}­ÎyGK1org/gradle/cli/CommandLineArgumentException.class•‘ÍJ1…Oú3£µ¶Zm+êÂî´UÜV " Âà–îÓi˜FfĘ́¯åªàÂð¡Ä$-U´fq“{rïwOÈûÇë€34K(`Ë„mu çœ žöê‡þ=}¤^DEèõSÅEØ=.å˜T}.Øm˜ÐQ¤•š/ ©â&Ÿ‹…t‚_ªÐ GÌ "î]Ê8¦bl *Ìb&Ò«ç€=¤\Š.³$¡¡¥þrAÐ^âí›2˜(ùdæ[ÃÅ€f‰&Õ—V”ú2S»æÆoë/c§PFŽ ‚Î?^E°û5ÿ.)Ùâ-äõ/˜•1ttuÖÓyNïN»3y±÷+:–¬ÚÔ•;XէƬJëk–â ŒuÍ0¬Êœu£gäõî¶;ÇSä~ÂötÓ¾…ÌÊ0w3§*6¬ÅMÛ]ûPK A³ßâúg)org/gradle/cli/CommandLineConverter.classQMKÃ@}ÓÖÆÔ¯ª'Ï"4 F<6¥ EQ($xߦë²%ÝÈvSúÛ<øüQâ6…L ]XvæÍ¾÷†™Ÿß¯o÷8wÐupJp’L-¸6„~/œ²óS¦„ÿb¸fã”%ìu<å‰ ¼*Dè<.þid¦æÎn$…b&לpW'<(a‘ÑR‰`ÄqàÙKxî…™¾Ðl’r?I¥ÿÆôœOFÙlÆÔ$”jçήwÚøºvRm_Uˆ%J¡¡ïÐÄýªñ°vJQ–ë„?ÉÔê_”äFë%p}»b.·;o¾ºÿ-7Û‰Zä3®ÌfSm¡Õi¶M´l¶g³–ÅÛplÔÀ~Qqk*[9Àa¯‘#ïÉPK ASf Õg&org/gradle/cli/CommandLineOption.classV[wUÝ“¦4™^ˆ´i¡\ä"iBµ´ ­ÜZ.Å^ÐÖŠÓdL¦™0™pïwü¼ø¦¼ð .UYË哾ùü.—¸Ïd:™Ü¤Ë‡œós¾³¿ÛþNæ÷~þÀËø&Œm8'ã|œkE–Zqo é¢Þ‰à.Eð .‹A•±AšŒwÃh/ÝÊ iEHzWœ¯Š…ª8ɉÁC^ܾ&KFA†-A6ó¶næ :¦®¨×ÕTÑÖÔœfJhÓ³9Õ.Zš„Ý•§c¥¥¡æ²©9ÛÒsÙÑü¡¨V¶¸ªåìù[y^ÚäÓ7ÔB*›«÷Æâf$£Ò–î8#!Z /!¬çÒÅeÕæJ‚´Dÿ²–YÌ/êöŠ„¡jÿL+›ÊZjÆÐRiCO›««j.3¥ç´YLjão8£å--­ÚZFB˘žÓíÃbqŸùI[³ÔeCí_73šHafŠ«Ëš5/΄ÃfZ5TKkw³Åtà Ú+:3¼ëÙNUæÇ³-¡»ÒÓë©çkƒê´ÍÙjúê´šw®Ê(ʸ.!¹a‘pV³g×)³)Þ_Cš½Õ{ œ‰¬¨…c.[$ Çk¨Ò¿‘lª¹'è´¡«{âRS|~2ävÆ?á§êæõx+ÉÚbi…¢ÁÈzkNu#£Y¢ j>¯å2ÓZ¡ fYËT¼¡òR­QŽ–ûxu¤Wx8R‹º± Eë1Ã0oøÐïgëmñަ¥ž74ŸŠ¢Ór_q9éë\…WO•w¸–/jÝh¼Šz"#ñÿåÐzÎ,Zií¤.Zª»FkP *Ø$}ÙÂiµ°B+ ¶c‡Œ› na·‚]bèÇïá¶‚÷1£à|(¡³º 2>Rð1>aÑÊ Sz´‰5 ‚‚½xAÁ$>UDœé¼P~Ã.*8…Ó ö•Êï%>Ä‚Ïñ…¸û¥‚¯ðµ‚;ÂôÎg¥¨ÂñÙå+ZšþEkߌõM' gÓ6-‡0 ë:ú ¦NVçÏŸ=!!¤{ŠÝLX`©e2zF»I«Áœ3Uö\É%ÑNµ§e5CC]ñZ]AáºmѸYC¶YÚb×Z.+ÈËØ&%ôÅÇÿëb Ý`¯ð)ð³sÜ4 º"((¼á{±j^×ð<ÿ¸·ñë QÁ*°>\¸ÄòÖ{ø#™åæœóÎü%ýNîíÇ׃\ý&9ŸI<†”x‚ÀùÇhzˆ`âG4?DKyGN®!$azÿZ%ÜÅV a ¿"2“ø Á5(,Þ{ú碑⸠!ŽÛ¹Š¡=èÆVú½£ôé$¥Ij¼Hôa¼Dÿ›„/üi;ÐßaÊ çÒÎ¥ƒ”»xÊšdôÉ8$ó‹¬ð«TŘfŠ+q½Yøúƒ£r²*6÷:^”ð›]Û%׸wG\788ˉ¤H€ir`ÂÎv?/'¨î’š†ì–ª†ØÙãç¨cæGaf„;B'”ˆFÖí|vévÊçrȵ#áx=Œ¶zCÄ8Pc.ÆÎÑ}‚vr cйëü JR̰i1!¤hô¹ÇØìˆ]ÑnŠÉGˆ•S³…†À¯Ö«ÓÁ¢ô0§»ì ƒ.§jÈ5"GO¥ú† ý™ªñ޹nÝæJ0¶·ï.b4Öó-ÂÉÎл˜n=ðŒw³"`9UZ®Ä;éÛ;:"@²¢¬ÍÈö§àx°v.UàkÊ®ÏÛ¤XRbI3Dª¹Ç -›¦¢Žk¢|Z*tzD®‚ãB!4q< b“ALáC›[j]y¡¯éÆ–~D=´' â*® Çf¨] Lßrœ »Ês ˆZ«ü(ÜšKŽ¡ïL=VMLŽÅÌ–lª‡c:N>}ÓPí»WщEà(QÉŠ¢‹‘$UioÑå´é¦¥ÔU¢Ã1¨óªÅÐQ>1rË«ªbíÝ-gqÌÑÜ:Ú»£fÍ9´cùЩ¶y§«š{Õ¢ý:Ãà9¹ÂOR/Àÿ•ºøiPÑF¿üFz°PH 4¢¼ðˆùúmÒi’Î^ÚƒÑØ'x¢±ø¼èìA3­ BÆ&PÃ&`Sh!^ ÉH—p°)šLÄc¸NÖÔ÷ðÃG{&úžÏðÅ¿ Æƒï¨íþð.øRŒ$þ(ÛAÝö.¤%¡·‹ÀR,N¬`÷ž°~ÛvX¸€lMlÍ,‡›·Ý‰:†öÝÉàÚÉ AÝ&ÊCA'ÁÂé ®ì7"µ!ÙYr8GRÃí °ƒ Ô (6^fŠï›âè"pfSQ;‚Š!nç¸ÛÆèÁeÚGÉl=ÆZ‰sƒö›> wDÈO7Rè‡x…¥0Dòí!Þo)Œú<˜¦=ë“þPK A¥D£¢&3org/gradle/cli/CommandLineParser$AfterOptions.class­•mOAÇÿ{-½r-´¨ >W+p€Š"ÆDð!$MFxa²´g9½î™í¡øü.¾D%ÑÄà‡2Î^ÏrÒ’cšìÎÌÎþffwnûó×·fqÛ€ŽQiŒu“4®£h ‰IS°tLë˜aÈT¼z‹jÉ6ÃPÉ“5«&yÕµ­ŠëXO¹lØÕ¥}Ÿ†ÔG8þ]†‘±x÷ñ2CrÉ«<§ +ÛõM[>ã›.YN”¼ wË\:JIËi0dï½ômùäïxB©ËBØrÉå†Mªu0r$f„Žî§¬óuþ~Ó^õ¹ô›F†þ±Ò+þ–[.5k՗ލ-Œo0$¸¬©äÚz<Aè˜eèkÊͨ´èS ÈbÅÑÆVçï…ùg<±â‰?ÕdþÊ`±Smññ¢‘t\cX>ÂÇcg‚>Ðv¦Õ@]7|”- ƪ·-+öCGõÅ@›Ï”ª0‹ ²j¸žE7 7æcékâµðÞ‰W7xØ’Š1§ãf·0Ï0y¬d˜8ÎÙ3Ì¿5èó?U†Ñ¶=ì¾ q~ :5úh˜hþkºmqéóåÕêƒ_ò2w·íC^€2 ô\¦é ¥G@õI]ÐTŸ‘¥‡´G¤i4gL¶Í,~Ab—T ½4ö"A;Ÿ£‹­Ã`È‘m éŽò:CóÙ¤ú÷3q‘æ‚äÓôhbÆoPK A¤ÇÇà› <org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.classÅVëRÛFþÖ¬#‹Ä¸˜„¶¤5|ÁÜ’`›$š[qpZ'´&½ÉBql9#ËM^¡Ð·HgÚ!)Ó¤ÿ:Ó·èß¾C;=+9`bƒL&3ý£Ý=ûéœo?=:þûë sx c‹'è‘‘Á"GN†„%Y\â ®r|$Ë+ö± ×8®pƒã¦Œ[øDÆÖ8ò2ÂXç(pÜaè·¿3±†±|ݪ¤+–ºUÕÓZÕH¯Ök5ÕÜʦ~Gµº•#ô’aö†“Þð׎y« —›Ú`Vë[:Ã)aXoÖʺuW-WÉÎ×5µº¡Z†X·Œ’ ËYÑÔ-ýºa5ìb³ÜòÉ Ü2MÝZ­ª†N°EO’±®Žè¤AmÚEœÎ³0 ÔÍ¢­Zvá‘mÔMŽÏݹ‹6mòµ9™¨~¯¦«ªYImË0+¹NË”7õßÄÁ¯Z!]‡?úvuO"¹wƒ–…Ët¯÷¶IUhÅ8*›\ŒŒXkÛ·ÕGÎÇå(2l¿•¼ò>¬“{¾'3â1+s ±^Þc‹õ¦¥QΈ„îÀL íœÁˆ‚aœæ¸Ë:–¦âå{ 6ð9Ç JØdˆzé©à>¾dÈxFºgn›õÇf—ÌQíÁð.­nÒÚO£Oü_<‘Üÿ'Zûð=OŠ=6>¶€ »€÷É6L{„Ç(ù†3£jK6†q¾åõ/ÐG£¾ ©”H²ô­Ç†ïú“ÏÁ}ø¬4"ýY×|âG„w!—´ Æ ¯<ÝÅ@)|Rú §JþTñB;|¹‹pI¼‘‘^!ßyêJÐ= Nt3D5‹Q–Ã[B’]FŽ]¥æqÅ¡¿àÛ£¯c“D[̦hæC›ˆ#I>GIž¦©uM;õýƒ‡Ä Dœm·@X‰FîèÇöõëŽÙœ8îBösj”O;9æÅlœ/tÑñq иBjQ·|–,1Ç%ÑMg‘ ¦yF¸  ºéUˆ^9‹Û„‹Ðø©äÃW4~-ÉÿPK A´*«ZMïForg/gradle/cli/CommandLineParser$CaseInsensitiveStringComparator.class¥S]OA=wû±P·RˇŠ"ˆUhAx1¦„¨MLšÔ¤„÷¡êàv—Ìn‰ÅÿÀ‹/˜ø`|öñãÎîƒEkâCçÎÜ9÷Ü{Ng?ÿðÀ&6 °Q)`Ì,9Ü5Ë=K&½l£fcÅÆ*!¿¥|m2ËÕ]B¶t%a¢¥|ù|Ðß“zGìyœ)·‚Žðv…Væœ&³Ñ+æ"”M?”~¨"u$Û‘V~¯ô…Q  NÓ÷¥nx" %œ©6mÜÁ#¥nÔóÖ›uBå_Єñ¶êù"ñ[šf)ÏýåØÖ°àm¦*´ƒîȧÊH›j·fŠpÉÁ\ëp ¥ß©LbÊûúèÿÙsì‰ ÂÔEŠ‹£Ý"L¦ïd'höü@KÓŸ0}Á›1/dü MXEÏnØü…qsYXÆ'>9|r9Ç\í=¬w¼±Pä5o’ô—yï$L Ì‘Œ…i±ft–cyeõ™í¹·ÈÍ›}ö˜³™˜©lôy:E¾Á¡1k-©LYÍn3q§2®òÎâ\Ãuæ™M&:åâÒcî#íÿ€ï2‹µ•OÈ­òïù㿈(&íJ`æR’‡­ÔºØ™p6k·0Ï÷,ÄøÛXŒã\‰ç·Øî*w™ÅM/ýPK Aè2 Á=org/gradle/cli/CommandLineParser$KnownOptionParserState.classÝXûwÕÿÜd“ÙlFMH²yðbÚ˜‚6 6ñÁ°;n63qf6 ¾ÛZmëûQj”jikR Uµ­‡£çôôOèá¨ßïÌìn’]ØÄýåÎ÷~ï÷u¿Ï»ûÕ×ý€NL‡ÐµŒ–ý!„“!1ñ’àeˆ—LPB2ˆa F·Â AÆCa•ÆÃD©0ÊÛ1 ‡BX…'ƒx*„<Â3x–Ož a7~Ê„? âçŒy¾à¼¼ áE>þ%ÿª¿Æó^bÖ—%¼"áUÙqtÓèw,ÝHHx0;gahÛkšÕ“Tm[³Ú#¦•hOXj<©µÇ’z{9<¬ñˆnh»TËÖ¬ºÙüw ”zn¹«ÇCÔå±,2‹«">‹‘XJlGu4 o·gB?#Ú Û:‹žMU“)¾eEä€:ª¶§=ÙÑm‡ÎÊúõ„¡:)‹×Í;Þì퓪‘h÷ïÝÅâœ!Ý®ë¸þÍ= ˜z³nèN—À—…É…ž/ìèÅ9³i@ ÐcÆÉ[˘$šÞ¯Y»ÕýIÂTF̘šP-÷>2ÀÞ¨Þa˜c†gÕœhn*l@~VòmÈ4º­DjX3{sÃÕ´ØT ªy•¹â–aì`Ÿ:âßn)ÇBµœ¨6î)‹Ö¹4¡9ÛT;{“âÆ¦ÝËçHRc/•¸)L•`:CšµÓ/=yÄ gz›“`9Ñö³B›Þ’ð¶Àÿ¾YY˜z½›¹E㼬祓— ¼läå6.ÿˆ¡¸ô›)+¦mÕ9þÕ94mœ52ºð›qC¿X‘í,Ý–¥âöÂG‡e܉M2šÑ.£ëe<dlÄ2úh¾¶Mé„Ù2Óü Øà·&é\ñ:´ÒPo7(qS³ÃtG=¨)ª¡¤½Úb6Ñwî? ÅȲßâ6oBÆØÜm(Úðˆs(挩¶2b™£z\‹+™–»†ê6 Çd¼‹ã2v""ã¢2N"*áw·tyŸnÛ”U^æÐ•ý¶Q•Ï6ÿž¤FÍïb¨ŒS8-á=ï㌌?਌ð¡Œ?r$ºúRIG§z̈¶•1ÍÒ,ü,þ$ãÏ|ûpnŽ×½Â‘qžþ1þ"á¥PɘĔÀß± t.°®ç0-σk]TƒhYLu ¬[X[£–­²^G³TÇ´hJ®j†ÂmÐï!Ôœi-¥X«Ô«7å™:{#ó ŠQžaR•ob±ð¤f$œ!WW/͇¹¯B«ñø<î´š•4Nº“Is,3QhüJº½…ë÷ºiåÝS`;ŽêÀr5Ól»nýÆêÆ= Ö•éy<9ÿR9B=rZ:OÉãøÂS+g°_k¼Ò£ÇÖŸ`ŠÿíYÙØ”ûú¬ÍÄ*Ý\fÅ,¨gr¸zs:·I€4¤Úüö •†ûYÙØ”›ìôx<ûÀIí}–™Ù£sš-Ÿ#½_c†%sÄbiÃæh¦Ò꯶´¿ Ð¯0ýš*E%8‚*yʹ_tî—fû¥9».ÂÝ<<]Î"ž¥tòCÚF1a€–pó$ŠÂbÅá‹ N£d¥á–IHáÖIÃ5I”…k:ïJì¦u $@AH¼ƒ*qµâÖŠwQ/Ž£YœÀ½D³%,=ظÛ]äBly± ±íbëKȺ­¸Ï·ñ$iaúhx åG°ú"äÁÊ%ËX:XþRÿ,›FÅß›§°<}\™{Lpió Va ZyŽ$»·¨eˆSÄi²þ}¬gÐ%>@¯øÐ½Aµ§=sƒ(¶¡—lÛNpEk×¼ßÚ}„ô­'}Á)TM †5Ï Z`K.bÕ »ù†ssXÊŽÕ9(âcW±ì òowi…BHzÈøÚ:éËDA_ÛÙLlJOв‚‚¾ ÁÏ_¨ä[öûöíf™ê9²&¯#ËxµžÖÕíFz]Má&Ø8vÁštPÖæÊ ]}-3¸™ÕVp‹À§¸5ÚÜ:…º3ßü×S?C‘ÉÒݦkˆ²ADÚxæ›ÿÊ:µ“nq +ÄeÊÇO)ªŸáQñ9ÆÄôTÿ&Ä—8&þ…KâßøB|…Š+®¿Âä“·) wQœ‹q‰ªÄ=org/gradle/cli/CommandLineParser$OptionAwareParserState.class­UÛnÓ@=›¤qâ¸$”6\Ê%¤)MÝKÚ@)½p)E¡ E*oÇÓĮօOá xá$ ˆJ|…˜MÝ’*A./Þ™³çŒgf퟿¾ÿPĽ8È©Ð0*w×TzŒ©Èc\…Ž “*L+(¨ˆcVAQÁu†„á4›Ü®•,ÛdÈ–Q/Ô¯5̂Ѱ O¹pÍÚêÌCÔ{i¹¹™è\û èe˶¼; óÁð`ùñ CdÕ©Q²IéØh5«¦xÆ« ò ”ƒ7*\XÒö™.Cúɶg9öʾZÙãŵuÛ6Åjƒ»®I¸…À,s½™è]SMþ¶j’%¼} ÃP¾ôŠ¿æ…·ë…²',»¾4þœ!ÌE]&ܤ–8ö†c$Ž${¿]pÆGÓì§±õ˜oûRËNKæš%t×éi©¨!‰”†Ó˜ÓÐSnbXÁ¼†[XP°¨a Ë s™¬¼ðL±f ×+·ª~˜a°—[ªÝf˜:ç~½¨Z§)9höæOØS†É©­‚» cÁsž›mÏqÌrºœ |ê¯Õ¼ñ¯ðFËüËdUº©ºÔ©áÜ0L×ÍÍÍÐ-=ƽ”»õ_îïqk³Þ¥vr®l0.’¡Ï¥FÒå|©”œxò„¡!òJ„ÓšÒ'vÁtö!}ráOþYÐYг,T6‚$Ëaˆ|iŠÑZÏíÔç ûÌ‹dKTTŸø‚ȇC¾(ÅÁò<ÑCž(.âÅ.#ãóì ¯*êŸ&ª>ZÙ7Dß!½eSZ2B™ÇÞ#¹‡ø¦oªÛo+5UÉÀ¦cÓºÅCÝ¢¯{•ö B£*^ÙvÒ#8G«Ni$èy6¢˜Ž+ùÿÑ1Eˆ8­3$r£]‹ØoPK A˜%àÌ»ª7org/gradle/cli/CommandLineParser$OptionComparator.class•TmOÓP~îÖÑQ:¯ ¾€ Ý ƒ2@Š.Ñ,YÀd†Äe4³¤kIÛ†?„/~#‰á³ÿƨ_ç¶ N6).]ÏË}Îsî=çô~ýõù €E”%d0#¡Ÿ¿ú0+bN‚UÂJ"E,IHs;'"V8|UÄSk"Öz6LÛô7’eA(;íªi;­æ¾á¾Ñ÷-ò Vºníé®ÉíÈ)øïL!»{䛎]všGº«ûŽË WlÛpË–îy!–ªŽÛP®~`jÝ2UÂ6uû€§y­»žáN_åÐÄz`Q¢W…kÂH-¡TˆÓ ôÃT|À%|‘ÎÚ4yÔ`õP?ÖUK·jÍwM»¡…kÉÚw÷º¯uz”Š-ÇÖ¤¤ñž$Þ/0LßÍÐ[3¶î·xѪÿÚMË7-õO¥7â ±IÔRÍi¹uã¥É;?Ú‘~žSËÈb@Æž‰ ™Z½a×ÃB¶ÏÏh÷Οñ\ƶið®ö‚a+6eY÷ŒŠí¶gúæ±Ñ™{"!c /&ãªÆqã ¥ÿý¿vŽa¸[ëhŠãÇ‚Z×0ü0 }‹¥m j†¯]{–…a¤=¿eÑžBº$Í>•½Pí¶Þ}à4¥s2¯|=ѧÕéQ*t±e躣KŠ.@ >rd ’¥’d$S3gH|$%!z÷p'û†aÒå€Ü!Éx‹¢àD–"¹2{Šä9„·ì ©Oè¹€¸Sìp­ çHs»wnL8…tr™­I"þŽ!öyö3Ⱥ2GY¹v÷‚¬à>i<2‡˜ Ø<l’4!»M»{ín•Vˆ™™Ù ôé ùäš#fÂdYþä"’5’‰¨>¬{}FCÀåNS˜Æ#ZOâq€Ï£H·INQÍ2(RÔ8éô˦ÉSÄ<Ùi’Ëÿ PK AäfC˜§£8org/gradle/cli/CommandLineParser$OptionParserState.class•’ßJAÆ¿³Y³º¦ÿ4Õ¶Ö¨£×JoJ¤P¥… …H.¼›$Ã:²™•Ù‰ø }¯/ú}¨Ò3›€ˆ…4»ß™³ßùΜýýçá€#ÔB°ÂÇF€ÍUBñXie? õ½Áo¦}IXl)-O‡ƒ®4碛pf¹•öDÒF¹ó8éÛK•–ή­Jõa2iÚVXþTú®µ4ÍDd™dËÇVjâ(6¢ŸÈ¨—¨¨™B÷]ŸQ]í¤AXH5‡ÆžÊ[ûÅĶóOúÖ÷&£ŸBÃT3k8ÚNê­+q#¢Dè8j[£tܘš¸KûMdT¾Ì‹¼W^'ÒÊÛ„Ýúdð‡†[ƒw{H¨ý›»´Ó¡éɯÊm¤òÌsàÆ+aÅ;„£é÷@(?^ÑY÷JöxÂ÷Ó\a{ò(„ê$“_åÿׇ{ŠðÜL |ŠX‰ufÿÞfs'é'æ8. ñðygXÊu+¹®âe®—/;çÚþ‰ÕÃéßðÊÈ0‚çÑ:^çeorÿ[nÎø}‡y?Ä"k™õ•³—gÿPK A¢Æ÷E«¶3org/gradle/cli/CommandLineParser$OptionString.class•TÿNAþözåÊq”ZDQ‹´GËQÄŸ kLŒ&(ÿ[®—rx½kî£âø/$‰&>€ï¤qv[l“B“ÎîÌÎ|óÍÌîýúóý'€9<éE?LÄ´Ž4ŠB-¥0£ã, ³:4…( 1—Âmá;¯á®†{ Ö²ËÛü#·<î׬µ8týÚCOЈÝÀ§Í¢ë»ñÃT¾Ý¯ÝRXgP+AÕaXv}ge§¾é„oø¦çˆLͽuºBoÕxËŒU™° Cê ßwŠǣȡSk9kV-äUϱlϵ*A½ÎýªHñš‡‘æNÆSéš?s£†Ç?¯ð:幘/t*´-æö‡W¼!éh¸ÏŠƒæ±† /ÏTww~eÙåÓ¬e!ærg‰cèã¶íDQ®ä¹ŽÀOE„–;McBÒ»…ÛÉ-Ü!¹%Œá.ÕÌ"‡{ä©äN'Möë¬zz‹ÆÇY%¼B65[ümŽ~çèkÿE“T‡BZÆ“q‘5²<”]/h¦¸äŸÀ}LѾ‚>‡‡‘ÆM²c”ïGÃäMHxº¦) ˆ±ïPK A`M~U¸2org/gradle/cli/CommandLineParser$ParserState.class•SßoÒPþN) s€ÛÔ97Õ½Œ&MLÈf‚ÙÃÞ.а.åÖÜvFÿ'_|ÑÄÿÿ(ã¹-›Ý Aš´çG¿óïœÛþþóó€´mdQ³‘C-Ç6êxbaÇBƒ{áI/zIÈ4šÇ³Œ\ÂjÏ“îáùdàªbàs¦Ò †Â?ÊÓñ4iF§^H(¼*tU?'‹ï¤tU×aèòËv/Pcg¬ÄÈw¡ï9Ý`2r¤;$uõTy‡Pšˆ/—#}Œ¼@Ö½3ñI8¾c§)OŽ;ÍBÞ / ¡ÆZå Ž°È›…&¡œøWtŸÌi2§íâqf¸YC!‡¼ûzÞPÚ•h&ß—ûP2£»e²»gÆv¡nÓ‚$Ù$T@|„*>AŸÑ%¾ W|Å):ËT Ð3€¿â‚Â_qIÅ_q3!ŠžÅ¹ t–¯^= xÎc @椚ÙCäÍ!ð÷:°Z_ eªàYòÊqà>8YM¨ÝHÅEÿF‚Ÿw@³@9\"žÙ!µvÚC”œzÀ¨1‹ø‰vñ«®¥x••&Òƒá€k$}ËŒfÇö!¶uõÁÇÏTsj]Åp9Ð9†+Î1Œø:ó*…4ñ*4fEù!Š´“æ¿Ëœ¦./1YœŸÍ ®‡µ?PK AdZ›Ôl)&org/gradle/cli/CommandLineParser.classYi`\Å‘þJš™7zz¶eÙ²=`láë–1¶°åS>K6–±‘ÌXz’Fψ™¶8B¸ÂŽŽ``‡‚¹d ÙM¸ÂÈîØÍ²aÙƒ=€ !lÇÇ~ýÞ›ÑÌè‰üPwOwUuUuÕ×ÕO¯{ö€YòT:ñ±jþW5¿×±Ÿhøƒ/>Ññ)þ¨sú3 ÿ§áOùø >סã yøRÃa#ñç|ÁÑ|ìÇ1ÕׄW‹ø%GÇÉÕÄ£c¼xýâS¿5ÕøEžŽ]¢û%_ͪ¡fFúeu‘¿ŒÖ¤PÇt|ÂeŒ&cu”࿱—qª¯8&¨& œ¤äž¬š‰JO‹ï”|7#ñP"t‰™M$(°¹ÓùÎL8?²=ݱ×cq3Ö”&LMÖsÇsO°¶A0ÚeúAQC(çÖöj]¬ÝZ¢-um 3fÏÆ5iŒµfÎ Å≦îmÔkG0ÒJKͶhÌÌš×dcÊu;ƒ13cßM‚üŒ‰ÍÜ0Ý[‚1«×¬«_ݸµ±®aÅÖ5uëÖ­XÛ(¬ê ^¬îN„ÂÕ1³ÝÜU½&˜ V‘ù‚QQ[Ù¥=I£Ò¨‚]¤Ék µG‚‰î-\‘¹ºÀþFÚ«móWEcíÕí±`kجn ‡ªÛV…"¦­ìüE”9:Gw6„v™­Ž»Êú1Ö|ÆyqeÌ41ë×òP<¸-lÒ‰¾¡H(±H[RÊsô,‹¶šJîÔØ½c›[§…«¢-Áðú`,¤~;“žDGˆ’§|…º¶³©¬·Kg–lloi¶‹­5M%ä· ü¤9.bˆI+vµ˜ÉÐÙ"˜[’FUÏóRŠo;ÃRØñ¬`öFNç”â3#­ŒmL=ƒ šŒ4åPõ%$Ðl¢ÓÉuöÎ * cÝLate+ïr"n꣓uUC›—iظ̀èéJ…›Ç]B\ð kÙΰX5¹P°jØìÃ:ÄÉ)Bˆp(^H˜i%ƒ¹…¯n ZÍükn »‰Ý’É_>N¶§¢‚ Ïœ&3A†32g R4ìÑd«Š Z”8?lçyÒO¤®«‹m'áˆf@çØh¬ÕŒ%sÆžUÊuÅÌ6ë’3iÊ­ Å•¾¹ÛÍ¢Ä%Áp77õš‘DLý^a÷E™9ÍšV\ÑEW ™p¼ vX8)â¬ä4iFf(Må¼aú„}îŽà.ÁÔl?ºFò´,ƒN@6ßÍ 7üwåž3ô½á§ÉEš5ÙF¼îŒ†p JÒ-‹†Ãf‹n1íR^¢¾:ít[½­“BÞY‹ñÔ™dïÁ3‰›©R÷­»­M΄A-µVÔvmê‚ϼ.(SžYìn‘Z¦Q_;¥S™©[ZÌx|Úœ™3ÓK†FR^Ñ9»fpÎUœg ‡sPY‘1O‰ð/ ›}›ëMÑîX k#…ÈãIªRr ÜŠ[ Ü€ ܬFßÁíD¨-Î Æ;¸&-†´Šià{¸OP<ì’Á´1¤MÚ¹ƒt¨†·\Í×ku§¸;5ÙnHXv‘¨!]r1%ûð ‰ Ã0§²Ò„t *‡Ü1½ðT]BØ­¬ÜtáÂ-å†ì”¸!»¤ÇKå2C.—+%‹ã¥Ū2C¾!W*¢or•\Mx´ÖÕ²ZÅm¸…UŒ3W¹¥ªŒqŸ\ÉêlE,rRzüà´…[UÆíºV®3ä[r½!7(GÜ(Wr“|Û›åjCnÁí†Ü*·ò%*ûÜŲ!·ËwYX¹À¤Š2Îu]Ì4y®‚Ó‡Y <'”kïP͆Ü%w't°3²ÝluY9LáÙC¾'÷d˜R‹{23$*Š ¼ƒ0d·\/€!{ä^C¾/÷hrŸ7å†ÜŸÅžkCPáæ™ŸɈ: ù¡\lȃò÷™nÑEñâbÅ`ÈÃ*ÅÆ¹c&{ý>Vi%±¬=f Ù½ƒwbª¼eic›^ÏRĉ^ÒÉw÷w¶`Ö× „OðFŸ3<,ôdn>g?Ü_çy2°Ï|ô—Ÿ˜Þ%õ €Áz¢Xç>"£Nd1ìV“fY72³pLbÊh1s}Á¸½6=£JqŠ®ÒÁÅ´Ï*£É9¡¤ôDuXàU ªëÇ»?›¹²}eÊг¡›§[»Ö‚eN(åóqæ%ÏB=—:‚ñFsWÂú®Áz˱~Œ-)u+Z v{¶©—p,‘|”•¸”ƒÕ{þâî`8žE< ÔrÐ_n¾ÆÛ·¥Cc^¼{[܉բ’z×v„ ç46º˜ð—<[]¿kŒt6SN¶¾oÌÆ;:낊´š»ÔƒÚC“êÕqÖ»›¦[àc¥¡`©ÛÑ|ݽóÛ(~®zvú‚V†7\eŸ £"šzü–¸ª>²ÝL°žP_·k¡°©pÊ6#í‰+Lé€üh¤1I`E™4c…Ò/·]AËin±çع¼™<í±hw׆ڧ0=ëÕ—g3†Nj'"³@#yëYk>nV²0=tziÎH_û»…ò×r3Þ %?~u©'þ\“‡éßv³ÇBä‘‹ Aå ¯Š7ºÝo}m°hüÜ~½ý ÂÇ¡öW„‡sú Èé_&º%î@,yÛÂÝñŽäÅ‘å<ހà MçÙ<ïkéš³®àÇÖ­²0nGRZÕžñA<[1ëQ; hK½&§i13|d³7ØLó]$7$åJ“¦þÙAÈh5㡘ٚz=©ïæ‚ÖÂè´ž¿_‘Ó.Ÿóq*:±€'©ª—£õF†à&kümþñ¹loU}Áõ²ãï¤ášíwùkr9ârÙxÊúám>ß3ÈyÂ⼃­Î˜æâNŽ ›wánöWñ¹})”¬…ìm^YùAh½ðïO ñYL+,ãl"G€íÆ®ß˱‡ý÷ùÇ7<£ÐÜ7hb>Åxú‘×ܽ¹ìiäô!_pÆŒhèÇÈæ² 9€Qå}(à Âðôa´`·¼®F…‚¿Â˜ZoeÀÛ‹±»å±€·°¨ãv£ ã›ë„Æ}r§½8i7N"eÀKâ“{1±Öðõâ\N‚IAUÀ[°°“k|6e)Š­Ðüå¹Èâ=•Lg“iŠÅtªEëñ:¤ðúRt“ŸÄÔ=("õ4RïA~?¦ó(N{,$ªõ)³¾>ÌÈ¡»Æ)Y>gGK;¼åÈ®Õ,JÍ¡¼ª²%TZXÖ‹rE\Þ‹ ÕO¬õü½¨Ü€?i.UÁMjºªÑ[“W”§\Vý æÒ*þRv×ê™"uG¤žYÕxmžì;þâ>,¦.’®®³¾Ó‡ÒKéÖ‘ÍlÜwlfe/N¯ØoEˆŠ§'QÁöÛõb¶ãô Wb#Ó`cm3Æ< ñרŠ_ã"¼KÊ÷° Ÿ£ÇÑ*#`Êx´É)h—btH):åLl—&„evH'¢Ò….¹ËMˆÉ^ÄåQþ~;å9ôÈ˸TÞÄ7äC\)À5ò®“?ãz9†sr˜–*öÅhêåÃp?Û»0à‡=ŒQÖœFÍ {•ºØtw›‚ñt‰c1~DŽÌÎÁ†k½ŒûßUôaŽ ±Ò!Œ¯t0¨F!SE/ÎÜwüƒ²XžÂSýá'æMâ©Íd_ø8ç¼ç¾‘g¦ôMÍ'¡Ð9Íóø×K ô(=SXº-,õ3úð,-Nž¡=ÓÏu†Sá9ÎPôièÔðœ†çÙ Ýñ¦Q³ûc"™áÛ%¹Ïp;°üªs›Ë`q·–x<¿™ð¹à6V¦€¹‹è‹~,¦ï–Ôz*-wÔü‡¼®FŽG|¶˜:%f)ÅXJ¨X–²œBV4[J^ Ï‘²^l×úT{À”€ß œúp…íÃäå¢ÁËÇ÷ü…gÄ9Ü…*Ô+±/#ß’½ZáJNxy½çæ*ú™ŒuìR6+í|*,í&©‘£VäUÀV} 5^ƇbiÌÒ•bY­¼Ð‡5»µùÉ…çyžÇÚæ\µÐ$hêÅ:4¯"iÏù4¥ˆh¹¾pƒm”7ƒ¼ÙãH´ßÌ8¼à‰T ^ÊÈRè”Çx 0ÓK%³°k˜ŸAæg„鵓r7sä~ÆÝ!ÆÙo_ÿŒçðžÇÇœ9Ì`9†Ÿ‹Ž_K_”¼$³ñ²,Á+² ¯J;~);ñšÜ†×å%¼!¯âMyxw§•Ø#){9í%ÊqÇGˆÒÏ2wR»ŸãŒÞ0 /r5{‚—,º5¤ÙËðqÃBH»\ˆ—‰ƒš Öd^pôK¼ÆPΓñ7xY§ñ+òçb–Ü‹7X:y¨ñóx“Yçµ²F园ɯSšü-1ÍÞáï8gËèOÉø{zSe× yµNv½¥a®•`¿aZx¼úà 5Öøm‹èCãd"æQL´ðtLîq:ɛŠeÍc%,3w„…Çä]}sÚêê²Sž}ÆÞÇ~e?š2<‹Ê_¯p媲>lJ¯›0Ý©›j½§ìA^Ãió† uoQ£ÜEûŽ¿Ãø¹pê8Ð~?ÞâžoSÑw/¿å-ýOijw‰g¿ÃÞ¶Kñ/´ÿýžU°üGÒy•^¤}×B±•Œ«‡,ÌZJ¾÷,;–ó–ô;É¢Ÿ½òøxŽb´†f9Ír¶öKêaß2ÿJ|ß‹sð=ijSž8TÞPqhQn§ÈsʃØYQä™Uëµ@Ýë”O~lm.¼ÈI=oÓA`‹2/-ÉõÖìõ'a*oµõ¢}CÓ‘Ms­‡wÅý¨iVÕò„*,ØK¿:&U¦@Äcéå©HbÏ{V5”ky¿†E=ð!Æâ#Þ&³Pÿ==÷ k Oц?âr®]?1Ë>gŽAäù’y{8u cÑaÝ*^®Ž°òHÝ*‡R·Ê!çV¹•g©ò-y‡hÇà·.Ž#¨f€N>Œ©_À{EV43$§øñïøçf®f¯N¹8÷Ѭ·Áœ´;ÙËlçÎdþOü— sNöÃÂù¿]w–aìÌÈûŸÔi‰µ ;{±g<¹Oajaø v<sð[©€Gò¸%.ÇX"œüÐ"ùQ kGOa©XÇg\Ÿp³±ŸÏ>Î>Á¾›â.a¿“œ»Ø÷xtòvâ2Îg9û+؃ë#Ù_Éþ›ì¯òäð´;q é¯eéV)^ñåý?PK A‹å>É&org/gradle/cli/ParsedCommandLine.class•Wiwg~FÛÈòÄ‹ê%v“TMc[–å’ñR·Ž›8¶SâÆÆ)-L¬‰¬TÖ(£‘·”.PhÙ¡liÙ7 ’`rX¾Áá;ßøÆŸ œœ˜ç}g$KÖ¸1GçÌÜ÷Î}Ÿ÷Þç.3úǽ?þÀü.‚v˜*òø`Ö!‰‹*¬‚΢ .¶ŠbuŽf¹¸T“¸,.+*žWñBM0#hÄ'ëñ".©øT=^ÂËa¼¢âÕ·}:‚|FÅkt ã³âþ¹0^÷7„ÅçÅÎ/Ô㋸$–__Vñ•0¾A¾V¯ãMaó qù¦¸¼©â[ ͼ1s…#+3¶•É¥©™¼ /ëE;“˜Òóà êf2éœn-CÁÉê§#Î2«çÒÀð¤i¥Ò–žÊ ÙÌÀ“ºU0RãæÒ’žKMfrÆ)yâð(‘ò–Q0r¶£*T>cØ4y¤Zãq ²Œ%sÙH•ŒË¶¥Yéâñ©hªÀ™Ìô¾Mª-°C#™\ÆUЯ08a–~.k ÷Î*Œ›)CxÏð¦‹Kç ë)ñLAtÒ\г³º•kWYçpÎ#„AÍ™ ´¼äÌ FA|»”ÒWÓݳwó/뀽˜)xØÖàÓV5KÔ¶x±  ­:Ô•|)ÜÃö#÷wOP¿cÆÖžcI(ßVñÃ^yØ¢ÈUØ6K¥Þïõ¤ÿbÑ´±\jÂÌú½Óîµ3Tp‘UG(ˆŒí|ÑVÐQ³áH1“M– 7S8–± ´RΊ|{…çY›#Û¶õô·nQ/”ª¬5^kÑKošu·O;=F‚¸m,·RÚÙ¯h¤q3›5$ßbwcÖLOËF¶Ü™mÞÆ ž¶¼ßûLïÐÏn"ªÝöûª9mØG7M”h©z*gJwr‹vè©”DœÕ³Ec úY®ÁeçyíK„?ëa{ÿòÿ?ÂÕœqZ:¯«fy Ó×ÈŒY´ŒcÑöm5ðû…Óã Ý é¸^Xd‹kèÇþšùÞဂ6žŽY–¾"Öð|PÃ[x[Ãwñ= ßÇÄîç1sµ=>4ü?Rñc¶ÂfÖUüDÃOñ3Ýñ8ë*$cÕ/GWý†º*ÀSç.°„5œÂ“~ŽU¾n¶˜ |ɘ†_à—=¦0­a ç4ü WU\Ó0³~ßp´WLöHZÏ–¼:zyÁpyØéøëé*ôÄr¦Kç}j¿Ècü­†ë¸ªážÑð®Ö’[û£v.•”2}Ri›ŒÆ—c9SV´UõPÉPŒIÎir+÷°©9¹¨ã‘´Ž°gËS§¹ Óù´ØQ¥¨Z³yˆœÛ‡ãµàµOBçMkI'Æ GÃ>ýÞ ï=Ÿ7r©‘W=¶~©„Ìœ­gDô­1[¼f(O :º½6y…ÙP=𸟳J8žJe³œÒÇÃü2mç‡sQÑëP0À•ïãš-^^äúЦ5[¼¼þêy?ŒAÊC€2?TjÞH܆’¸ßümøo"@1H1tꆦXG1rõ}kÐL%×°CÁœ¤Ð à¯hœ¾ƒ&Ú4úo!º† ;‚®]LHÒ°e(”ø=¡ŽÀZý˜[]ÿ×êú;7dÃò?‚Æk'W­ü¾o£ÔÎÏñ ùAþØ…ì†=xá5Äð:IáŽCüa£b!ZÀcxœ(DÃÌp1Ž')Å1ÒóaÊïŽæ8¥”÷!°NÎü*’*&TþïÀ=t«hTÑÄÕÐý_éP;É=œ'¼’XœáÙ­/ÚúÚçý F«ÞÆÎ™ù€ë¥bXˆ@Çu #Bw¶vÉp§ú\‡}bÈ9¹Ã»¼‡x?}düÁ©À¨“•¡€àTò}HH.ßÁÝo!’Œîº…ÝsÉèyëV¬ü£«ëOÞÂC×ËIØ/ë¥a$¡qÖa’xA1c¬¾ã¤x‚š)R_J@{ñ& (ü+“}š?Av˜ö3xŠþG¸û f™”«97­ðßCTE§Bºï"¦¢å]t¸Œ”Fœ×.ã'¨ññޜ軅؜ ›t<ìõ2¯i Êâ1éi›³¡ì_3ã%œ‚§ß6ì ;AØ“÷ýžq“÷6ïA-ÁöV4Rg©‘Z¦l G® ¸¶ºþoÿµrNÚ$«gسdyŽE:ú+ŽŽ‘ÉN:$ôËÌ•œèųøxU¡ Í'\ž5øïB%Ç»6 Zç3¾]^ᜈ¢kéô>lšJþ ;ï k>ÚeÞ'*ù6zþ’Eä—Ge¤)ö¤Aù<],;[í¢ÃS;\ô¬Oº†r=l8>Y ŠÃ߀äŠ^ÚÜ9ÙŠÎ ºðNL¯ç‘vczÂÍ­&@S܇¹›Òšg\¬H«VvWc£òŒ .¸ˆ97­{ªXšŘ”ã°—GôoøÛ )ãªÈ‘¶,ÏI8åsöÈQ¦HI 0­›$AbïsŒÖ9ûŠ{ö`_ið–«*^QUt¥ Õ ¢š¹èó‰ñûÏåŒ9%ö<'ì tçE¾B^âKãårÖvs?ê–Ø`ÙÑAé^EAEXP QP –dȹÿPK AyßtÚE,org/gradle/cli/ParsedCommandLineOption.classS]OÔ@=ݯîGeùPa„eQª¨ø"ˆhHV1YƒÁ·awR»í¦íá§ðl⋘¨IÔg”ñN[`Y$ñ¡Ó™Û{Ï=çÜéï?ߘ“4²(ª˜H#‚b ¸ž¦å†ŠÉ$ô4¸™Á-L%q[¾ï¨¸+ßÓr¹§â¾Š [ÌlpWA¶´É¶˜Þð„©—„ëÍ(H•…a1¯áp#-Ÿgƒ³É,C/{ްŒ™9*IÌ Kxs ¢…ñU±E»JÅ%añ—Ú:w^³u“"¹’]aæ*s„<‡Á˜·!ˆI¡d;†n8¬jr½b ýs\^]´k5fU%ÔJݶEí’÷V¥Ý…ñ³”´•=Vy÷‚Õé£ j”;*i=z&xŽÔ «V£Qã–§ §p6K:dÇ)¹ñKn07T@–½U.Û §ÂŸ Évàé“ICzt°]p¶-)kèDNÃ(Æ t]6Mn0“,ñøÒû ÷±(#ÍWmîæ-ÛËo°-žgÖvÞ¿“²Ñ°Š‡f0« ?L'æùZÃôDÝäA¦K©@Ó϶*Õðó$¡Ñÿï)”•õM^!ÛO†îŒ+vï–i¥áÊQ,7_… ”¬ŽÒÀZ~“¾«Â]ªÕ½m\¡(K? LºHï.:EÐ8íÉrZ/PdQÚÙâ>”â!"kûˆ~E쳟}‘Vù_‚*bTÓG;-ÈÇ%ôûø¸bí„XÓÅoˆï¢í‰µœºäÏâÄ"¡Âpú(=@&‚_Ðö¨2êwì%Ž ^*õè$üAêPÀPS÷é°û =1D:¥š!䉩ä¡ÓIfÅ%þÞ±„n‚‰‡05W(v•¾bžRD ×$ÈÄÚ"xÓjÊ2D¬Ï§ìç†xr7‚k> º½!âóV.p£]Á.ÔØG²àÓ±ô€ãDÇ\“Ô8"Ùy Rð‰ŒÿPK A\vÆB| :org/gradle/cli/ProjectPropertiesCommandLineConverter.class’KOÂ@…ÏD|?PâìÀšuã#QŒ+¢$÷C;–1m‡  ÿJW&.üþ(ãª1ØDã,îéœ9ßôv¦oï/¯ö±[@yl汕G)‡ívÙ }FHWkw„LSºœ°Ü!¿]®nY×7ÎZK:Ì¿cJDóØÌ螎ZRy¶§˜ësÛñ…ÝVò;ÚHŸ+-ø )ƒ€…n´kS†#cruLXõøgh|Ó×B†„j­õÀFÌöYèÙ­Dè™èÎè%×LøÜ%”ÖŽñŽ…Ž*‡_‰¨å½?õÖˆ:("‡<Ú„bJÕö ®­ØŠtòfë^*K÷¸Õ ßµ¦ XUÞðV½Œ£Üi01Èk ÂÁp8ƒwZ±ß8T0gî?Pôa¦Î›™m”ŒÎí=ƒžÌC S³s ¦§£‹| Ë1\áôZêq-}CÓ_èJšžEˉèjš™E+ ¨ùw'©õPK A Ï8=|ü9org/gradle/cli/SystemPropertiesCommandLineConverter.class’ËJÃ@†ÏØ«mµ¶ÖjÕEÜ5BPÄ…R/Pé~šÓ‘$&ÓBÞJW‚ À‡'i©AÄYœ3óÏÿÍœ¹¼¼¾Àl— "l¡Y„Íl E Ê<&Ï dÚú@¶ËÇH ÚgÞLÝŠ{:r”Rïs‹:C*X4NĬœ°€ÀQŸ Û´;hZ3a ѽÜG!]îºÔG‹v¹7S"Š5eb o}ɸG ÑÖûtFM‡z¶9‚y¶²¶~X{()spL`7e.°KV, øTXxÉ¢Šõ¿”fDT E¤G ÄPÇWãJm®h~²­Æ49Aíjx­µÑ° ­ÓsÃhöÌ gÔ™¢n8üÇ5©Û] .FÔ’¿s°9õàQˉ΢ⲙ*•sû/@žUg J*æc±e+sƒÊ+1¾ Õî$p¦¾ô´€6¿¡™/t-Í,¢;©h-Í.¢Z ª>kìZÿPK AýØ?¢gradle-cli-classpath.properties+(ÊÏJM.)¶å**Í+ÉÌMµåPK A%gradle-cli-parameter-names.propertiesPK A íAMETA-INF/PK Am±>=@?¤)META-INF/MANIFEST.MFPK AíA›org/PK A íA¿org/gradle/PK AíAêorg/gradle/wrapper/PK AªÙfØê -¤org/gradle/wrapper/BootstrapMainStarter.classPK AhQþ}¢Ò#¤korg/gradle/wrapper/Download$1.classPK AÇåî©L4¤Norg/gradle/wrapper/Download$ProxyAuthenticator.classPK A5¶<›Àœ!¤» org/gradle/wrapper/Download.classPK AyL¢¡Ê1¤ºorg/gradle/wrapper/DownloadProgressListener.classPK A!9|¶„ 3¤ªorg/gradle/wrapper/ExclusiveFileAccessManager.classPK Aì„,y†-¤± org/gradle/wrapper/GradleUserHomeLookup.classPK A™c67§ *¤u#org/gradle/wrapper/GradleWrapperMain.classPK AúâæªÛ"¤d-org/gradle/wrapper/IDownload.classPK Ap@áõc "¤N.org/gradle/wrapper/Install$1.classPK AT¨,-t+ ¤ñ5org/gradle/wrapper/Install.classPK Að¿:öo4¤\Jorg/gradle/wrapper/Logger.classPK Aon¶`8¤Morg/gradle/wrapper/PathAssembler$LocalDistribution.classPK AJØâ[&¤Oorg/gradle/wrapper/PathAssembler.classPK A„ÍëÂ| 0¤nVorg/gradle/wrapper/SystemPropertiesHandler.classPK Aª=©°?-¤~[org/gradle/wrapper/WrapperConfiguration.classPK AGü¨ (¤y^org/gradle/wrapper/WrapperExecutor.classPK AÔe‹ #¤Ôggradle-wrapper-classpath.propertiesPK A)¤4hgradle-wrapper-parameter-names.propertiesPK AíA}horg/gradle/cli/PK AÕÜ?®<S1¤¬horg/gradle/cli/AbstractCommandLineConverter.classPK A׃µ³Xì ;¤7korg/gradle/cli/AbstractPropertiesCommandLineConverter.classPK A}­ÎyGK1¤èoorg/gradle/cli/CommandLineArgumentException.classPK A³ßâúg)¤~qorg/gradle/cli/CommandLineConverter.classPK ASf Õg&¤Þrorg/gradle/cli/CommandLineOption.classPK Aü튯¥å(¤$yorg/gradle/cli/CommandLineParser$1.classPK A™ÐÆ­Nå ;¤zorg/gradle/cli/CommandLineParser$AfterFirstSubCommand.classPK A¥D£¢&3¤¶}org/gradle/cli/CommandLineParser$AfterOptions.classPK A¤ÇÇà› <¤©€org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.classPK A´*«ZMïF¤…org/gradle/cli/CommandLineParser$CaseInsensitiveStringComparator.classPK Aè2 Á=¤µ‡org/gradle/cli/CommandLineParser$KnownOptionParserState.classPK A$ľ¢¥ô<¤org/gradle/cli/CommandLineParser$MissingOptionArgState.classPK ATK>ªÄ=¤’org/gradle/cli/CommandLineParser$OptionAwareParserState.classPK A˜%àÌ»ª7¤•org/gradle/cli/CommandLineParser$OptionComparator.classPK AäfC˜§£8¤(˜org/gradle/cli/CommandLineParser$OptionParserState.classPK A¢Æ÷E«¶3¤%šorg/gradle/cli/CommandLineParser$OptionString.classPK AgAq²”x=¤!org/gradle/cli/CommandLineParser$OptionStringComparator.classPK A`M~U¸2¤ org/gradle/cli/CommandLineParser$ParserState.classPK ApÍX Ýk?¤d¢org/gradle/cli/CommandLineParser$UnknownOptionParserState.classPK AdZ›Ôl)&¤ž¥org/gradle/cli/CommandLineParser.classPK A‹å>É&¤ø·org/gradle/cli/ParsedCommandLine.classPK AyßtÚE,¤Àorg/gradle/cli/ParsedCommandLineOption.classPK A\vÆB| :¤)Ãorg/gradle/cli/ProjectPropertiesCommandLineConverter.classPK A Ï8=|ü9¤ýÄorg/gradle/cli/SystemPropertiesCommandLineConverter.classPK AýØ?¢¤ÐÆgradle-cli-classpath.propertiesPK A%¤"Çgradle-cli-parameter-names.propertiesPK33ÃgÇlibmongocrypt-1.8.4/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.properties000066400000000000000000000003101454530651600313060ustar00rootroot00000000000000distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists libmongocrypt-1.8.4/bindings/java/mongocrypt/gradlew000077500000000000000000000134351454530651600227250ustar00rootroot00000000000000#!/usr/bin/env sh # # Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi exec "$JAVACMD" "$@" libmongocrypt-1.8.4/bindings/java/mongocrypt/gradlew.bat000066400000000000000000000055761454530651600234760ustar00rootroot00000000000000@rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega libmongocrypt-1.8.4/bindings/java/mongocrypt/src/000077500000000000000000000000001454530651600221335ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/000077500000000000000000000000001454530651600230575ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/000077500000000000000000000000001454530651600240005ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/000077500000000000000000000000001454530651600245565ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/000077500000000000000000000000001454530651600262035ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/000077500000000000000000000000001454530651600273445ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/000077500000000000000000000000001454530651600302605ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/BinaryHolder.java000066400000000000000000000026041454530651600335070ustar00rootroot00000000000000/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_destroy; // Wrap JNA memory and a mongocrypt_binary_t that references that memory, in order to ensure that the JNA Memory is not GC'd before the // mongocrypt_binary_t is destroyed class BinaryHolder implements AutoCloseable { private final DisposableMemory memory; private final mongocrypt_binary_t binary; BinaryHolder(final DisposableMemory memory, final mongocrypt_binary_t binary) { this.memory = memory; this.binary = binary; } mongocrypt_binary_t getBinary() { return binary; } @Override public void close() { mongocrypt_binary_destroy(binary); memory.dispose(); } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPI.java000066400000000000000000001241441454530651600316450ustar00rootroot00000000000000/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.sun.jna.Callback; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.PointerType; import com.sun.jna.ptr.PointerByReference; //CHECKSTYLE:OFF /** * For internal use only. Not part of the public API. */ @SuppressWarnings("WeakerAccess") public class CAPI { public static class cstring extends PointerType { public cstring() { super(); } public cstring(String string) { Pointer m = new Memory(string.length() + 1); m.setString(0, string); setPointer(m); } public String toString() { return getPointer().getString(0); } } /** * Indicates success or contains error information. *

* Functions like @ref mongocrypt_ctx_encrypt_init follow a pattern to expose a * status. A boolean is returned. True indicates success, and false indicates * failure. On failure a status on the handle is set, and is accessible with a * corresponding status function. E.g. @ref mongocrypt_ctx_status. */ public static class mongocrypt_status_t extends PointerType { } /** * Contains all options passed on initialization of a @ref mongocrypt_ctx_t. */ public static class mongocrypt_opts_t extends PointerType { } /** * A non-owning view of a byte buffer. *

* Functions returning a mongocrypt_binary_t* expect it to be destroyed with * mongocrypt_binary_destroy. */ public static class mongocrypt_binary_t extends PointerType { } /** * The top-level handle to libmongocrypt. *

* Create a mongocrypt_t handle to perform operations within libmongocrypt: * encryption, decryption, registering log callbacks, etc. *

* Functions on a mongocrypt_t are thread safe, though functions on derived * handle (e.g. mongocrypt_encryptor_t) are not and must be owned by a single * thread. See each handle's documentation for thread-safety considerations. *

* Multiple mongocrypt_t handles may be created. */ public static class mongocrypt_t extends PointerType { } /** * Manages the state machine for encryption or decryption. */ public static class mongocrypt_ctx_t extends PointerType { } /** * Manages a single KMS HTTP request/response. */ public static class mongocrypt_kms_ctx_t extends PointerType { } /** * Returns the version string x.y.z for libmongocrypt. * * @param len an optional length of the returned string. May be NULL. * @return the version string x.y.z for libmongocrypt. */ public static native cstring mongocrypt_version(Pointer len); /** * Create a new non-owning view of a buffer (data + length). *

* Use this to create a mongocrypt_binary_t used for output parameters. * * @return A new mongocrypt_binary_t. */ public static native mongocrypt_binary_t mongocrypt_binary_new(); /** * Create a new non-owning view of a buffer (data + length). * * @param data A pointer to an array of bytes. This is not copied. data must outlive the binary object. * @param len The length of the @p data byte array. * @return A new mongocrypt_binary_t. */ public static native mongocrypt_binary_t mongocrypt_binary_new_from_data(Pointer data, int len); /** * Get a pointer to the referenced data. * * @param binary The @ref mongocrypt_binary_t. * @return A pointer to the referenced data. */ public static native Pointer mongocrypt_binary_data(mongocrypt_binary_t binary); /** * Get the length of the referenced data. * * @param binary The @ref mongocrypt_binary_t. * @return The length of the referenced data. */ public static native int mongocrypt_binary_len(mongocrypt_binary_t binary); /** * Free the @ref mongocrypt_binary_t. *

* This does not free the referenced data. Refer to individual function * documentation to determine the lifetime guarantees of the underlying * data. * * @param binary The mongocrypt_binary_t destroy. */ public static native void mongocrypt_binary_destroy(mongocrypt_binary_t binary); public static final int MONGOCRYPT_STATUS_OK = 0; public static final int MONGOCRYPT_STATUS_ERROR_CLIENT = 1; public static final int MONGOCRYPT_STATUS_ERROR_KMS = 2; /** * Create a new status object. *

* Use a new status object to retrieve the status from a handle by passing * this as an out-parameter to functions like @ref mongocrypt_ctx_status. * When done, destroy it with @ref mongocrypt_status_destroy. * * @return A new status object. */ public static native mongocrypt_status_t mongocrypt_status_new(); /** * Set a status object with message, type, and code. *

* Use this to set the mongocrypt_status_t given in the crypto hooks. * * @param status The status. * @param type The status type. * @param code The status code. * @param message The message. * @param message_len The length of @p message. Pass -1 to determine the * string length with strlen (must * be NULL terminated). */ public static native void mongocrypt_status_set(mongocrypt_status_t status, int type, int code, cstring message, int message_len); /** * Indicates success or the type of error. * * @param status The status object. * @return A @ref mongocrypt_status_type_t. */ public static native int mongocrypt_status_type(mongocrypt_status_t status); /** * Get an error code or 0. * * @param status The status object. * @return An error code. */ public static native int mongocrypt_status_code(mongocrypt_status_t status); /** * Get the error message associated with a status, or an empty string. * * @param status The status object. * @param len an optional length of the returned string. May be NULL. * @return An error message or an empty string. */ public static native cstring mongocrypt_status_message(mongocrypt_status_t status, Pointer len); /** * Returns true if the status indicates success. * * @param status The status to check. * @return A boolean indicating success. */ public static native boolean mongocrypt_status_ok(mongocrypt_status_t status); /** * Free the memory for a status object. * * @param status The status to destroy. */ public static native void mongocrypt_status_destroy(mongocrypt_status_t status); public static final int MONGOCRYPT_LOG_LEVEL_FATAL = 0; public static final int MONGOCRYPT_LOG_LEVEL_ERROR = 1; public static final int MONGOCRYPT_LOG_LEVEL_WARNING = 2; public static final int MONGOCRYPT_LOG_LEVEL_INFO = 3; public static final int MONGOCRYPT_LOG_LEVEL_TRACE = 4; /** * A log callback function. Set a custom log callback with mongocrypt_setopt_log_handler. */ public interface mongocrypt_log_fn_t extends Callback { void log(int level, cstring message, int message_len, Pointer ctx); } public interface mongocrypt_crypto_fn extends Callback { boolean crypt(Pointer ctx, mongocrypt_binary_t key, mongocrypt_binary_t iv, mongocrypt_binary_t in, mongocrypt_binary_t out, Pointer bytesWritten, mongocrypt_status_t status); } public interface mongocrypt_hmac_fn extends Callback { boolean hmac(Pointer ctx, mongocrypt_binary_t key, mongocrypt_binary_t in, mongocrypt_binary_t out, mongocrypt_status_t status); } public interface mongocrypt_hash_fn extends Callback { boolean hash(Pointer ctx, mongocrypt_binary_t in, mongocrypt_binary_t out, mongocrypt_status_t status); } public interface mongocrypt_random_fn extends Callback { boolean random(Pointer ctx, mongocrypt_binary_t out, int count, mongocrypt_status_t status); } /** * Allocate a new @ref mongocrypt_t object. *

* Initialize with @ref mongocrypt_init. When done, free with @ref * mongocrypt_destroy. * * @return A new @ref mongocrypt_t object. */ public static native mongocrypt_t mongocrypt_new(); /** * Set a handler to get called on every log message. * * @param crypt The @ref mongocrypt_t object. * @param log_fn The log callback. * @param log_ctx A context passed as an argument to the log callback every * invokation. * @return A boolean indicating success. */ public static native boolean mongocrypt_setopt_log_handler(mongocrypt_t crypt, mongocrypt_log_fn_t log_fn, Pointer log_ctx); public static native boolean mongocrypt_setopt_crypto_hooks(mongocrypt_t crypt, mongocrypt_crypto_fn aes_256_cbc_encrypt, mongocrypt_crypto_fn aes_256_cbc_decrypt, mongocrypt_random_fn random, mongocrypt_hmac_fn hmac_sha_512, mongocrypt_hmac_fn hmac_sha_256, mongocrypt_hash_fn sha_256, Pointer ctx); /** * Set a crypto hook for the AES256-CTR operations. * * @param crypt The @ref mongocrypt_t object. * @param aes_256_ctr_encrypt The crypto callback function for encrypt * operation. * @param aes_256_ctr_decrypt The crypto callback function for decrypt * operation. * @param ctx A context passed as an argument to the crypto callback * every invocation. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status * */ public static native boolean mongocrypt_setopt_aes_256_ctr (mongocrypt_t crypt, mongocrypt_crypto_fn aes_256_ctr_encrypt, mongocrypt_crypto_fn aes_256_ctr_decrypt, Pointer ctx); /** * Set a crypto hook for the RSASSA-PKCS1-v1_5 algorithm with a SHA-256 hash. * *

See: https://tools.ietf.org/html/rfc3447#section-8.2

* *

Note: this function has the wrong name. It should be: * mongocrypt_setopt_crypto_hook_sign_rsassa_pkcs1_v1_5

* * @param crypt The @ref mongocrypt_t object. * @param sign_rsaes_pkcs1_v1_5 The crypto callback function. * @param sign_ctx A context passed as an argument to the crypto callback * every invocation. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status */ public static native boolean mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( mongocrypt_t crypt, mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5, Pointer sign_ctx); /** * Set a handler to get called on every log message. * * @param crypt The @ref mongocrypt_t object. * @param aws_access_key_id The AWS access key ID used to generate KMS * messages. * @param aws_access_key_id_len The string length (in bytes) of @p * * aws_access_key_id. Pass -1 to determine the string length with strlen (must * * be NULL terminated). * @param aws_secret_access_key The AWS secret access key used to generate * KMS messages. * @param aws_secret_access_key_len The string length (in bytes) of @p * aws_secret_access_key. Pass -1 to determine the string length with strlen * (must be NULL terminated). * @return A boolean indicating success. */ public static native boolean mongocrypt_setopt_kms_provider_aws(mongocrypt_t crypt, cstring aws_access_key_id, int aws_access_key_id_len, cstring aws_secret_access_key, int aws_secret_access_key_len); /** * Configure a local KMS provider on the @ref mongocrypt_t object. * * @param crypt The @ref mongocrypt_t object. * @param key A 64 byte master key used to encrypt and decrypt key vault keys. * @return A boolean indicating success. */ public static native boolean mongocrypt_setopt_kms_provider_local(mongocrypt_t crypt, mongocrypt_binary_t key); /** * Configure KMS providers with a BSON document. * * @param crypt The @ref mongocrypt_t object. * @param kms_providers A BSON document mapping the KMS provider names to credentials. * @return A boolean indicating success. If false, an error status is set. * @since 1.1 */ public static native boolean mongocrypt_setopt_kms_providers(mongocrypt_t crypt, mongocrypt_binary_t kms_providers); /** * Set a local schema map for encryption. * * @param crypt The @ref mongocrypt_t object. * @param schema_map A BSON document representing the schema map supplied by * the user. The keys are collection namespaces and values are JSON schemas. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status */ public static native boolean mongocrypt_setopt_schema_map (mongocrypt_t crypt, mongocrypt_binary_t schema_map); /** * Opt-into setting KMS providers before each KMS request. * * If set, before entering the MONGOCRYPT_CTX_NEED_KMS state, * contexts will enter the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state * and then wait for credentials to be supplied through @ref mongocrypt_ctx_provide_kms_providers. * * @param crypt The @ref mongocrypt_t object to update */ public static native void mongocrypt_setopt_use_need_kms_credentials_state (mongocrypt_t crypt); /** * Set a local EncryptedFieldConfigMap for encryption. * * @param crypt The @ref mongocrypt_t object. * @param encryptedFieldConfigMap A BSON document representing the EncryptedFieldConfigMap * supplied by the user. The keys are collection namespaces and values are * EncryptedFieldConfigMap documents. The viewed data copied. It is valid to * destroy @p efc_map with @ref mongocrypt_binary_destroy immediately after. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status */ public static native boolean mongocrypt_setopt_encrypted_field_config_map (mongocrypt_t crypt, mongocrypt_binary_t encryptedFieldConfigMap); /** * Opt-into skipping query analysis. * *

If opted in: *

    *
  • The crypt_shared shared library will not attempt to be loaded.
  • *
  • A mongocrypt_ctx_t will never enter the MONGOCRYPT_CTX_NEED_MARKINGS state.
  • *
* * @param crypt The @ref mongocrypt_t object to update * @since 1.5 */ public static native void mongocrypt_setopt_bypass_query_analysis (mongocrypt_t crypt); /** * Set the contention factor used for explicit encryption. * The contention factor is only used for indexed Queryable Encryption. * * @param ctx The @ref mongocrypt_ctx_t object. * @param contention_factor the contention factor * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status. * @since 1.5 */ public static native boolean mongocrypt_ctx_setopt_contention_factor (mongocrypt_ctx_t ctx, long contention_factor); /** * Set the index key id to use for Queryable Encryption explicit encryption. * * If the index key id not set, the key id from @ref mongocrypt_ctx_setopt_key_id is used. * * @param ctx The @ref mongocrypt_ctx_t object. * @param key_id The binary corresponding to the _id (a UUID) of the data key to use from * the key vault collection. Note, the UUID must be encoded with RFC-4122 byte order. * The viewed data is copied. It is valid to destroy key_id with @ref mongocrypt_binary_destroy immediately after. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status * @since 1.5 */ public static native boolean mongocrypt_ctx_setopt_index_key_id (mongocrypt_ctx_t ctx, mongocrypt_binary_t key_id); /** * Append an additional search directory to the search path for loading * the crypt_shared dynamic library. * * @param crypt The @ref mongocrypt_t object to update * @param path A null-terminated sequence of bytes for the search path. On * some filesystems, this may be arbitrary bytes. On other filesystems, this may * be required to be a valid UTF-8 code unit sequence. If the leading element of * the path is the literal string "$ORIGIN", that substring will be replaced * with the directory path containing the executable libmongocrypt module. If * the path string is literal "$SYSTEM", then libmongocrypt will defer to the * system's library resolution mechanism to find the crypt_shared library. * *

If no crypt_shared dynamic library is found in any of the directories * specified by the search paths loaded here, @ref mongocrypt_init() will still * succeed and continue to operate without crypt_shared.

* *

The search paths are searched in the order that they are appended. This * allows one to provide a precedence in how the library will be discovered. For * example, appending known directories before appending "$SYSTEM" will allow * one to supersede the system's installed library, but still fall-back to it if * the library wasn't found otherwise. If one does not ever append "$SYSTEM", * then the system's library-search mechanism will never be consulted.

* *

If an absolute path to the library is specified using @ref mongocrypt_setopt_set_crypt_shared_lib_path_override, * then paths appended here will have no effect.

* @since 1.5 */ public static native void mongocrypt_setopt_append_crypt_shared_lib_search_path (mongocrypt_t crypt, cstring path); /** * Set a single override path for loading the crypt_shared dynamic library. * @param crypt The @ref mongocrypt_t object to update * @param path A null-terminated sequence of bytes for a path to the crypt_shared * dynamic library. On some filesystems, this may be arbitrary bytes. On other * filesystems, this may be required to be a valid UTF-8 code unit sequence. If * the leading element of the path is the literal string `$ORIGIN`, that * substring will be replaced with the directory path containing the executable * libmongocrypt module. * *

This function will do no IO nor path validation. All validation will * occur during the call to @ref mongocrypt_init.

*

If a crypt_shared library path override is specified here, then no paths given * to @ref mongocrypt_setopt_append_crypt_shared_lib_search_path will be consulted when * opening the crypt_shared library.

*

If a path is provided via this API and @ref mongocrypt_init fails to * initialize a valid crypt_shared library instance for the path specified, then * the initialization of mongocrypt_t will fail with an error.

* @since 1.5 */ public static native void mongocrypt_setopt_set_crypt_shared_lib_path_override(mongocrypt_t crypt, cstring path); /** * Set the query type to use for Queryable Encryption explicit encryption. * The query type is only used for indexed Queryable Encryption. * * @param ctx The @ref mongocrypt_ctx_t object. * @param query_type the query type * @param len the length * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ public static native boolean mongocrypt_ctx_setopt_query_type (mongocrypt_ctx_t ctx, cstring query_type, int len); /** * Set options for explicit encryption with the "rangePreview" algorithm. * NOTE: The RangePreview algorithm is experimental only. It is not intended for * public use. * * opts is a BSON document of the form: * { * "min": Optional<BSON value>, * "max": Optional<BSON value>, * "sparsity": Int64, * "precision": Optional<Int32> * } * * @param ctx The @ref mongocrypt_ctx_t object. * @param opts BSON. * @return A boolean indicating success. If false, an error status is set. * @since 1.7 */ public static native boolean mongocrypt_ctx_setopt_algorithm_range (mongocrypt_ctx_t ctx, mongocrypt_binary_t opts); /** * Initialize new @ref mongocrypt_t object. * * @param crypt The @ref mongocrypt_t object. * @return A boolean indicating success. Failure may occur if previously set options are invalid. */ public static native boolean mongocrypt_init(mongocrypt_t crypt); /** * Get the status associated with a @ref mongocrypt_t object. * * @param crypt The @ref mongocrypt_t object. * @param status Receives the status. * @return A boolean indicating success. */ public static native boolean mongocrypt_status(mongocrypt_t crypt, mongocrypt_status_t status); /** * Destroy the @ref mongocrypt_t object. * * @param crypt The @ref mongocrypt_t object to destroy. */ public static native void mongocrypt_destroy(mongocrypt_t crypt); /** * Obtain a nul-terminated version string of the loaded crypt_shared dynamic library, * if available. * * If no crypt_shared was successfully loaded, this function returns NULL. * * @param crypt The mongocrypt_t object after a successful call to mongocrypt_init. * @param len an optional length of the returned string. May be NULL. * * @return A nul-terminated string of the dynamically loaded crypt_shared library. * @since 1.5 */ public static native cstring mongocrypt_crypt_shared_lib_version_string (mongocrypt_t crypt, Pointer len); /** * Call in response to the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state * to set per-context KMS provider settings. These follow the same format * as @ref mongocrypt_setopt_kms_providers. If no keys are present in the * BSON input, the KMS provider settings configured for the @ref mongocrypt_t * at initialization are used. * * @param ctx The @ref mongocrypt_ctx_t object. * @param kms_providers A BSON document mapping the KMS provider names * to credentials. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status. */ public static native boolean mongocrypt_ctx_provide_kms_providers (mongocrypt_ctx_t ctx, mongocrypt_binary_t kms_providers); /** * Set the key id to use for explicit encryption. * * @param ctx The @ref mongocrypt_ctx_t object. * @param key_id The key_id to use. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t ctx, mongocrypt_binary_t key_id); /** * Set the keyAltName to use for explicit encryption. * keyAltName should be a binary encoding a bson document * with the following format: { "keyAltName" : >BSON UTF8 value< } * *

It is an error to set both this and the key id.

* * @param ctx The @ref mongocrypt_ctx_t object. * @param key_alt_name The name to use. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ public static native boolean mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t ctx, mongocrypt_binary_t key_alt_name); /** * Set the keyMaterial to use for encrypting data. * *

* Pass the binary encoding of a BSON document like the following: * { "keyMaterial" : (BSON BINARY value) } *

* * @param ctx The @ref mongocrypt_ctx_t object. * @param key_material The data encryption key to use. The viewed data is * copied. It is valid to destroy @p key_material with @ref * mongocrypt_binary_destroy immediately after. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ public static native boolean mongocrypt_ctx_setopt_key_material (mongocrypt_ctx_t ctx, mongocrypt_binary_t key_material); /** * Set the algorithm used for encryption to either * deterministic or random encryption. This value * should only be set when using explicit encryption. * * If -1 is passed in for "len", then "algorithm" is * assumed to be a null-terminated string. * * Valid values for algorithm are: * "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" * "AEAD_AES_256_CBC_HMAC_SHA_512-Randomized" * * @param ctx The @ref mongocrypt_ctx_t object. * @param algorithm A string specifying the algorithm to * use for encryption. * @param len The length of the algorithm string. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t ctx, cstring algorithm, int len); /** * Create a new uninitialized @ref mongocrypt_ctx_t. *

* Initialize the context with functions like @ref mongocrypt_ctx_encrypt_init. * When done, destroy it with @ref mongocrypt_ctx_destroy. * * @param crypt The @ref mongocrypt_t object. * @return A new context. */ public static native mongocrypt_ctx_t mongocrypt_ctx_new(mongocrypt_t crypt); /** * Get the status associated with a @ref mongocrypt_ctx_t object. * * @param ctx The @ref mongocrypt_ctx_t object. * @param status Receives the status. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_status(mongocrypt_ctx_t ctx, mongocrypt_status_t status); /** * Identify the AWS KMS master key to use for creating a data key. * * @param ctx The @ref mongocrypt_ctx_t object. * @param region The AWS region. * @param region_len The string length of @p region. Pass -1 to determine * the string length with strlen (must be NULL terminated). * @param cmk The Amazon Resource Name (ARN) of the customer master key * (CMK). * @param cmk_len The string length of @p cmk_len. Pass -1 to determine the * string length with strlen (must be NULL terminated). * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t ctx, cstring region, int region_len, cstring cmk, int cmk_len); /** * Identify a custom AWS endpoint when creating a data key. * This is used internally to construct the correct HTTP request * (with the Host header set to this endpoint). This endpoint * is persisted in the new data key, and will be returned via * mongocrypt_kms_ctx_endpoint. * * @param ctx The @ref mongocrypt_ctx_t object. * @param endpoint The endpoint. * @param endpoint_len The string length of @p endpoint. Pass -1 to * determine the string length with strlen (must be NULL terminated). * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ public static native boolean mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t ctx, cstring endpoint, int endpoint_len); /** * Set the master key to "local" for creating a data key. * * @param ctx The @ref mongocrypt_ctx_t object. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t ctx); /** * Set key encryption key document for creating a data key. * * @param ctx The @ref mongocrypt_ctx_t object. * @param keyDocument BSON representing the key encryption key document. * @return A boolean indicating success. If false, and error status is set. * @since 1.1 */ public static native boolean mongocrypt_ctx_setopt_key_encryption_key(mongocrypt_ctx_t ctx, mongocrypt_binary_t keyDocument); /** * Initialize a context to create a data key. * * Set options before using @ref mongocrypt_ctx_setopt_masterkey_aws and * mongocrypt_ctx_setopt_masterkey_local. * * @param ctx The @ref mongocrypt_ctx_t object. * @return A boolean indicating success. * * Assumes a master key option has been set, and an associated KMS provider * has been set on the parent @ref mongocrypt_t. */ public static native boolean mongocrypt_ctx_datakey_init (mongocrypt_ctx_t ctx); /** * Initialize a context for encryption. * * Associated options: * - @ref mongocrypt_ctx_setopt_cache_noblock * - @ref mongocrypt_ctx_setopt_schema * * @param ctx The @ref mongocrypt_ctx_t object. * @param db The database name. * @param db_len The byte length of @p db. Pass -1 to determine the string length with strlen (must be NULL terminated). * @param cmd The BSON command to be encrypted. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ public static native boolean mongocrypt_ctx_encrypt_init(mongocrypt_ctx_t ctx, cstring db, int db_len, mongocrypt_binary_t cmd); /** * Explicit helper method to encrypt a single BSON object. Contexts * created for explicit encryption will not go through mongocryptd. * * To specify a key_id, algorithm, or iv to use, please use the * corresponding mongocrypt_setopt methods before calling this. * * This method expects the passed-in BSON to be of the form: * { "v" : BSON value to encrypt } * * @param ctx A @ref mongocrypt_ctx_t. * @param msg A @ref mongocrypt_binary_t the plaintext BSON value. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_explicit_encrypt_init (mongocrypt_ctx_t ctx, mongocrypt_binary_t msg); /** * Explicit helper method to encrypt a Match Expression or Aggregate Expression. * Contexts created for explicit encryption will not go through mongocryptd. * Requires query_type to be "rangePreview". * NOTE: The RangePreview algorithm is experimental only. It is not intended for * public use. * * This method expects the passed-in BSON to be of the form: * { "v" : FLE2RangeFindDriverSpec } * * FLE2RangeFindDriverSpec is a BSON document with one of these forms: * * 1. A Match Expression of this form: * {$and: [{<field>: {<op>: <value1>, {<field>: {<op>: <value2> }}]} * 2. An Aggregate Expression of this form: * {$and: [{<op>: [<fieldpath>, <value1>]}, {<op>: [<fieldpath>, <value2>]}] * * may be $lt, $lte, $gt, or $gte. * * The value of "v" is expected to be the BSON value passed to a driver * ClientEncryption.encryptExpression helper. * * Associated options for FLE 1: * - @ref mongocrypt_ctx_setopt_key_id * - @ref mongocrypt_ctx_setopt_key_alt_name * - @ref mongocrypt_ctx_setopt_algorithm * * Associated options for Queryable Encryption: * - @ref mongocrypt_ctx_setopt_key_id * - @ref mongocrypt_ctx_setopt_index_key_id * - @ref mongocrypt_ctx_setopt_contention_factor * - @ref mongocrypt_ctx_setopt_query_type * - @ref mongocrypt_ctx_setopt_algorithm_range * * An error is returned if FLE 1 and Queryable Encryption incompatible options * are set. * * @param ctx A @ref mongocrypt_ctx_t. * @param msg A @ref mongocrypt_binary_t the plaintext BSON value. * @return A boolean indicating success. * @since 1.7 */ public static native boolean mongocrypt_ctx_explicit_encrypt_expression_init (mongocrypt_ctx_t ctx, mongocrypt_binary_t msg); /** * Initialize a context for decryption. * * @param ctx The mongocrypt_ctx_t object. * @param doc The document to be decrypted. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_decrypt_init(mongocrypt_ctx_t ctx, mongocrypt_binary_t doc); /** * Explicit helper method to decrypt a single BSON object. * * @param ctx A @ref mongocrypt_ctx_t. * @param msg A @ref mongocrypt_binary_t the encrypted BSON. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_explicit_decrypt_init (mongocrypt_ctx_t ctx, mongocrypt_binary_t msg); /** * Initialize a context to rewrap datakeys. * * Associated options {@link #mongocrypt_ctx_setopt_key_encryption_key(mongocrypt_ctx_t, mongocrypt_binary_t)} * * @param ctx The @ref mongocrypt_ctx_t object. * @param filter The filter to use for the find command on the key vault collection to retrieve datakeys to rewrap. * @return A boolean indicating success. If false, and error status is set. * @since 1.5 */ public static native boolean mongocrypt_ctx_rewrap_many_datakey_init (mongocrypt_ctx_t ctx, mongocrypt_binary_t filter); public static final int MONGOCRYPT_CTX_ERROR = 0; public static final int MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1; /* run on main MongoClient */ public static final int MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2; /* run on mongocryptd. */ public static final int MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3; /* run on key vault */ public static final int MONGOCRYPT_CTX_NEED_KMS = 4; public static final int MONGOCRYPT_CTX_READY = 5; /* ready for encryption/decryption */ public static final int MONGOCRYPT_CTX_DONE = 6; public static final int MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7; /* fetch/renew KMS credentials */ public static final int MONGOCRYPT_INDEX_TYPE_NONE = 1; public static final int MONGOCRYPT_INDEX_TYPE_EQUALITY = 2; public static final int MONGOCRYPT_QUERY_TYPE_EQUALITY = 1; /** * Get the current state of a context. * * @param ctx The @ref mongocrypt_ctx_t object. * @return A @ref mongocrypt_ctx_state_t. */ public static native int mongocrypt_ctx_state(mongocrypt_ctx_t ctx); /** * Get BSON necessary to run the mongo operation when mongocrypt_ctx_t * is in MONGOCRYPT_CTX_NEED_MONGO_* states. * *

* op_bson is a BSON document to be used for the operation. * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter. * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter. * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a JSON schema to append. *

* * @param ctx The @ref mongocrypt_ctx_t object. * @param op_bson A BSON document for the MongoDB operation. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_mongo_op(mongocrypt_ctx_t ctx, mongocrypt_binary_t op_bson); /** * Feed a BSON reply or result when when mongocrypt_ctx_t is in * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times * depending on the operation. *

* op_bson is a BSON document to be used for the operation. * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections * cursor. * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor. * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a reply from mongocryptd. * * @param ctx The @ref mongocrypt_ctx_t object. * @param reply A BSON document for the MongoDB operation. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_mongo_feed(mongocrypt_ctx_t ctx, mongocrypt_binary_t reply); /** * Call when done feeding the reply (or replies) back to the context. * * @param ctx The @ref mongocrypt_ctx_t object. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_mongo_done(mongocrypt_ctx_t ctx); /** * Get the next KMS handle. *

* Multiple KMS handles may be retrieved at once. Drivers may do this to fan * out multiple concurrent KMS HTTP requests. Feeding multiple KMS requests * is thread-safe. *

* Is KMS handles are being handled synchronously, the driver can reuse the same * TLS socket to send HTTP requests and receive responses. * * @param ctx A @ref mongocrypt_ctx_t. * @return a new @ref mongocrypt_kms_ctx_t or NULL. */ public static native mongocrypt_kms_ctx_t mongocrypt_ctx_next_kms_ctx(mongocrypt_ctx_t ctx); /** * Get the KMS provider identifier associated with this KMS request. * * This is used to conditionally configure TLS connections based on the KMS * request. It is useful for KMIP, which authenticates with a client * certificate. * * @param kms The mongocrypt_kms_ctx_t object. * @param len Receives the length of the returned string. * * @return The name of the KMS provider */ public static native cstring mongocrypt_kms_ctx_get_kms_provider(mongocrypt_kms_ctx_t kms, Pointer len); /** * Get the HTTP request message for a KMS handle. * * @param kms A @ref mongocrypt_kms_ctx_t. * @param msg The HTTP request to send to KMS. * @return A boolean indicating success. */ public static native boolean mongocrypt_kms_ctx_message(mongocrypt_kms_ctx_t kms, mongocrypt_binary_t msg); /** * Get the hostname from which to connect over TLS. *

* The storage for @p endpoint is not owned by the caller, but * is valid until calling @ref mongocrypt_ctx_kms_done on the * parent @ref mongocrypt_ctx_t. * * @param kms A @ref mongocrypt_kms_ctx_t. * @param endpoint The output hostname. * @return A boolean indicating success. */ public static native boolean mongocrypt_kms_ctx_endpoint(mongocrypt_kms_ctx_t kms, PointerByReference endpoint); /** * Indicates how many bytes to feed into @ref mongocrypt_kms_ctx_feed. * * @param kms The @ref mongocrypt_kms_ctx_t. * @return The number of requested bytes. */ public static native int mongocrypt_kms_ctx_bytes_needed(mongocrypt_kms_ctx_t kms); /** * Feed bytes from the HTTP response. *

* Feeding more bytes than what has been returned in @ref * mongocrypt_kms_ctx_bytes_needed is an error. * * @param kms The @ref mongocrypt_kms_ctx_t. * @param bytes The bytes to feed. * @return A boolean indicating success. */ public static native boolean mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t kms, mongocrypt_binary_t bytes); /** * Get the status associated with a @ref mongocrypt_kms_ctx_t object. * * @param kms The @ref mongocrypt_kms_ctx_t object. * @param status Receives the status. * @return A boolean indicating success. */ public static native boolean mongocrypt_kms_ctx_status(mongocrypt_kms_ctx_t kms, mongocrypt_status_t status); /** * Call when done handling all KMS contexts. * * @param ctx The @ref mongocrypt_ctx_t object. * @return A boolean indicating success. */ public static native boolean mongocrypt_ctx_kms_done(mongocrypt_ctx_t ctx); /** * Perform the final encryption or decryption. * * @param ctx A @ref mongocrypt_ctx_t. * @param out The final BSON to send to the server. * @return a boolean indicating success. */ public static native boolean mongocrypt_ctx_finalize(mongocrypt_ctx_t ctx, mongocrypt_binary_t out); /** * Destroy and free all memory associated with a @ref mongocrypt_ctx_t. * * @param ctx A @ref mongocrypt_ctx_t. */ public static native void mongocrypt_ctx_destroy(mongocrypt_ctx_t ctx); static final String NATIVE_LIBRARY_NAME = "mongocrypt"; static { Native.register(CAPI.class, NATIVE_LIBRARY_NAME); } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPIHelper.java000066400000000000000000000072651454530651600330110ustar00rootroot00000000000000/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.sun.jna.Pointer; import org.bson.BsonBinaryWriter; import org.bson.BsonDocument; import org.bson.RawBsonDocument; import org.bson.codecs.BsonValueCodecProvider; import org.bson.codecs.Codec; import org.bson.codecs.EncoderContext; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.bson.io.BasicOutputBuffer; import java.nio.ByteBuffer; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_data; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_len; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_new_from_data; import static java.lang.String.format; final class CAPIHelper { private static final CodecRegistry CODEC_REGISTRY = CodecRegistries.fromProviders(new BsonValueCodecProvider()); @SuppressWarnings("unchecked") static BinaryHolder toBinary(final BsonDocument document) { BasicOutputBuffer buffer = new BasicOutputBuffer(); BsonBinaryWriter writer = new BsonBinaryWriter(buffer); ((Codec) CODEC_REGISTRY.get(document.getClass())).encode(writer, document, EncoderContext.builder().build()); DisposableMemory memory = new DisposableMemory(buffer.size()); memory.write(0, buffer.getInternalBuffer(), 0, buffer.size()); return new BinaryHolder(memory, mongocrypt_binary_new_from_data(memory, buffer.getSize())); } static RawBsonDocument toDocument(final mongocrypt_binary_t binary) { ByteBuffer byteBuffer = toByteBuffer(binary); byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); return new RawBsonDocument(bytes); } static BinaryHolder toBinary(final ByteBuffer buffer) { byte[] message = new byte[buffer.remaining()]; buffer.get(message, 0, buffer.remaining()); DisposableMemory memory = new DisposableMemory(message.length); memory.write(0, message, 0, message.length); return new BinaryHolder(memory, mongocrypt_binary_new_from_data(memory, message.length)); } static ByteBuffer toByteBuffer(final mongocrypt_binary_t binary) { Pointer pointer = mongocrypt_binary_data(binary); int length = mongocrypt_binary_len(binary); return pointer.getByteBuffer(0, length); } static byte[] toByteArray(final mongocrypt_binary_t binary) { ByteBuffer byteBuffer = toByteBuffer(binary); byte[] byteArray = new byte[byteBuffer.remaining()]; byteBuffer.get(byteArray); return byteArray; } static void writeByteArrayToBinary(final mongocrypt_binary_t binary, byte[] bytes) { if (mongocrypt_binary_len(binary) < bytes.length) { throw new IllegalArgumentException(format("mongocrypt binary of length %d is not large enough to hold %d bytes", mongocrypt_binary_len(binary), bytes.length)); } Pointer outPointer = mongocrypt_binary_data(binary); outPointer.write(0, bytes, 0, bytes.length); } private CAPIHelper() { } } CipherCallback.java000066400000000000000000000050661454530651600337020ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.cstring; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_crypto_fn; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import com.sun.jna.Pointer; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_STATUS_ERROR_CLIENT; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_set; import static com.mongodb.crypt.capi.CAPIHelper.toByteArray; import static com.mongodb.crypt.capi.CAPIHelper.writeByteArrayToBinary; class CipherCallback implements mongocrypt_crypto_fn { private final String algorithm; private final String transformation; private final int mode; CipherCallback(final String algorithm, final String transformation, final int mode) { this.algorithm = algorithm; this.transformation = transformation; this.mode = mode; } @Override public boolean crypt(final Pointer ctx, final mongocrypt_binary_t key, final mongocrypt_binary_t iv, final mongocrypt_binary_t in, final mongocrypt_binary_t out, final Pointer bytesWritten, final mongocrypt_status_t status) { try { IvParameterSpec ivParameterSpec = new IvParameterSpec(toByteArray(iv)); SecretKeySpec secretKeySpec = new SecretKeySpec(toByteArray(key), algorithm); Cipher cipher = Cipher.getInstance(transformation); cipher.init(mode, secretKeySpec, ivParameterSpec); byte[] result = cipher.doFinal(toByteArray(in)); writeByteArrayToBinary(out, result); bytesWritten.setInt(0, result.length); return true; } catch (Exception e) { mongocrypt_status_set(status, MONGOCRYPT_STATUS_ERROR_CLIENT, 0, new cstring(e.toString()), -1); return false; } } } DisposableMemory.java000066400000000000000000000016271454530651600343300ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.sun.jna.Memory; // Subclass of JNA's Memory class so that we can call its protected dispose method class DisposableMemory extends Memory { DisposableMemory(final int size) { super(size); } public void dispose() { super.dispose(); } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/JULLogger.java000066400000000000000000000056561454530651600327310ustar00rootroot00000000000000 /* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import java.util.logging.Level; import static java.util.logging.Level.FINE; import static java.util.logging.Level.FINER; import static java.util.logging.Level.INFO; import static java.util.logging.Level.SEVERE; import static java.util.logging.Level.WARNING; class JULLogger implements Logger { private final java.util.logging.Logger delegate; JULLogger(final String name) { this.delegate = java.util.logging.Logger.getLogger(name); } @Override public String getName() { return delegate.getName(); } @Override public boolean isTraceEnabled() { return isEnabled(FINER); } @Override public void trace(final String msg) { log(FINER, msg); } @Override public void trace(final String msg, final Throwable t) { log(FINER, msg, t); } @Override public boolean isDebugEnabled() { return isEnabled(FINE); } @Override public void debug(final String msg) { log(FINE, msg); } @Override public void debug(final String msg, final Throwable t) { log(FINE, msg, t); } @Override public boolean isInfoEnabled() { return delegate.isLoggable(INFO); } @Override public void info(final String msg) { log(INFO, msg); } @Override public void info(final String msg, final Throwable t) { log(INFO, msg, t); } @Override public boolean isWarnEnabled() { return delegate.isLoggable(WARNING); } @Override public void warn(final String msg) { log(WARNING, msg); } @Override public void warn(final String msg, final Throwable t) { log(WARNING, msg, t); } @Override public boolean isErrorEnabled() { return delegate.isLoggable(SEVERE); } @Override public void error(final String msg) { log(SEVERE, msg); } @Override public void error(final String msg, final Throwable t) { log(SEVERE, msg, t); } private boolean isEnabled(final Level level) { return delegate.isLoggable(level); } private void log(final Level level, final String msg) { delegate.log(level, msg); } public void log(final Level level, final String msg, final Throwable t) { delegate.log(level, msg, t); } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/Logger.java000066400000000000000000000073741454530651600323550ustar00rootroot00000000000000 /* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; /** * Not part of the public API */ public interface Logger { /** * Return the name of this Logger instance. * * @return name of this logger instance */ String getName(); /** * Is the logger instance enabled for the TRACE level? * * @return True if this Logger is enabled for the TRACE level, false otherwise. */ boolean isTraceEnabled(); /** * Log a message at the TRACE level. * * @param msg the message string to be logged */ void trace(String msg); /** * Log an exception (throwable) at the TRACE level with an accompanying message. * * @param msg the message accompanying the exception * @param t the exception (throwable) to log */ void trace(String msg, Throwable t); /** * Is the logger instance enabled for the DEBUG level? * * @return True if this Logger is enabled for the DEBUG level, false otherwise. */ boolean isDebugEnabled(); /** * Log a message at the DEBUG level. * * @param msg the message string to be logged */ void debug(String msg); /** * Log an exception (throwable) at the DEBUG level with an accompanying message. * * @param msg the message accompanying the exception * @param t the exception (throwable) to log */ void debug(String msg, Throwable t); /** * Is the logger instance enabled for the INFO level? * * @return True if this Logger is enabled for the INFO level, false otherwise. */ boolean isInfoEnabled(); /** * Log a message at the INFO level. * * @param msg the message string to be logged */ void info(String msg); /** * Log an exception (throwable) at the INFO level with an accompanying message. * * @param msg the message accompanying the exception * @param t the exception (throwable) to log */ void info(String msg, Throwable t); /** * Is the logger instance enabled for the WARN level? * * @return True if this Logger is enabled for the WARN level, false otherwise. */ boolean isWarnEnabled(); /** * Log a message at the WARN level. * * @param msg the message string to be logged */ void warn(String msg); /** * Log an exception (throwable) at the WARN level with an accompanying message. * * @param msg the message accompanying the exception * @param t the exception (throwable) to log */ void warn(String msg, Throwable t); /** * Is the logger instance enabled for the ERROR level? * * @return True if this Logger is enabled for the ERROR level, false otherwise. */ boolean isErrorEnabled(); /** * Log a message at the ERROR level. * * @param msg the message string to be logged */ void error(String msg); /** * Log an exception (throwable) at the ERROR level with an accompanying message. * * @param msg the message accompanying the exception * @param t the exception (throwable) to log */ void error(String msg, Throwable t); } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/Loggers.java000066400000000000000000000024601454530651600325270ustar00rootroot00000000000000/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; /** * This class is not part of the public API. */ public final class Loggers { private static final String NAME = "org.mongodb.driver.crypt"; private static final boolean USE_SLF4J = shouldUseSLF4J(); /** * @return the logger */ public static Logger getLogger() { if (USE_SLF4J) { return new SLF4JLogger(NAME); } else { return new JULLogger(NAME); } } private Loggers() { } private static boolean shouldUseSLF4J() { try { Class.forName("org.slf4j.Logger"); return true; } catch (ClassNotFoundException e) { return false; } } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MacCallback.java000066400000000000000000000041151454530651600332410ustar00rootroot00000000000000/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.cstring; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_hmac_fn; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import com.sun.jna.Pointer; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_STATUS_ERROR_CLIENT; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_set; import static com.mongodb.crypt.capi.CAPIHelper.toByteArray; import static com.mongodb.crypt.capi.CAPIHelper.writeByteArrayToBinary; class MacCallback implements mongocrypt_hmac_fn { private final String algorithm; MacCallback(final String algorithm) { this.algorithm = algorithm; } @Override public boolean hmac(final Pointer ctx, final mongocrypt_binary_t key, final mongocrypt_binary_t in, final mongocrypt_binary_t out, final mongocrypt_status_t status) { try { Mac mac = Mac.getInstance(algorithm); SecretKeySpec keySpec = new SecretKeySpec(toByteArray(key), algorithm); mac.init(keySpec); mac.update(toByteArray(in)); byte[] result = mac.doFinal(); writeByteArrayToBinary(out, result); return true; } catch (Exception e) { mongocrypt_status_set(status, MONGOCRYPT_STATUS_ERROR_CLIENT, 0, new cstring(e.toString()), -1); return false; } } } MessageDigestCallback.java000066400000000000000000000037411454530651600352120ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.cstring; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_hash_fn; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import com.sun.jna.Pointer; import java.security.MessageDigest; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_STATUS_ERROR_CLIENT; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_set; import static com.mongodb.crypt.capi.CAPIHelper.toByteArray; import static com.mongodb.crypt.capi.CAPIHelper.writeByteArrayToBinary; class MessageDigestCallback implements mongocrypt_hash_fn { private final String algorithm; MessageDigestCallback(final String algorithm) { this.algorithm = algorithm; } @Override public boolean hash(final Pointer ctx, final mongocrypt_binary_t in, final mongocrypt_binary_t out, final mongocrypt_status_t status) { try { MessageDigest messageDigest = MessageDigest.getInstance(algorithm); messageDigest.update(toByteArray(in)); byte[] digest = messageDigest.digest(); writeByteArrayToBinary(out, digest); return true; } catch (Exception e) { mongocrypt_status_set(status, MONGOCRYPT_STATUS_ERROR_CLIENT, 0, new cstring(e.toString()), -1); return false; } } } MongoAwsKmsProviderOptions.java000066400000000000000000000052261454530651600363450ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import static org.bson.assertions.Assertions.notNull; /** * The options for configuring the AWS KMS provider. */ public class MongoAwsKmsProviderOptions { private final String accessKeyId; private final String secretAccessKey; /** * Construct a builder for the options * * @return the builder */ public static Builder builder() { return new Builder(); } /** * Gets the access key id * * @return the access key id, which may not be null */ public String getAccessKeyId() { return accessKeyId; } /** * Gets the secret access key * * @return the secret access key, which may not be null */ public String getSecretAccessKey() { return secretAccessKey; } /** * The builder for the options */ public static class Builder { private String accessKeyId; private String secretAccessKey; private Builder() { } /** * Sets the access key id. * * @param accessKeyId the access key id * @return this */ public Builder accessKeyId(final String accessKeyId) { this.accessKeyId = accessKeyId; return this; } /** * Sets the secret access key. * * @param secretAccessKey the secret access key * @return this */ public Builder secretAccessKey(final String secretAccessKey) { this.secretAccessKey = secretAccessKey; return this; } /** * Build the options. * * @return the options */ public MongoAwsKmsProviderOptions build() { return new MongoAwsKmsProviderOptions(this); } } private MongoAwsKmsProviderOptions(final Builder builder) { this.accessKeyId = notNull("AWS KMS provider accessKeyId", builder.accessKeyId); this.secretAccessKey = notNull("AWS KMS provider secretAccessKey", builder.secretAccessKey); } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoCrypt.java000066400000000000000000000063201454530651600332250ustar00rootroot00000000000000/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import org.bson.BsonDocument; import java.io.Closeable; /** * A context for encryption/decryption operations. */ public interface MongoCrypt extends Closeable { /** * Create a context to use for encryption * * @param database the namespace * @param command the document representing the command to encrypt * @return the context */ MongoCryptContext createEncryptionContext(String database, final BsonDocument command); /** * Create a context to use for decryption * * @param document the document to decrypt * @return the context */ MongoCryptContext createDecryptionContext(BsonDocument document); /** * Create a context to use for creating a data key * @param kmsProvider the KMS provider * @param options the data key options * @return the context */ MongoCryptContext createDataKeyContext(String kmsProvider, MongoDataKeyOptions options); /** * Create a context to use for encryption * * @param document the document to encrypt, which must be in the form { "v" : BSON value to encrypt } * @param options the explicit encryption options * @return the context */ MongoCryptContext createExplicitEncryptionContext(BsonDocument document, MongoExplicitEncryptOptions options); /** * Create a context to use for encryption * * @param document the document to encrypt, which must be in the form { "v" : BSON value to encrypt } * @param options the expression encryption options * @return the context * @since 1.7 */ MongoCryptContext createEncryptExpressionContext(BsonDocument document, MongoExplicitEncryptOptions options); /** * Create a context to use for encryption * * @param document the document to decrypt,which must be in the form { "v" : encrypted BSON value } * @return the context */ MongoCryptContext createExplicitDecryptionContext(BsonDocument document); /** * Create a context to use for encryption * * @param filter The filter to use for the find command on the key vault collection to retrieve datakeys to rewrap. * @param options the rewrap many data key options * @return the context * @since 1.5 */ MongoCryptContext createRewrapManyDatakeyContext(BsonDocument filter, MongoRewrapManyDataKeyOptions options); /** * @return the version string of the loaded crypt shared dynamic library if available or null * @since 1.5 */ String getCryptSharedLibVersionString(); @Override void close(); } MongoCryptContext.java000066400000000000000000000065071454530651600345220ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import org.bson.BsonDocument; import org.bson.RawBsonDocument; import java.io.Closeable; /** * An interface representing the lifecycle of an encryption or decryption request. It's modelled as a state machine. */ public interface MongoCryptContext extends Closeable { /** * The possible states. */ enum State { /** * Needs collection information from the cluster encrypting to */ NEED_MONGO_COLLINFO(CAPI.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO), /** * Need to mark command with encryption markers */ NEED_MONGO_MARKINGS(CAPI.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS), /** * Need keys from the key vault */ NEED_MONGO_KEYS(CAPI.MONGOCRYPT_CTX_NEED_MONGO_KEYS), /** * Need the key management service */ NEED_KMS(CAPI.MONGOCRYPT_CTX_NEED_KMS), /** * Need to fetch/renew KMS credentials * @since 1.4 */ NEED_KMS_CREDENTIALS(CAPI.MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS), /** * Ready for encryption/decryption */ READY(CAPI.MONGOCRYPT_CTX_READY), /** * Done */ DONE(CAPI.MONGOCRYPT_CTX_DONE); private final int index; State(final int index) { this.index = index; } static State fromIndex(final int index) { for (State state : State.values()) { if (state.index == index) { return state; } } throw new MongoCryptException("Unknown context state " + index); } } /** * Gets the current state. * * @return the current state */ State getState(); /** * * @return the operation to execute */ RawBsonDocument getMongoOperation(); /** * * @param document a result of the operation */ void addMongoOperationResult(BsonDocument document); /** * Signal completion of the operation */ void completeMongoOperation(); /** * Provide KMS credentials on demand, in response to NEED_KMS_CREDENTIALS state * * @param credentialsDocument document containing all credentials * @since 1.4 */ void provideKmsProviderCredentials(BsonDocument credentialsDocument); /** * * @return the next key decryptor, or null if there are no more */ MongoKeyDecryptor nextKeyDecryptor(); /** * Indicate that all key decryptors have been completed */ void completeKeyDecryptors(); /** * * @return the encrypted or decrypted document */ RawBsonDocument finish(); @Override void close(); } MongoCryptContextImpl.java000066400000000000000000000125631454530651600353430ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_t; import org.bson.BsonDocument; import org.bson.RawBsonDocument; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_new; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_finalize; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_kms_done; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_mongo_done; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_mongo_feed; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_mongo_op; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_next_kms_ctx; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_provide_kms_providers; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_state; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_status; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_new; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import static com.mongodb.crypt.capi.CAPIHelper.toBinary; import static com.mongodb.crypt.capi.CAPIHelper.toDocument; import static org.bson.assertions.Assertions.isTrue; import static org.bson.assertions.Assertions.notNull; class MongoCryptContextImpl implements MongoCryptContext { private final mongocrypt_ctx_t wrapped; private volatile boolean closed; MongoCryptContextImpl(final mongocrypt_ctx_t wrapped) { notNull("wrapped", wrapped); this.wrapped = wrapped; } @Override public State getState() { isTrue("open", !closed); return State.fromIndex(mongocrypt_ctx_state(wrapped)); } @Override public RawBsonDocument getMongoOperation() { isTrue("open", !closed); mongocrypt_binary_t binary = mongocrypt_binary_new(); try { boolean success = mongocrypt_ctx_mongo_op(wrapped, binary); if (!success) { throwExceptionFromStatus(); } return toDocument(binary); } finally { mongocrypt_binary_destroy(binary); } } @Override public void addMongoOperationResult(final BsonDocument document) { isTrue("open", !closed); try (BinaryHolder binaryHolder = toBinary(document)) { boolean success = mongocrypt_ctx_mongo_feed(wrapped, binaryHolder.getBinary()); if (!success) { throwExceptionFromStatus(); } } } @Override public void completeMongoOperation() { isTrue("open", !closed); boolean success = mongocrypt_ctx_mongo_done(wrapped); if (!success) { throwExceptionFromStatus(); } } @Override public void provideKmsProviderCredentials(final BsonDocument credentialsDocument) { try (BinaryHolder binaryHolder = toBinary(credentialsDocument)) { boolean success = mongocrypt_ctx_provide_kms_providers(wrapped, binaryHolder.getBinary()); if (!success) { throwExceptionFromStatus(); } } } @Override public MongoKeyDecryptor nextKeyDecryptor() { isTrue("open", !closed); mongocrypt_kms_ctx_t kmsContext = mongocrypt_ctx_next_kms_ctx(wrapped); if (kmsContext == null) { return null; } return new MongoKeyDecryptorImpl(kmsContext); } @Override public void completeKeyDecryptors() { isTrue("open", !closed); boolean success = mongocrypt_ctx_kms_done(wrapped); if (!success) { throwExceptionFromStatus(); } } @Override public RawBsonDocument finish() { isTrue("open", !closed); mongocrypt_binary_t binary = mongocrypt_binary_new(); try { boolean success = mongocrypt_ctx_finalize(wrapped, binary); if (!success) { throwExceptionFromStatus(); } return toDocument(binary); } finally { mongocrypt_binary_destroy(binary); } } @Override public void close() { mongocrypt_ctx_destroy(wrapped); closed = true; } static void throwExceptionFromStatus(final mongocrypt_ctx_t wrapped) { mongocrypt_status_t status = mongocrypt_status_new(); mongocrypt_ctx_status(wrapped, status); MongoCryptException e = new MongoCryptException(status); mongocrypt_status_destroy(status); throw e; } private void throwExceptionFromStatus() { throwExceptionFromStatus(wrapped); } } MongoCryptException.java000066400000000000000000000035461454530651600350340ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_code; import static org.bson.assertions.Assertions.isTrue; /** * Top level Exception for all Mongo Crypt CAPI exceptions */ public class MongoCryptException extends RuntimeException { private static final long serialVersionUID = -5524416583514807953L; private final int code; /** * @param msg the message */ public MongoCryptException(final String msg) { super(msg); this.code = -1; } /** * @param msg the message * @param cause the cause */ public MongoCryptException(final String msg, Throwable cause) { super(msg, cause); this.code = -1; } /** * Construct an instance from a {@code mongocrypt_status_t}. * * @param status the status */ MongoCryptException(final mongocrypt_status_t status) { super(CAPI.mongocrypt_status_message(status, null).toString()); isTrue("status not ok", !CAPI.mongocrypt_status_ok(status)); code = mongocrypt_status_code(status); } /** * @return the error code for the exception. */ public int getCode() { return code; } } MongoCryptImpl.java000066400000000000000000000457401454530651600340010ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.cstring; import com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_log_fn_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_t; import com.sun.jna.Pointer; import org.bson.BsonBinary; import org.bson.BsonDocument; import org.bson.BsonString; import javax.crypto.Cipher; import java.nio.ByteBuffer; import java.security.SecureRandom; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_LOG_LEVEL_ERROR; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_LOG_LEVEL_FATAL; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_LOG_LEVEL_INFO; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_LOG_LEVEL_TRACE; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_LOG_LEVEL_WARNING; import static com.mongodb.crypt.capi.CAPI.mongocrypt_crypt_shared_lib_version_string; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_datakey_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_decrypt_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_encrypt_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_explicit_decrypt_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_explicit_encrypt_expression_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_explicit_encrypt_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_new; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_rewrap_many_datakey_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_algorithm; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_algorithm_range; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_contention_factor; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_key_alt_name; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_key_encryption_key; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_key_id; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_key_material; import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_query_type; import static com.mongodb.crypt.capi.CAPI.mongocrypt_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_init; import static com.mongodb.crypt.capi.CAPI.mongocrypt_new; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_aes_256_ctr; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_append_crypt_shared_lib_search_path; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_bypass_query_analysis; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_crypto_hooks; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_encrypted_field_config_map; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_kms_provider_aws; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_kms_provider_local; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_kms_providers; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_log_handler; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_schema_map; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_set_crypt_shared_lib_path_override; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_use_need_kms_credentials_state; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_new; import static com.mongodb.crypt.capi.CAPIHelper.toBinary; import static org.bson.assertions.Assertions.isTrue; import static org.bson.assertions.Assertions.notNull; class MongoCryptImpl implements MongoCrypt { private static final Logger LOGGER = Loggers.getLogger(); private final mongocrypt_t wrapped; // Keep a strong reference to all the callbacks so that they don't get garbage collected @SuppressWarnings("FieldCanBeLocal") private final LogCallback logCallback; @SuppressWarnings("FieldCanBeLocal") private final CipherCallback aesCBC256EncryptCallback; @SuppressWarnings("FieldCanBeLocal") private final CipherCallback aesCBC256DecryptCallback; @SuppressWarnings("FieldCanBeLocal") private final CipherCallback aesCTR256EncryptCallback; @SuppressWarnings("FieldCanBeLocal") private final CipherCallback aesCTR256DecryptCallback; @SuppressWarnings("FieldCanBeLocal") private final MacCallback hmacSha512Callback; @SuppressWarnings("FieldCanBeLocal") private final MacCallback hmacSha256Callback; @SuppressWarnings("FieldCanBeLocal") private final MessageDigestCallback sha256Callback; @SuppressWarnings("FieldCanBeLocal") private final SecureRandomCallback secureRandomCallback; @SuppressWarnings("FieldCanBeLocal") private final SigningRSAESPKCSCallback signingRSAESPKCSCallback; private final AtomicBoolean closed; MongoCryptImpl(final MongoCryptOptions options) { closed = new AtomicBoolean(); wrapped = mongocrypt_new(); if (wrapped == null) { throw new MongoCryptException("Unable to create new mongocrypt object"); } logCallback = new LogCallback(); configure(() -> mongocrypt_setopt_log_handler(wrapped, logCallback, null)); // We specify NoPadding here because the underlying C library is responsible for padding prior // to executing the callback aesCBC256EncryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.ENCRYPT_MODE); aesCBC256DecryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.DECRYPT_MODE); aesCTR256EncryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.ENCRYPT_MODE); aesCTR256DecryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.DECRYPT_MODE); hmacSha512Callback = new MacCallback("HmacSHA512"); hmacSha256Callback = new MacCallback("HmacSHA256"); sha256Callback = new MessageDigestCallback("SHA-256"); secureRandomCallback = new SecureRandomCallback(new SecureRandom()); configure(() -> mongocrypt_setopt_crypto_hooks(wrapped, aesCBC256EncryptCallback, aesCBC256DecryptCallback, secureRandomCallback, hmacSha512Callback, hmacSha256Callback, sha256Callback, null)); signingRSAESPKCSCallback = new SigningRSAESPKCSCallback(); configure(() -> mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(wrapped, signingRSAESPKCSCallback, null)); configure(() -> mongocrypt_setopt_aes_256_ctr(wrapped, aesCTR256EncryptCallback, aesCTR256DecryptCallback, null)); if (options.getLocalKmsProviderOptions() != null) { try (BinaryHolder localMasterKeyBinaryHolder = toBinary(options.getLocalKmsProviderOptions().getLocalMasterKey())) { configure(() -> mongocrypt_setopt_kms_provider_local(wrapped, localMasterKeyBinaryHolder.getBinary())); } } if (options.getAwsKmsProviderOptions() != null) { configure(() -> mongocrypt_setopt_kms_provider_aws(wrapped, new cstring(options.getAwsKmsProviderOptions().getAccessKeyId()), -1, new cstring(options.getAwsKmsProviderOptions().getSecretAccessKey()), -1)); } if (options.isNeedsKmsCredentialsStateEnabled()) { mongocrypt_setopt_use_need_kms_credentials_state(wrapped); } if (options.getKmsProviderOptions() != null) { try (BinaryHolder binaryHolder = toBinary(options.getKmsProviderOptions())) { configure(() -> mongocrypt_setopt_kms_providers(wrapped, binaryHolder.getBinary())); } } if (options.getLocalSchemaMap() != null) { BsonDocument localSchemaMapDocument = new BsonDocument(); localSchemaMapDocument.putAll(options.getLocalSchemaMap()); try (BinaryHolder localSchemaMapBinaryHolder = toBinary(localSchemaMapDocument)) { configure(() -> mongocrypt_setopt_schema_map(wrapped, localSchemaMapBinaryHolder.getBinary())); } } if (options.isBypassQueryAnalysis()) { mongocrypt_setopt_bypass_query_analysis(wrapped); } if (options.getEncryptedFieldsMap() != null) { BsonDocument localEncryptedFieldsMap = new BsonDocument(); localEncryptedFieldsMap.putAll(options.getEncryptedFieldsMap()); try (BinaryHolder localEncryptedFieldsMapHolder = toBinary(localEncryptedFieldsMap)) { configure(() -> mongocrypt_setopt_encrypted_field_config_map(wrapped, localEncryptedFieldsMapHolder.getBinary())); } } options.getSearchPaths().forEach(p -> mongocrypt_setopt_append_crypt_shared_lib_search_path(wrapped, new cstring(p))); if (options.getExtraOptions().containsKey("cryptSharedLibPath")) { mongocrypt_setopt_set_crypt_shared_lib_path_override(wrapped, new cstring(options.getExtraOptions().getString("cryptSharedLibPath").getValue())); } configure(() -> mongocrypt_init(wrapped)); } @Override public MongoCryptContext createEncryptionContext(final String database, final BsonDocument commandDocument) { isTrue("open", !closed.get()); notNull("database", database); notNull("commandDocument", commandDocument); mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); if (context == null) { throwExceptionFromStatus(); } try (BinaryHolder commandDocumentBinaryHolder = toBinary(commandDocument)) { configure(() -> mongocrypt_ctx_encrypt_init(context, new cstring(database), -1, commandDocumentBinaryHolder.getBinary()), context); return new MongoCryptContextImpl(context); } } @Override public MongoCryptContext createDecryptionContext(final BsonDocument document) { isTrue("open", !closed.get()); mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); if (context == null) { throwExceptionFromStatus(); } try (BinaryHolder documentBinaryHolder = toBinary(document)){ configure(() -> mongocrypt_ctx_decrypt_init(context, documentBinaryHolder.getBinary()), context); } return new MongoCryptContextImpl(context); } @Override public MongoCryptContext createDataKeyContext(final String kmsProvider, final MongoDataKeyOptions options) { isTrue("open", !closed.get()); mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); if (context == null) { throwExceptionFromStatus(); } BsonDocument keyDocument = new BsonDocument("provider", new BsonString(kmsProvider)); BsonDocument masterKey = options.getMasterKey(); if (masterKey != null) { masterKey.forEach(keyDocument::append); } try (BinaryHolder masterKeyHolder = toBinary(keyDocument)) { configure(() -> mongocrypt_ctx_setopt_key_encryption_key(context, masterKeyHolder.getBinary()), context); } if (options.getKeyAltNames() != null) { for (String cur : options.getKeyAltNames()) { try (BinaryHolder keyAltNameBinaryHolder = toBinary(new BsonDocument("keyAltName", new BsonString(cur)))) { configure(() -> mongocrypt_ctx_setopt_key_alt_name(context, keyAltNameBinaryHolder.getBinary()), context); } } } if (options.getKeyMaterial() != null) { try (BinaryHolder keyMaterialBinaryHolder = toBinary(new BsonDocument("keyMaterial", new BsonBinary(options.getKeyMaterial())))) { configure(() -> mongocrypt_ctx_setopt_key_material(context, keyMaterialBinaryHolder.getBinary()), context); } } if (!mongocrypt_ctx_datakey_init(context)) { MongoCryptContextImpl.throwExceptionFromStatus(context); } return new MongoCryptContextImpl(context); } @Override public MongoCryptContext createExplicitEncryptionContext(final BsonDocument document, final MongoExplicitEncryptOptions options) { isTrue("open", !closed.get()); mongocrypt_ctx_t context = configureExplicitEncryption(options); try (BinaryHolder documentBinaryHolder = toBinary(document)) { configure(() -> mongocrypt_ctx_explicit_encrypt_init(context, documentBinaryHolder.getBinary()), context); } return new MongoCryptContextImpl(context); } @Override public MongoCryptContext createEncryptExpressionContext(final BsonDocument document, final MongoExplicitEncryptOptions options) { isTrue("open", !closed.get()); mongocrypt_ctx_t context = configureExplicitEncryption(options); try (BinaryHolder documentBinaryHolder = toBinary(document)) { configure(() -> mongocrypt_ctx_explicit_encrypt_expression_init(context, documentBinaryHolder.getBinary()), context); } return new MongoCryptContextImpl(context); } @Override public MongoCryptContext createExplicitDecryptionContext(final BsonDocument document) { isTrue("open", !closed.get()); mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); if (context == null) { throwExceptionFromStatus(); } try (BinaryHolder binaryHolder = toBinary(document)) { configure(() -> mongocrypt_ctx_explicit_decrypt_init(context, binaryHolder.getBinary()), context); } return new MongoCryptContextImpl(context); } @Override public MongoCryptContext createRewrapManyDatakeyContext(final BsonDocument filter, final MongoRewrapManyDataKeyOptions options) { isTrue("open", !closed.get()); mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); if (context == null) { throwExceptionFromStatus(); } if (options != null && options.getProvider() != null) { BsonDocument keyDocument = new BsonDocument("provider", new BsonString(options.getProvider())); BsonDocument masterKey = options.getMasterKey(); if (masterKey != null) { masterKey.forEach(keyDocument::append); } try (BinaryHolder binaryHolder = toBinary(keyDocument)) { configure(() -> mongocrypt_ctx_setopt_key_encryption_key(context, binaryHolder.getBinary()), context); } } try (BinaryHolder binaryHolder = toBinary(filter)) { configure(() -> mongocrypt_ctx_rewrap_many_datakey_init(context, binaryHolder.getBinary()), context); } return new MongoCryptContextImpl(context); } @Override public String getCryptSharedLibVersionString() { cstring versionString = mongocrypt_crypt_shared_lib_version_string(wrapped, null); return versionString == null ? null : versionString.toString(); } @Override public void close() { if (!closed.getAndSet(true)) { mongocrypt_destroy(wrapped); } } private mongocrypt_ctx_t configureExplicitEncryption(final MongoExplicitEncryptOptions options) { mongocrypt_ctx_t context = mongocrypt_ctx_new(wrapped); if (context == null) { throwExceptionFromStatus(); } if (options.getKeyId() != null) { try (BinaryHolder keyIdBinaryHolder = toBinary(ByteBuffer.wrap(options.getKeyId().getData()))) { configure(() -> mongocrypt_ctx_setopt_key_id(context, keyIdBinaryHolder.getBinary()), context); } } else if (options.getKeyAltName() != null) { try (BinaryHolder keyAltNameBinaryHolder = toBinary(new BsonDocument("keyAltName", new BsonString(options.getKeyAltName())))) { configure(() -> mongocrypt_ctx_setopt_key_alt_name(context, keyAltNameBinaryHolder.getBinary()), context); } } if (options.getAlgorithm() != null) { configure(() -> mongocrypt_ctx_setopt_algorithm(context, new cstring(options.getAlgorithm()), -1), context); } if (options.getQueryType() != null) { configure(() -> mongocrypt_ctx_setopt_query_type(context, new cstring(options.getQueryType()), -1), context); } if (options.getContentionFactor() != null) { configure(() -> mongocrypt_ctx_setopt_contention_factor(context, options.getContentionFactor()), context); } if (options.getRangeOptions() != null) { try (BinaryHolder rangeOptionsHolder = toBinary(options.getRangeOptions())) { configure(() -> mongocrypt_ctx_setopt_algorithm_range(context, rangeOptionsHolder.getBinary()), context); } } return context; } private void configure(final Supplier successSupplier) { if (!successSupplier.get()) { throwExceptionFromStatus(); } } private void configure(final Supplier successSupplier, final mongocrypt_ctx_t context) { if (!successSupplier.get()) { MongoCryptContextImpl.throwExceptionFromStatus(context); } } private void throwExceptionFromStatus() { mongocrypt_status_t status = mongocrypt_status_new(); mongocrypt_status(wrapped, status); MongoCryptException e = new MongoCryptException(status); mongocrypt_status_destroy(status); throw e; } static class LogCallback implements mongocrypt_log_fn_t { @Override public void log(final int level, final cstring message, final int messageLength, final Pointer ctx) { if (level == MONGOCRYPT_LOG_LEVEL_FATAL) { LOGGER.error(message.toString()); } if (level == MONGOCRYPT_LOG_LEVEL_ERROR) { LOGGER.error(message.toString()); } if (level == MONGOCRYPT_LOG_LEVEL_WARNING) { LOGGER.warn(message.toString()); } if (level == MONGOCRYPT_LOG_LEVEL_INFO) { LOGGER.info(message.toString()); } if (level == MONGOCRYPT_LOG_LEVEL_TRACE) { LOGGER.trace(message.toString()); } } } } MongoCryptOptions.java000066400000000000000000000215241454530651600345250ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import org.bson.BsonDocument; import java.util.List; import java.util.Map; import static java.util.Collections.emptyList; import static org.bson.assertions.Assertions.isTrue; /** * The options for configuring MongoCrypt. */ public class MongoCryptOptions { private final MongoAwsKmsProviderOptions awsKmsProviderOptions; private final MongoLocalKmsProviderOptions localKmsProviderOptions; private final BsonDocument kmsProviderOptions; private final Map localSchemaMap; private final boolean needsKmsCredentialsStateEnabled; private final Map encryptedFieldsMap; private final BsonDocument extraOptions; private final boolean bypassQueryAnalysis; private final List searchPaths; /** * Construct a builder for the options * * @return the builder */ public static Builder builder() { return new Builder(); } /** * Gets the AWS KMS provider options. * * @return the AWS KMS provider options, which may be null */ public MongoAwsKmsProviderOptions getAwsKmsProviderOptions() { return awsKmsProviderOptions; } /** * Gets the local KMS provider options. * * @return the local KMS provider options, which may be null */ public MongoLocalKmsProviderOptions getLocalKmsProviderOptions() { return localKmsProviderOptions; } /** * Returns the KMS provider options. * * @return the KMS provider options, which may be null * @since 1.1 */ public BsonDocument getKmsProviderOptions() { return kmsProviderOptions; } /** * Gets the local schema map. * * @return the local schema map */ public Map getLocalSchemaMap() { return localSchemaMap; } /** * Gets whether the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS is enabled. Defaults to false * * @return whether the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS is enabled * @since 1.4 */ public boolean isNeedsKmsCredentialsStateEnabled() { return needsKmsCredentialsStateEnabled; } /** * Gets the encrypted fields map. * * @since 1.5 * @return the encrypted fields map */ public Map getEncryptedFieldsMap() { return encryptedFieldsMap; } /** * Gets whether automatic analysis of outgoing commands should be disabled. * * @since 1.5 * @return true if bypassing query analysis */ public boolean isBypassQueryAnalysis() { return bypassQueryAnalysis; } /** * The extraOptions that relate to the mongocryptd process or shared library. * @return the extra options * @since 1.5 */ public BsonDocument getExtraOptions() { return extraOptions; } /** * Gets the search paths * @return this * @since 1.5 */ public List getSearchPaths() { return searchPaths; } /** * The builder for the options */ public static class Builder { private MongoAwsKmsProviderOptions awsKmsProviderOptions; private MongoLocalKmsProviderOptions localKmsProviderOptions; private BsonDocument kmsProviderOptions = null; private Map localSchemaMap = null; private boolean needsKmsCredentialsStateEnabled; private Map encryptedFieldsMap = null; private boolean bypassQueryAnalysis; private BsonDocument extraOptions = new BsonDocument(); private List searchPaths = emptyList(); private Builder() { } /** * Sets the AWS KMS provider options. * * @param awsKmsProviderOptions the AWS KMS provider options * @return this */ public Builder awsKmsProviderOptions(final MongoAwsKmsProviderOptions awsKmsProviderOptions) { this.awsKmsProviderOptions = awsKmsProviderOptions; return this; } /** * Sets the local KMS provider options. * * @param localKmsProviderOptions the local KMS provider options * @return this */ public Builder localKmsProviderOptions(final MongoLocalKmsProviderOptions localKmsProviderOptions) { this.localKmsProviderOptions = localKmsProviderOptions; return this; } /** * Sets the KMS provider options. * * @param kmsProviderOptions the KMS provider options document * @return this * @since 1.1 */ public Builder kmsProviderOptions(final BsonDocument kmsProviderOptions) { this.kmsProviderOptions = kmsProviderOptions; return this; } /** * Sets the local schema map. * * @param localSchemaMap local schema map * @return this */ public Builder localSchemaMap(final Map localSchemaMap) { this.localSchemaMap = localSchemaMap; return this; } /** * Sets whether the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS is enabled. Defaults to false * * @param needsKmsCredentialsStateEnabled whether the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS is enabled * @return this * @since 1.4 */ public Builder needsKmsCredentialsStateEnabled(final boolean needsKmsCredentialsStateEnabled) { this.needsKmsCredentialsStateEnabled = needsKmsCredentialsStateEnabled; return this; } /** * Sets the encrypted fields map. * * @param encryptedFieldsMap the encrypted fields map * @since 1.5 * @return this */ public Builder encryptedFieldsMap(final Map encryptedFieldsMap) { this.encryptedFieldsMap = encryptedFieldsMap; return this; } /** * Sets whether automatic analysis of outgoing commands should be disabled. * *

Set bypassQueryAnalysis to true to use explicit encryption on indexed fields * without the MongoDB Enterprise Advanced licensed crypt shared library.

* * @param bypassQueryAnalysis whether the analysis of outgoing commands should be disabled. * @since 1.5 * @return this */ public Builder bypassQueryAnalysis(final boolean bypassQueryAnalysis) { this.bypassQueryAnalysis = bypassQueryAnalysis; return this; } /** * The extraOptions that relate to the mongocryptd process or shared library. * @param extraOptions the extraOptions * @return this * @since 1.5 */ public Builder extraOptions(final BsonDocument extraOptions) { this.extraOptions = extraOptions; return this; } /** * Sets search paths * @param searchPaths sets search path * @return this * @since 1.5 */ public Builder searchPaths(final List searchPaths) { this.searchPaths = searchPaths; return this; } /** * Build the options. * * @return the options */ public MongoCryptOptions build() { return new MongoCryptOptions(this); } } private MongoCryptOptions(final Builder builder) { isTrue("at least one KMS provider is configured", builder.awsKmsProviderOptions != null || builder.localKmsProviderOptions != null || builder.kmsProviderOptions != null ); this.awsKmsProviderOptions = builder.awsKmsProviderOptions; this.localKmsProviderOptions = builder.localKmsProviderOptions; this.kmsProviderOptions = builder.kmsProviderOptions; this.localSchemaMap = builder.localSchemaMap; this.needsKmsCredentialsStateEnabled = builder.needsKmsCredentialsStateEnabled; this.encryptedFieldsMap = builder.encryptedFieldsMap; this.bypassQueryAnalysis = builder.bypassQueryAnalysis; this.extraOptions = builder.extraOptions; this.searchPaths = builder.searchPaths; } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoCrypts.java000066400000000000000000000021411454530651600334050ustar00rootroot00000000000000/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; /** * The entry point to the MongoCrypt library. */ public class MongoCrypts { /** * Create a {@code MongoCrypt} instance. * *

* Make sure that JNA is able to find the shared library, most likely by setting the jna.library.path system property *

* * @param options the options * @return the instance */ public static MongoCrypt create(MongoCryptOptions options) { return new MongoCryptImpl(options); } } MongoDataKeyOptions.java000066400000000000000000000061101454530651600347400ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import org.bson.BsonDocument; import java.util.List; /** * The options for creation of a data key */ public class MongoDataKeyOptions { private final List keyAltNames; private final BsonDocument masterKey; private final byte[] keyMaterial; /** * Options builder */ public static class Builder { private List keyAltNames; private BsonDocument masterKey; private byte[] keyMaterial; /** * Add alternate key names * @param keyAltNames the alternate key names * @return this */ public Builder keyAltNames(final List keyAltNames) { this.keyAltNames = keyAltNames; return this; } /** * Add the master key. * * @param masterKey the master key * @return this */ public Builder masterKey(final BsonDocument masterKey) { this.masterKey = masterKey; return this; } /** * Add the key material * * @param keyMaterial the optional custom key material for the data key * @return this * @since 1.5 */ public Builder keyMaterial(final byte[] keyMaterial) { this.keyMaterial = keyMaterial; return this; } /** * Build the options. * * @return the options */ public MongoDataKeyOptions build() { return new MongoDataKeyOptions(this); } } /** * Create a builder for the options. * * @return the builder */ public static Builder builder() { return new Builder(); } /** * Gets the alternate key names for the data key. * * @return the alternate key names */ public List getKeyAltNames() { return keyAltNames; } /** * Gets the master key for the data key. * * @return the master key */ public BsonDocument getMasterKey() { return masterKey; } /** * Gets the custom key material if set. * * @return the custom key material for the data key or null * @since 1.5 */ public byte[] getKeyMaterial() { return keyMaterial; } private MongoDataKeyOptions(final Builder builder) { keyAltNames = builder.keyAltNames; masterKey = builder.masterKey; keyMaterial = builder.keyMaterial; } } MongoExplicitEncryptOptions.java000066400000000000000000000144151454530651600365530ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import org.bson.BsonBinary; import org.bson.BsonDocument; import java.util.Objects; /** * Options for explicit encryption. */ public class MongoExplicitEncryptOptions { private final BsonBinary keyId; private final String keyAltName; private final String algorithm; private final Long contentionFactor; private final String queryType; private final BsonDocument rangeOptions; /** * The builder for the options */ public static class Builder { private BsonBinary keyId; private String keyAltName; private String algorithm; private Long contentionFactor; private String queryType; private BsonDocument rangeOptions; private Builder() { } /** * Add the key identifier. * * @param keyId the key idenfifier * @return this */ public Builder keyId(final BsonBinary keyId) { this.keyId = keyId; return this; } /** * Add the key alternative name. * * @param keyAltName the key alternative name * @return this */ public Builder keyAltName(final String keyAltName) { this.keyAltName = keyAltName; return this; } /** * Add the encryption algorithm. * *

To insert or query with an "Indexed" encrypted payload, use a MongoClient configured with {@code AutoEncryptionSettings}. * {@code AutoEncryptionSettings.bypassQueryAnalysis} may be true. * {@code AutoEncryptionSettings.bypassAutoEncryption must be false}.

* * @param algorithm the encryption algorithm * @return this */ public Builder algorithm(final String algorithm) { this.algorithm = algorithm; return this; } /** * The contention factor. * *

It is an error to set contentionFactor when algorithm is not "Indexed". * @param contentionFactor the contention factor * @return this * @since 1.5 */ public Builder contentionFactor(final Long contentionFactor) { this.contentionFactor = contentionFactor; return this; } /** * The QueryType. * *

It is an error to set queryType when algorithm is not "Indexed".

* * @param queryType the query type * @return this * @since 1.5 */ public Builder queryType(final String queryType) { this.queryType = queryType; return this; } /** * The Range Options. * *

It is an error to set rangeOptions when the algorithm is not "rangePreview".

* * @param rangeOptions the range options * @return this * @since 1.7 */ public Builder rangeOptions(final BsonDocument rangeOptions) { this.rangeOptions = rangeOptions; return this; } /** * Build the options. * * @return the options */ public MongoExplicitEncryptOptions build() { return new MongoExplicitEncryptOptions(this); } } /** * Create a builder for the options. * * @return the builder */ public static Builder builder() { return new Builder(); } /** * Gets the key identifier * @return the key identifier */ public BsonBinary getKeyId() { return keyId; } /** * Gets the key alternative name * @return the key alternative name */ public String getKeyAltName() { return keyAltName; } /** * Gets the encryption algorithm * @return the encryption algorithm */ public String getAlgorithm() { return algorithm; } /** * Gets the contention factor * @return the contention factor * @since 1.5 */ public Long getContentionFactor() { return contentionFactor; } /** * Gets the query type * @return the query type * @since 1.5 */ public String getQueryType() { return queryType; } /** * Gets the range options * @return the range options * @since 1.7 */ public BsonDocument getRangeOptions() { return rangeOptions; } private MongoExplicitEncryptOptions(Builder builder) { this.keyId = builder.keyId; this.keyAltName = builder.keyAltName; this.algorithm = builder.algorithm; this.contentionFactor = builder.contentionFactor; this.queryType = builder.queryType; this.rangeOptions = builder.rangeOptions; if (!(Objects.equals(algorithm, "Indexed") || Objects.equals(algorithm, "RangePreview"))) { if (contentionFactor != null) { throw new IllegalStateException("Invalid configuration, contentionFactor can only be set if algorithm is 'Indexed' or 'RangePreview'"); } else if (queryType != null) { throw new IllegalStateException("Invalid configuration, queryType can only be set if algorithm is 'Indexed' or 'RangePreview'"); } } } @Override public String toString() { return "MongoExplicitEncryptOptions{" + "keyId=" + keyId + ", keyAltName='" + keyAltName + '\'' + ", algorithm='" + algorithm + '\'' + ", contentionFactor=" + contentionFactor + ", queryType='" + queryType + '\'' + ", rangeOptions=" + rangeOptions + '}'; } } MongoKeyDecryptor.java000066400000000000000000000044131454530651600344720ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import java.nio.ByteBuffer; /** * An interface representing a key decryption operation using a key management service. */ public interface MongoKeyDecryptor { /** * Gets the name of the KMS provider, e.g. "aws" or "kmip" * * @return the KMS provider name */ String getKmsProvider(); /** * Gets the host name of the key management service. * * @return the host name */ String getHostName(); /** * Gets the message to send to the key management service. * *

* Clients should call this method first, and send the message on a TLS connection to a configured KMS server. *

* * @return the message to send */ ByteBuffer getMessage(); /** * Gets the number of bytes that should be received from the KMS server. * *

* After sending the message to the KMS server, clients should call this method in a loop, receiving {@code bytesNeeded} from * the KMS server and feeding those bytes to this decryptor, until {@code bytesNeeded} is 0. *

* * @return the actual number of bytes that clients should be prepared receive */ int bytesNeeded(); /** * Feed the received bytes to the decryptor. * *

* After sending the message to the KMS server, clients should call this method in a loop, receiving the number of bytes indicated by * a call to {@link #bytesNeeded()} from the KMS server and feeding those bytes to this decryptor, until {@link #bytesNeeded()} * returns 0. *

* * @param bytes the received bytes */ void feed(ByteBuffer bytes); } MongoKeyDecryptorImpl.java000066400000000000000000000073051454530651600353170ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import com.sun.jna.Pointer; import com.sun.jna.ptr.PointerByReference; import java.nio.ByteBuffer; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_binary_new; import static com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_bytes_needed; import static com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_endpoint; import static com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_feed; import static com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_get_kms_provider; import static com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_message; import static com.mongodb.crypt.capi.CAPI.mongocrypt_kms_ctx_status; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_new; import static com.mongodb.crypt.capi.CAPIHelper.toBinary; import static com.mongodb.crypt.capi.CAPIHelper.toByteBuffer; import static org.bson.assertions.Assertions.notNull; class MongoKeyDecryptorImpl implements MongoKeyDecryptor { private final mongocrypt_kms_ctx_t wrapped; MongoKeyDecryptorImpl(final mongocrypt_kms_ctx_t wrapped) { notNull("wrapped", wrapped); this.wrapped = wrapped; } @Override public String getKmsProvider() { return mongocrypt_kms_ctx_get_kms_provider(wrapped, null).toString(); } @Override public String getHostName() { PointerByReference hostNamePointerByReference = new PointerByReference(); boolean success = mongocrypt_kms_ctx_endpoint(wrapped, hostNamePointerByReference); if (!success) { throwExceptionFromStatus(); } Pointer hostNamePointer = hostNamePointerByReference.getValue(); return hostNamePointer.getString(0); } @Override public ByteBuffer getMessage() { mongocrypt_binary_t binary = mongocrypt_binary_new(); try { boolean success = mongocrypt_kms_ctx_message(wrapped, binary); if (!success) { throwExceptionFromStatus(); } return toByteBuffer(binary); } finally { mongocrypt_binary_destroy(binary); } } @Override public int bytesNeeded() { return mongocrypt_kms_ctx_bytes_needed(wrapped); } @Override public void feed(final ByteBuffer bytes) { try (BinaryHolder binaryHolder = toBinary(bytes)) { boolean success = mongocrypt_kms_ctx_feed(wrapped, binaryHolder.getBinary()); if (!success) { throwExceptionFromStatus(); } } } private void throwExceptionFromStatus() { mongocrypt_status_t status = mongocrypt_status_new(); mongocrypt_kms_ctx_status(wrapped, status); MongoCryptException e = new MongoCryptException(status); mongocrypt_status_destroy(status); throw e; } } MongoLocalKmsProviderOptions.java000066400000000000000000000040611454530651600366410ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import java.nio.ByteBuffer; import static org.bson.assertions.Assertions.notNull; /** * The options for configuring a local KMS provider. */ public class MongoLocalKmsProviderOptions { private final ByteBuffer localMasterKey; /** * Construct a builder for the options * * @return the builder */ public static Builder builder() { return new Builder(); } /** * Gets the local master key * * @return the local master key */ public ByteBuffer getLocalMasterKey() { return localMasterKey; } /** * The builder for the options */ public static class Builder { private ByteBuffer localMasterKey; private Builder() { } /** * Sets the local master key. * * @param localMasterKey the local master key * @return this */ public Builder localMasterKey(final ByteBuffer localMasterKey) { this.localMasterKey = localMasterKey; return this; } /** * Build the options. * * @return the options */ public MongoLocalKmsProviderOptions build() { return new MongoLocalKmsProviderOptions(this); } } private MongoLocalKmsProviderOptions(final Builder builder) { this.localMasterKey = notNull("Local KMS provider localMasterKey", builder.localMasterKey); } } MongoRewrapManyDataKeyOptions.java000066400000000000000000000046751454530651600367640ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mongodb.crypt.capi; import org.bson.BsonDocument; /** * The rewrap many data key options * *

* The masterKey document MUST have the fields corresponding to the given provider as specified in masterKey. *

* * @since 1.5 */ public class MongoRewrapManyDataKeyOptions { private final String provider; private final BsonDocument masterKey; /** * Options builder */ public static class Builder { private String provider; private BsonDocument masterKey; /** * The provider * * @param provider the provider * @return this */ public Builder provider(final String provider) { this.provider = provider; return this; } /** * Add the master key. * * @param masterKey the master key * @return this */ public Builder masterKey(final BsonDocument masterKey) { this.masterKey = masterKey; return this; } /** * Build the options. * * @return the options */ public MongoRewrapManyDataKeyOptions build() { return new MongoRewrapManyDataKeyOptions(this); } } /** * Create a builder for the options. * * @return the builder */ public static Builder builder() { return new Builder(); } /** * @return the provider name */ public String getProvider() { return provider; } /** * Gets the master key for the data key. * * @return the master key */ public BsonDocument getMasterKey() { return masterKey; } private MongoRewrapManyDataKeyOptions(final Builder builder) { provider = builder.provider; masterKey = builder.masterKey; } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/SLF4JLogger.java000066400000000000000000000046441454530651600331150ustar00rootroot00000000000000 /* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import org.slf4j.LoggerFactory; class SLF4JLogger implements Logger { private final org.slf4j.Logger delegate; SLF4JLogger(final String name) { this.delegate = LoggerFactory.getLogger(name); } @Override public String getName() { return delegate.getName(); } @Override public boolean isTraceEnabled() { return delegate.isTraceEnabled(); } @Override public void trace(final String msg) { delegate.trace(msg); } @Override public void trace(final String msg, final Throwable t) { delegate.trace(msg, t); } @Override public boolean isDebugEnabled() { return delegate.isDebugEnabled(); } @Override public void debug(final String msg) { delegate.debug(msg); } @Override public void debug(final String msg, final Throwable t) { delegate.debug(msg, t); } @Override public boolean isInfoEnabled() { return delegate.isInfoEnabled(); } @Override public void info(final String msg) { delegate.info(msg); } @Override public void info(final String msg, final Throwable t) { delegate.info(msg, t); } @Override public boolean isWarnEnabled() { return delegate.isWarnEnabled(); } @Override public void warn(final String msg) { delegate.warn(msg); } @Override public void warn(final String msg, final Throwable t) { delegate.warn(msg, t); } @Override public boolean isErrorEnabled() { return delegate.isErrorEnabled(); } @Override public void error(final String msg) { delegate.error(msg); } @Override public void error(final String msg, final Throwable t) { delegate.error(msg, t); } } SecureRandomCallback.java000066400000000000000000000035121454530651600350510ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.cstring; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_random_fn; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import com.sun.jna.Pointer; import java.security.SecureRandom; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_STATUS_ERROR_CLIENT; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_set; import static com.mongodb.crypt.capi.CAPIHelper.writeByteArrayToBinary; class SecureRandomCallback implements mongocrypt_random_fn { private final SecureRandom secureRandom; SecureRandomCallback(final SecureRandom secureRandom) { this.secureRandom = secureRandom; } @Override public boolean random(final Pointer ctx, final mongocrypt_binary_t out, final int count, final mongocrypt_status_t status) { try { byte[] randomBytes = new byte[count]; secureRandom.nextBytes(randomBytes); writeByteArrayToBinary(out, randomBytes); return true; } catch (Exception e) { mongocrypt_status_set(status, MONGOCRYPT_STATUS_ERROR_CLIENT, 0, new cstring(e.toString()), -1); return false; } } } SigningRSAESPKCSCallback.java000066400000000000000000000056411454530651600353440ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/* * Copyright 2008-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.CAPI.cstring; import com.mongodb.crypt.capi.CAPI.mongocrypt_binary_t; import com.mongodb.crypt.capi.CAPI.mongocrypt_hmac_fn; import com.mongodb.crypt.capi.CAPI.mongocrypt_status_t; import com.sun.jna.Pointer; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_STATUS_ERROR_CLIENT; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_set; import static com.mongodb.crypt.capi.CAPIHelper.toByteArray; import static com.mongodb.crypt.capi.CAPIHelper.writeByteArrayToBinary; class SigningRSAESPKCSCallback implements mongocrypt_hmac_fn { private static final String KEY_ALGORITHM = "RSA"; private static final String SIGN_ALGORITHM = "SHA256withRSA"; SigningRSAESPKCSCallback() { } @Override public boolean hmac(final Pointer ctx, final mongocrypt_binary_t key, final mongocrypt_binary_t in, final mongocrypt_binary_t out, final mongocrypt_status_t status) { try { byte[] result = getSignature(toByteArray(key), toByteArray(in)); writeByteArrayToBinary(out, result); return true; } catch (Exception e) { mongocrypt_status_set(status, MONGOCRYPT_STATUS_ERROR_CLIENT, 0, new cstring(e.toString()), -1); return false; } } static byte[] getSignature(final byte[] privateKeyBytes, final byte[] dataToSign) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); Signature privateSignature = Signature.getInstance(SIGN_ALGORITHM); privateSignature.initSign(privateKey); privateSignature.update(dataToSign); return privateSignature.sign(); } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/package-info.java000066400000000000000000000011771454530651600334550ustar00rootroot00000000000000/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/000077500000000000000000000000001454530651600231125ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/java/000077500000000000000000000000001454530651600240335ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/java/com/000077500000000000000000000000001454530651600246115ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/java/com/mongodb/000077500000000000000000000000001454530651600262365ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/000077500000000000000000000000001454530651600273775ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/capi/000077500000000000000000000000001454530651600303135ustar00rootroot00000000000000MongoCryptTest.java000066400000000000000000000331301454530651600340400ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/capi/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.mongodb.crypt.capi; import com.mongodb.crypt.capi.MongoCryptContext.State; import org.bson.BsonBinary; import org.bson.BsonBinarySubType; import org.bson.BsonDocument; import org.bson.BsonString; import org.bson.RawBsonDocument; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.URISyntaxException; import java.net.URL; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @SuppressWarnings("SameParameterValue") public class MongoCryptTest { @Test public void testEncrypt() throws URISyntaxException, IOException { MongoCrypt mongoCrypt = createMongoCrypt(); assertNotNull(mongoCrypt); MongoCryptContext encryptor = mongoCrypt.createEncryptionContext("test", getResourceAsDocument("command.json")); assertEquals(State.NEED_MONGO_COLLINFO, encryptor.getState()); BsonDocument listCollectionsFilter = encryptor.getMongoOperation(); assertEquals(getResourceAsDocument("list-collections-filter.json"), listCollectionsFilter); encryptor.addMongoOperationResult(getResourceAsDocument("collection-info.json")); encryptor.completeMongoOperation(); assertEquals(State.NEED_MONGO_MARKINGS, encryptor.getState()); BsonDocument jsonSchema = encryptor.getMongoOperation(); assertEquals(getResourceAsDocument("mongocryptd-command.json"), jsonSchema); encryptor.addMongoOperationResult(getResourceAsDocument("mongocryptd-reply.json")); encryptor.completeMongoOperation(); assertEquals(State.NEED_MONGO_KEYS, encryptor.getState()); testKeyDecryptor(encryptor); assertEquals(State.READY, encryptor.getState()); RawBsonDocument encryptedDocument = encryptor.finish(); assertEquals(State.DONE, encryptor.getState()); assertEquals(getResourceAsDocument("encrypted-command.json"), encryptedDocument); encryptor.close(); mongoCrypt.close(); } @Test public void testDecrypt() throws IOException, URISyntaxException { MongoCrypt mongoCrypt = createMongoCrypt(); assertNotNull(mongoCrypt); MongoCryptContext decryptor = mongoCrypt.createDecryptionContext(getResourceAsDocument("encrypted-command-reply.json")); assertEquals(State.NEED_MONGO_KEYS, decryptor.getState()); testKeyDecryptor(decryptor); assertEquals(State.READY, decryptor.getState()); RawBsonDocument decryptedDocument = decryptor.finish(); assertEquals(State.DONE, decryptor.getState()); assertEquals(getResourceAsDocument("command-reply.json"), decryptedDocument); decryptor.close(); mongoCrypt.close(); } @Test public void testEmptyAwsCredentials() throws URISyntaxException, IOException { MongoCrypt mongoCrypt = MongoCrypts.create(MongoCryptOptions .builder() .kmsProviderOptions(new BsonDocument("aws", new BsonDocument())) .needsKmsCredentialsStateEnabled(true) .build()); MongoCryptContext decryptor = mongoCrypt.createDecryptionContext(getResourceAsDocument("encrypted-command-reply.json")); assertEquals(State.NEED_KMS_CREDENTIALS, decryptor.getState()); BsonDocument awsCredentials = new BsonDocument(); awsCredentials.put("accessKeyId", new BsonString("example")); awsCredentials.put("secretAccessKey", new BsonString("example")); decryptor.provideKmsProviderCredentials(new BsonDocument("aws", awsCredentials)); assertEquals(State.NEED_MONGO_KEYS, decryptor.getState()); mongoCrypt.close(); } @Test public void testMultipleCloseCalls() { MongoCrypt mongoCrypt = createMongoCrypt(); assertNotNull(mongoCrypt); mongoCrypt.close(); mongoCrypt.close(); } @Test public void testDataKeyCreation() { MongoCrypt mongoCrypt = createMongoCrypt(); assertNotNull(mongoCrypt); List keyAltNames = Arrays.asList("first", "second"); MongoCryptContext dataKeyContext = mongoCrypt.createDataKeyContext("local", MongoDataKeyOptions.builder().masterKey(new BsonDocument()) .keyAltNames(keyAltNames) .build()); assertEquals(State.READY, dataKeyContext.getState()); RawBsonDocument dataKeyDocument = dataKeyContext.finish(); assertEquals(State.DONE, dataKeyContext.getState()); assertNotNull(dataKeyDocument); List actualKeyAltNames = dataKeyDocument.getArray("keyAltNames").stream() .map(bsonValue -> bsonValue.asString().getValue()) .sorted() .collect(Collectors.toList()); assertIterableEquals(keyAltNames, actualKeyAltNames); dataKeyContext.close(); mongoCrypt.close(); } @Test public void testExplicitEncryptionDecryption() { MongoCrypt mongoCrypt = createMongoCrypt(); assertNotNull(mongoCrypt); BsonDocument documentToEncrypt = new BsonDocument("v", new BsonString("hello")); MongoExplicitEncryptOptions options = MongoExplicitEncryptOptions.builder() .keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, Base64.getDecoder().decode("YWFhYWFhYWFhYWFhYWFhYQ=="))) .algorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") .build(); MongoCryptContext encryptor = mongoCrypt.createExplicitEncryptionContext(documentToEncrypt, options); assertEquals(State.NEED_MONGO_KEYS, encryptor.getState()); testKeyDecryptor(encryptor); assertEquals(State.READY, encryptor.getState()); RawBsonDocument encryptedDocument = encryptor.finish(); assertEquals(State.DONE, encryptor.getState()); assertEquals(getResourceAsDocument("encrypted-value.json"), encryptedDocument); MongoCryptContext decryptor = mongoCrypt.createExplicitDecryptionContext(encryptedDocument); assertEquals(State.READY, decryptor.getState()); RawBsonDocument decryptedDocument = decryptor.finish(); assertEquals(State.DONE, decryptor.getState()); assertEquals(documentToEncrypt, decryptedDocument); encryptor.close(); mongoCrypt.close(); } @Test public void testExplicitExpressionEncryption() { MongoCrypt mongoCrypt = createMongoCrypt(); assertNotNull(mongoCrypt); BsonDocument valueToEncrypt = getResourceAsDocument("fle2-find-range-explicit-v2/int32/value-to-encrypt.json"); BsonDocument rangeOptions = getResourceAsDocument("fle2-find-range-explicit-v2/int32/rangeopts.json"); BsonDocument expectedEncryptedPayload = getResourceAsDocument("fle2-find-range-explicit-v2/int32/encrypted-payload.json"); MongoExplicitEncryptOptions options = MongoExplicitEncryptOptions.builder() .keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, Base64.getDecoder().decode("q83vqxI0mHYSNBI0VniQEg=="))) .algorithm("RangePreview") .queryType("rangePreview") .contentionFactor(4L) .rangeOptions(rangeOptions) .build(); MongoCryptContext encryptor = mongoCrypt.createEncryptExpressionContext(valueToEncrypt, options); assertEquals(State.NEED_MONGO_KEYS, encryptor.getState()); testKeyDecryptor(encryptor, "fle2-find-range-explicit-v2/int32/key-filter.json", "keys/ABCDEFAB123498761234123456789012-local-document.json"); assertEquals(State.READY, encryptor.getState()); RawBsonDocument actualEncryptedPayload = encryptor.finish(); assertEquals(State.DONE, encryptor.getState()); assertEquals(expectedEncryptedPayload, actualEncryptedPayload); encryptor.close(); mongoCrypt.close(); } @Test public void testExplicitEncryptionDecryptionKeyAltName() throws IOException, URISyntaxException { MongoCrypt mongoCrypt = createMongoCrypt(); assertNotNull(mongoCrypt); BsonDocument documentToEncrypt = new BsonDocument("v", new BsonString("hello")); MongoExplicitEncryptOptions options = MongoExplicitEncryptOptions.builder() .keyAltName("altKeyName") .algorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") .build(); MongoCryptContext encryptor = mongoCrypt.createExplicitEncryptionContext(documentToEncrypt, options); assertEquals(State.NEED_MONGO_KEYS, encryptor.getState()); testKeyDecryptor(encryptor, "key-filter-keyAltName.json", "key-document.json"); assertEquals(State.READY, encryptor.getState()); RawBsonDocument encryptedDocument = encryptor.finish(); assertEquals(State.DONE, encryptor.getState()); assertEquals(getResourceAsDocument("encrypted-value.json"), encryptedDocument); MongoCryptContext decryptor = mongoCrypt.createExplicitDecryptionContext(encryptedDocument); assertEquals(State.READY, decryptor.getState()); RawBsonDocument decryptedDocument = decryptor.finish(); assertEquals(State.DONE, decryptor.getState()); assertEquals(documentToEncrypt, decryptedDocument); encryptor.close(); mongoCrypt.close(); } private void testKeyDecryptor(final MongoCryptContext context) { testKeyDecryptor(context, "key-filter.json", "key-document.json"); } private void testKeyDecryptor(final MongoCryptContext context, final String keyFilterPath, final String keyDocumentPath) { BsonDocument keyFilter = context.getMongoOperation(); assertEquals(getResourceAsDocument(keyFilterPath), keyFilter); context.addMongoOperationResult(getResourceAsDocument(keyDocumentPath)); context.completeMongoOperation(); if (context.getState() == State.READY) { return; } assertEquals(State.NEED_KMS, context.getState()); MongoKeyDecryptor keyDecryptor = context.nextKeyDecryptor(); assertEquals("aws", keyDecryptor.getKmsProvider()); assertEquals("kms.us-east-1.amazonaws.com:443", keyDecryptor.getHostName()); ByteBuffer keyDecryptorMessage = keyDecryptor.getMessage(); assertEquals(790, keyDecryptorMessage.remaining()); int bytesNeeded = keyDecryptor.bytesNeeded(); assertEquals(1024, bytesNeeded); keyDecryptor.feed(getHttpResourceAsByteBuffer("kms-reply.txt")); bytesNeeded = keyDecryptor.bytesNeeded(); assertEquals(0, bytesNeeded); assertNull(context.nextKeyDecryptor()); context.completeKeyDecryptors(); } private MongoCrypt createMongoCrypt() { return MongoCrypts.create(MongoCryptOptions .builder() .awsKmsProviderOptions(MongoAwsKmsProviderOptions.builder() .accessKeyId("example") .secretAccessKey("example") .build()) .localKmsProviderOptions(MongoLocalKmsProviderOptions.builder() .localMasterKey(ByteBuffer.wrap(new byte[96])) .build()) .build()); } private static BsonDocument getResourceAsDocument(final String fileName) { return BsonDocument.parse(getFileAsString(fileName, System.getProperty("line.separator"))); } private static ByteBuffer getHttpResourceAsByteBuffer(final String fileName) { return ByteBuffer.wrap(getFileAsString(fileName, "\r\n").getBytes(StandardCharsets.UTF_8)); } private static String getFileAsString(final String fileName, String lineSeparator) { try { URL resource = MongoCryptTest.class.getResource("/" + fileName); if (resource == null) { throw new RuntimeException("Could not find file " + fileName); } File file = new File(resource.toURI()); StringBuilder stringBuilder = new StringBuilder(); String line; try (BufferedReader reader = new BufferedReader( new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8))) { boolean first = true; while ((line = reader.readLine()) != null) { if (!first) { stringBuilder.append(lineSeparator); } first = false; stringBuilder.append(line); } } return stringBuilder.toString(); } catch (Throwable t) { throw new RuntimeException("Could not parse file " + fileName, t); } } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/000077500000000000000000000000001454530651600251245ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/collection-info.json000066400000000000000000000017241454530651600311070ustar00rootroot00000000000000{ "type": "collection", "name": "test", "idIndex": { "ns": "test.test", "name": "_id_", "key": { "_id": { "$numberInt": "1" } }, "v": { "$numberInt": "2" } }, "options": { "validator": { "$jsonSchema": { "properties": { "ssn": { "encrypt": { "keyId": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "type": "string", "algorithm": "AEAD_AES_CBC_HMAC_SHA512-Deterministic" } } }, "bsonType": "object" } } } }libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/command-reply.json000066400000000000000000000002361454530651600305670ustar00rootroot00000000000000{ "cursor": { "firstBatch": [ { "_id": 1, "ssn": "457-55-5462" } ], "id": 0, "ns": "test.test" }, "ok": 1 } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/command.json000066400000000000000000000001121454530651600274270ustar00rootroot00000000000000{ "find": "test", "filter": { "ssn": "457-55-5462" } }libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/encrypted-command-reply.json000066400000000000000000000005251454530651600325630ustar00rootroot00000000000000{ "cursor" : { "firstBatch" : [ { "_id": 1, "ssn": { "$binary": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", "$type": "06" } } ], "id" : 0, "ns" : "test.test" }, "ok" : 1 }libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/encrypted-command.json000066400000000000000000000004101454530651600314230ustar00rootroot00000000000000{ "filter": { "ssn": { "$binary": { "base64": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", "subType": "06" } } }, "find": "test" } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/encrypted-value.json000066400000000000000000000002461454530651600311300ustar00rootroot00000000000000{ "v": { "$binary": "AWFhYWFhYWFhYWFhYWFhYWECW+zDjR/69eS6VtuMD5+O2lZw6JyiWOw3avI7mnUkdpKzPfvy8F/nlZrgZa2cGmQsb0TmLZuk5trldosnGKD91w==", "$type": "06" } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/000077500000000000000000000000001454530651600321305ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/000077500000000000000000000000001454530651600330675ustar00rootroot00000000000000encrypted-payload.json000066400000000000000000000024421454530651600373310ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32{ "v": { "$and": [ { "age": { "$gte": { "$binary": { "base64": "Dd0BAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAAA==", "subType": "06" } } } }, { "age": { "$lte": { "$binary": { "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", "subType": "06" } } } } ] } } key-filter.json000066400000000000000000000003631454530651600357600ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32{ "$or": [ { "_id": { "$in": [ { "$binary": "q83vqxI0mHYSNBI0VniQEg==", "$type": "04" } ] } }, { "keyAltNames": { "$in": [] } } ] }rangeopts.json000066400000000000000000000002251454530651600357040ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32{ "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" }, "sparsity": { "$numberLong": "1" } } value-to-encrypt.json000066400000000000000000000005761454530651600371310ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32{ "v": { "$and": [ { "age": { "$gte": { "$numberInt": "23" } } }, { "age": { "$lte": { "$numberInt": "35" } } } ] } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/json-schema.json000066400000000000000000000004361454530651600302310ustar00rootroot00000000000000{ "properties": { "ssn": { "encrypt": { "keyId": { "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", "$type": "04" }, "type": "string", "algorithm": "AEAD_AES_CBC_HMAC_SHA512-Deterministic" } } }, "bsonType": "object" }libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/key-document.json000066400000000000000000000020731454530651600304250ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "masterKey": { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "provider": "aws" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": [ "altKeyName", "another_altname" ] } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/key-filter-keyAltName.json000066400000000000000000000002221454530651600321160ustar00rootroot00000000000000{ "$or": [ { "_id": { "$in": [] } }, { "keyAltNames": { "$in": ["altKeyName"] } } ] } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/key-filter.json000066400000000000000000000003631454530651600300740ustar00rootroot00000000000000{ "$or": [ { "_id": { "$in": [ { "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", "$type": "04" } ] } }, { "keyAltNames": { "$in": [] } } ] }libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/keys/000077500000000000000000000000001454530651600260775ustar00rootroot00000000000000ABCDEFAB123498761234123456789012-local-document.json000066400000000000000000000013741454530651600352750ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/keys{ "_id": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "27OBvUqHAuYFy60nwCdvq2xmZ4kFzVySphXzBGq+HEot13comCoydEfnltBzLTuXLbV9cnREFJIO5f0jMqrlkxIuvAV8yO84p5VJTEa8j/xSNe7iA594rx7UeKT0fOt4VqM47fht8h+8PZYc5JVezvEMvwk115IBCwENxDjLtT0g+y8Hf+aTUEGtxrYToH8zf1/Y7S16mHiIc4jK3/vxHw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648915408923" } }, "updateDate": { "$date": { "$numberLong": "1648915408923" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/kms-reply.txt000066400000000000000000000005561454530651600276160ustar00rootroot00000000000000HTTP/1.1 200 OK x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e Content-Type: application/x-amz-json-1.1 Content-Length: 233 {"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "Plaintext": "TqhXy3tKckECjy4/ZNykMWG8amBF46isVPzeOgeusKrwheBmYaU8TMG5AHR/NeUDKukqo8hBGgogiQOVpLPkqBQHD8YkLsNbDmHoGOill5QAHnniF/Lz405bGucB5TfR"}libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/list-collections-filter.json000066400000000000000000000000241454530651600325650ustar00rootroot00000000000000{ "name": "test" }libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/mongocryptd-command.json000066400000000000000000000006461454530651600320060ustar00rootroot00000000000000{ "find": "test", "filter": { "ssn": "457-55-5462" }, "jsonSchema": { "properties": { "ssn": { "encrypt": { "keyId": { "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", "$type": "04" }, "type": "string", "algorithm": "AEAD_AES_CBC_HMAC_SHA512-Deterministic" } } }, "bsonType": "object" }, "isRemoteSchema": true }libmongocrypt-1.8.4/bindings/java/mongocrypt/src/test/resources/mongocryptd-reply.json000066400000000000000000000006541454530651600315220ustar00rootroot00000000000000{ "schemaRequiresEncryption": true, "ok": { "$numberInt": "1" }, "result": { "filter": { "ssn": { "$binary": { "base64": "ADgAAAAQYQABAAAABWtpABAAAAAEYWFhYWFhYWFhYWFhYWFhYQJ2AAwAAAA0NTctNTUtNTQ2MgAA", "subType": "06" } } }, "find": "test" }, "hasEncryptedPlaceholders": true }libmongocrypt-1.8.4/bindings/node/000077500000000000000000000000001454530651600171475ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/.clang-format000066400000000000000000000006131454530651600215220ustar00rootroot00000000000000BasedOnStyle: Google AllowShortFunctionsOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false BinPackArguments: false BinPackParameters: false ColumnLimit: 100 Cpp11BracedListStyle: true DerivePointerAlignment: false IndentWidth: 4 MaxEmptyLinesToKeep: 1 NamespaceIndentation: None SpaceBeforeAssignmentOperators: true Standard: Cpp11 UseTab: Never libmongocrypt-1.8.4/bindings/node/.eslintrc.json000066400000000000000000000032001454530651600217360ustar00rootroot00000000000000{ "root": true, "extends": [ "eslint:recommended", "plugin:prettier/recommended" ], "env": { "node": true, "mocha": true, "es6": true }, "parserOptions": { "ecmaVersion": 2019 }, "plugins": [ "prettier" ], "rules": { "no-restricted-properties": [ "error", { "object": "describe", "property": "only" }, { "object": "it", "property": "only" }, { "object": "context", "property": "only" } ], "prettier/prettier": "error", "no-console": "error", "valid-typeof": "error", "eqeqeq": ["error", "always", {"null": "ignore"}], "strict": ["error", "global"], "no-restricted-syntax": [ "error", { "selector": "TSEnumDeclaration", "message": "Do not declare enums" }, { "selector": "BinaryExpression[operator=/[=!]==/] Identifier[name='undefined']", "message": "Do not strictly check undefined" }, { "selector": "BinaryExpression[operator=/[=!]==/] Literal[raw='null']", "message": "Do not strictly check null" }, { "selector": "BinaryExpression[operator=/[=!]==?/] Literal[value='undefined']", "message": "Do not strictly check typeof undefined (NOTE: currently this rule only detects the usage of 'undefined' string literal so this could be a misfire)" } ] }, "overrides": [ { // Settings for javascript test files "files": [ "test/**/*.js" ], "rules": { "no-console": "off", "no-restricted-syntax": "off" } } ] } libmongocrypt-1.8.4/bindings/node/.evergreen/000077500000000000000000000000001454530651600212075ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/.evergreen/init-nvm.sh000066400000000000000000000006061454530651600233060ustar00rootroot00000000000000#! /usr/bin/env bash export PATH="/opt/mongodbtoolchain/v2/bin:$PATH" NODE_ARTIFACTS_PATH="${PROJECT_DIRECTORY}/node-artifacts" if [[ "$OS" == "Windows_NT" ]]; then NODE_ARTIFACTS_PATH=$(cygpath --unix "$NODE_ARTIFACTS_PATH") fi export PATH="$NODE_ARTIFACTS_PATH/npm_global/bin:$NODE_ARTIFACTS_PATH/nodejs/bin:$PATH" hash -r export NODE_OPTIONS="--trace-deprecation --trace-warnings" libmongocrypt-1.8.4/bindings/node/.evergreen/install-dependencies.sh000066400000000000000000000077231454530651600256460ustar00rootroot00000000000000#!/usr/bin/env bash set -o errexit # Exit the script with error if any of the commands fail NODE_LTS_NAME=${NODE_LTS_NAME:-fermium} NODE_ARTIFACTS_PATH="${PROJECT_DIRECTORY:-$(pwd)}/node-artifacts" if [[ "$OS" = "Windows_NT" ]]; then NODE_ARTIFACTS_PATH=$(cygpath --unix "$NODE_ARTIFACTS_PATH"); fi CURL_FLAGS=( --fail # Exit code 1 if request fails --compressed # Request a compressed response should keep fetching fast --location # Follow a redirect --retry 8 # Retry HTTP 408, 429, 500, 502, 503 or 504, 8 times --silent # Do not print a progress bar --show-error # Despite the silent flag still print out errors --max-time 900 # 900 seconds is 15 minutes, evergreen times out at 20 --continue-at - # If a download is interrupted it can figure out where to resume ) mkdir -p "$NODE_ARTIFACTS_PATH/npm_global" # Comparisons are all case insensitive shopt -s nocasematch # index.tab is a sorted tab separated values file with the following headers # 0 1 2 3 4 5 6 7 8 9 10 # version date files npm v8 uv zlib openssl modules lts security curl "${CURL_FLAGS[@]}" "https://nodejs.org/dist/index.tab" --output node_index.tab while IFS=$'\t' read -r -a row; do node_index_version="${row[0]}" node_index_date="${row[1]}" node_index_lts="${row[9]}" [[ "$node_index_version" = "version" ]] && continue # skip tsv header [[ "$NODE_LTS_NAME" = "latest" ]] && break # first line is latest [[ "$NODE_LTS_NAME" = "$node_index_lts" ]] && break # case insensitive compare done < node_index.tab if [[ "$OS" = "Windows_NT" ]]; then operating_system="win" elif [[ $(uname) = "darwin" ]]; then operating_system="darwin" elif [[ $(uname) = "linux" ]]; then operating_system="linux" else echo "Unable to determine operating system: $operating_system" exit 1 fi architecture=$(uname -m) if [[ $architecture = "x86_64" ]]; then architecture="x64" elif [[ $architecture = "arm64" ]]; then architecture="arm64" elif [[ $architecture = "aarch64" ]]; then architecture="arm64" elif [[ $architecture == s390* ]]; then architecture="s390x" elif [[ $architecture == ppc* ]]; then architecture="ppc64le" else echo "Unable to determine operating system: $architecture" exit 1 fi file_extension="tar.gz" if [[ "$OS" = "Windows_NT" ]]; then file_extension="zip"; fi node_directory="node-${node_index_version}-${operating_system}-${architecture}" node_archive="${node_directory}.${file_extension}" node_archive_path="$NODE_ARTIFACTS_PATH/${node_archive}" node_download_url="https://nodejs.org/dist/${node_index_version}/${node_archive}" echo "Node.js ${node_index_version} for ${operating_system}-${architecture} released on ${node_index_date}" set -o xtrace curl "${CURL_FLAGS[@]}" "${node_download_url}" --output "$node_archive_path" if [[ "$file_extension" = "zip" ]]; then unzip -q "$node_archive_path" -d "${NODE_ARTIFACTS_PATH}" mkdir -p "${NODE_ARTIFACTS_PATH}/nodejs" # Windows "bins" are at the top level mv "${NODE_ARTIFACTS_PATH}/${node_directory}" "${NODE_ARTIFACTS_PATH}/nodejs/bin" # Need to add executable flag ourselves chmod +x "${NODE_ARTIFACTS_PATH}/nodejs/bin/node.exe" chmod +x "${NODE_ARTIFACTS_PATH}/nodejs/bin/npm" else tar -xf "$node_archive_path" -C "${NODE_ARTIFACTS_PATH}" mv "${NODE_ARTIFACTS_PATH}/${node_directory}" "${NODE_ARTIFACTS_PATH}/nodejs" fi export PATH="$NODE_ARTIFACTS_PATH/npm_global/bin:$NODE_ARTIFACTS_PATH/nodejs/bin:$PATH" hash -r # Set npm -g prefix to our local artifacts directory cat < .npmrc prefix=$NODE_ARTIFACTS_PATH/npm_global EOT if [[ $operating_system != "win" ]]; then # Update npm to latest when we can npm install --global npm@latest hash -r fi echo "npm version: $(npm -v)" # other repos that use this script run npm install after installing Node. # we can't in mongodb-client-encryption, because when releasing # npm install will attempt to build from source, which fails # because we haven't built libmongocrypt yet. # npm install "${NPM_OPTIONS}" libmongocrypt-1.8.4/bindings/node/.evergreen/prebuild.sh000077500000000000000000000054241454530651600233610ustar00rootroot00000000000000#!/usr/bin/env bash if [ -z ${DISTRO_ID+omitted} ]; then echo "DISTRO_ID is unset" && exit 1; fi set -o errexit set +o xtrace # FLE platform matrix (as of Feb 8th 2022) # macos arm64 (compiled on 11.00) # macos x86_64 (compiled on 10.14) # windows x86_64 (compiled on vs2017) # linux x86_64 (releases on RHEL7) # linux s390x # linux arm64 # Determines the OS name through uname results # Returns 'windows' 'linux' 'macos' or 'unknown' os_name() { local WINDOWS_REGEX="cygwin|windows|mingw|msys" local UNAME UNAME=$(uname | tr '[:upper:]' '[:lower:]') local OS_NAME="unknown" if [[ $UNAME =~ $WINDOWS_REGEX ]]; then OS_NAME="windows" elif [[ $UNAME == "darwin" ]]; then OS_NAME="macos" elif [[ $UNAME == "linux" ]]; then OS_NAME="linux" fi echo $OS_NAME } OS=$(os_name) get_version_at_git_rev () { local REV=$1 local VERSION VERSION=$(node -r child_process -e "console.log(JSON.parse(child_process.execSync('git show $REV:./package.json', { encoding: 'utf8' })).version);") echo "$VERSION" } run_prebuild() { if [ -z ${NODE_GITHUB_TOKEN+omitted} ]; then echo "NODE_GITHUB_TOKEN is unset" && exit 1; fi echo "Github token detected. Running prebuild." npm run prebuild -- -u "$NODE_GITHUB_TOKEN" echo "Prebuild's successfully submitted" } VERSION_AT_HEAD=$(get_version_at_git_rev "HEAD") VERSION_AT_HEAD_1=$(get_version_at_git_rev "HEAD~1") if [[ "$OS" == "macos" ]]; then ARCH=$(uname -m) if [[ "$ARCH" == "arm64" ]]; then # TODO(NODE-5174): node-gyp fails to run prebuild if Python 3.11+ echo "Exporting PYTHON location for version $(/opt/homebrew/opt/python@3.9/bin/python3.9 --version)" export PYTHON="/opt/homebrew/opt/python@3.9/bin/python3.9" fi fi if [[ -n $NODE_FORCE_PUBLISH ]]; then echo "\$NODE_FORCE_PUBLISH=${NODE_FORCE_PUBLISH} detected" echo "Beginning prebuild" run_prebuild elif [[ "$VERSION_AT_HEAD" != "$VERSION_AT_HEAD_1" ]]; then echo "Difference is package version ($VERSION_AT_HEAD_1 -> $VERSION_AT_HEAD)" echo "Beginning prebuild" if [[ "$OS" == "linux" ]]; then # Handle limiting which linux gets to publish prebuild ARCH=$(uname -m) if [[ $DISTRO_ID == "rhel70-small" ]]; then # only publish x86_64 linux prebuilds from RHEL 7 run_prebuild elif [[ "$ARCH" != "x86_64" ]]; then # Non-x86 linux variants should just publish run_prebuild else # Non RHEL 7 linux variants should just test the prebuild task echo "Will prebuild without submit ($OS - $ARCH - $DISTRO_ID)" npm run prebuild fi exit 0 fi # Windows and MacOS run_prebuild else echo "No difference is package version ($VERSION_AT_HEAD_1 -> $VERSION_AT_HEAD)" echo "Will prebuild without submit ($OS - $DISTRO_ID)" npm run prebuild echo "Local prebuild successful." fi libmongocrypt-1.8.4/bindings/node/.evergreen/test.sh000077500000000000000000000016061454530651600225300ustar00rootroot00000000000000#!/usr/bin/env bash # set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail echo "Setting up environment" export PATH="/opt/mongodbtoolchain/v2/bin:$PATH" hash -r export NODE_LTS_NAME="gallium" source ./.evergreen/install-dependencies.sh # Handle the circular dependency when testing with a real client. MONGODB_CLIENT_ENCRYPTION_OVERRIDE="$(pwd)" export MONGODB_CLIENT_ENCRYPTION_OVERRIDE # install node dependencies echo "Installing package dependencies (includes a static build)" bash ./etc/build-static.sh if [[ $OMIT_PEER_DEPS != "true" ]]; then npm install '@aws-sdk/credential-providers' npm install 'gcp-metadata' fi # Run tests echo "Running tests" npm run check:lint MONGODB_NODE_SKIP_LIVE_TESTS=true npm test # Run prebuild and deploy echo "Running prebuild and deploy" bash ./.evergreen/prebuild.sh libmongocrypt-1.8.4/bindings/node/.gitignore000066400000000000000000000002171454530651600211370ustar00rootroot00000000000000lib-cov *.seed *.log *.csv *.dat *.out *.pid *.gz .DS_Store pids logs results node_modules build npm-debug.log .vscode deps *.tgz xunit.xml libmongocrypt-1.8.4/bindings/node/.mocharc.json000066400000000000000000000004201454530651600215300ustar00rootroot00000000000000{ "$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/mocharc.json", "require": [ "test/tools/chai-addons.js" ], "recursive": true, "failZero": true, "reporter": "test/tools/mongodb_reporter.js", "color": true } libmongocrypt-1.8.4/bindings/node/.prettierrc.json000066400000000000000000000001771454530651600223100ustar00rootroot00000000000000{ "singleQuote": true, "tabWidth": 2, "printWidth": 100, "arrowParens": "avoid", "trailingComma": "none" } libmongocrypt-1.8.4/bindings/node/CHANGELOG.md000066400000000000000000000123741454530651600207670ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. ## [2.8.0-alpha.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.8.0-alpha.0...node-v2.8.0-alpha.1) (2023-04-27) ## [2.8.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.7.1...node-v2.8.0-alpha.0) (2023-04-04) ### [2.7.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.7.0...node-v2.7.1) (2023-03-20) ## [2.7.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.7.0-alpha.0...node-v2.7.0) (2023-03-20) ## [2.7.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.6.0...node-v2.7.0-alpha.0) (2023-03-14) ## [2.6.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.6.0-alpha.0...node-v2.6.0) (2023-02-23) ## [2.6.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.5.0...node-v2.6.0-alpha.0) (2023-02-16) ## [2.5.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0...node-v2.5.0) (2023-02-06) ## [2.4.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0-alpha.2...node-v2.4.0) (2023-01-26) ## [2.4.0-alpha.2](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0-alpha.0...node-v2.4.0-alpha.2) (2023-01-24) ## [2.4.0-alpha.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0-alpha.0...node-v2.4.0-alpha.1) (2023-01-23) ## [2.4.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.3.0...node-v2.4.0-alpha.0) (2023-01-20) ## [2.3.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.1...node-v2.3.0) (2022-10-05) ### [2.2.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0...node-v2.2.1) (2022-09-12) ## [2.2.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.6...node-v2.2.0) (2022-08-10) ## [2.2.0-alpha.6](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.5...node-v2.2.0-alpha.6) (2022-07-29) ## [2.2.0-alpha.6](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.5...node-v2.2.0-alpha.6) (2022-07-29) ## [2.2.0-alpha.5](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.4...node-v2.2.0-alpha.5) (2022-07-20) ## [2.2.0-alpha.5](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.4...node-v2.2.0-alpha.5) (2022-07-20) ## [2.2.0-alpha.4](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.3...node-v2.2.0-alpha.4) (2022-07-06) ## [2.2.0-alpha.3](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.2...node-v2.2.0-alpha.3) (2022-06-23) ## [2.2.0-alpha.2](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.1...node-v2.2.0-alpha.2) (2022-06-10) ## [2.2.0-alpha.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.0...node-v2.2.0-alpha.1) (2022-06-01) ## [2.2.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.1.0...node-v2.2.0-alpha.0) (2022-05-04) ## [2.1.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0...node-v2.1.0) (2022-04-21) ## [2.0.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.4...node-v2.0.0) (2022-02-17) ## [2.0.0-beta.4](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.3...node-v2.0.0-beta.4) (2022-02-09) ## [2.0.0-beta.3](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.0...node-v2.0.0-beta.3) (2022-01-31) ## [2.0.0-beta.2](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.0...node-v2.0.0-beta.2) (2021-12-22) ## [2.0.0-beta.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.0...node-v2.0.0-beta.1) (2021-12-21) ## [2.0.0-beta.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.7...node-v2.0.0-beta.0) (2021-10-07) ### [1.2.7](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.6...node-v1.2.7) (2021-09-14) ### [1.2.6](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.5...node-v1.2.6) (2021-07-01) ### [1.2.5](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.4...node-v1.2.5) (2021-06-10) ### [1.2.4](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.3...node-v1.2.4) (2021-06-01) ### [1.2.3](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.2...node-v1.2.3) (2021-04-06) ### [1.2.2](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.1...node-v1.2.2) (2021-03-16) ### [1.2.1](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.0...node-v1.2.1) (2021-02-05) ## [1.2.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.1.0...node-v1.2.0) (2021-02-02) ### [1.1.1-beta.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.1.0...node-v1.1.1-beta.0) (2020-12-04) # [1.1.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.1...node-v1.1.0) (2020-06-23) ## [1.0.1](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0...1.0.1) (2019-12-31) # [1.0.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc3.0...1.0.0) (2019-12-10) # [1.0.0-rc3.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc2.0...1.0.0-rc3.0) (2019-12-04) # [1.0.0-rc2.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc1.0...1.0.0-rc2.0) (2019-12-04) # [1.0.0-rc1.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc0...1.0.0-rc1.0) (2019-12-04) libmongocrypt-1.8.4/bindings/node/LICENSE000066400000000000000000000261351454530651600201630ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. libmongocrypt-1.8.4/bindings/node/README.md000066400000000000000000001123711454530651600204330ustar00rootroot00000000000000MongoDB Client Encryption ========================= The Node.js wrapper for [`libmongocrypt`](../../README.md) ### Installation You can install `mongodb-client-encryption` with the following: ```bash npm install mongodb-client-encryption ``` ### Development #### Setup Run the following command to build libmongocrypt and setup the node bindings for development: ```shell bash ./etc/build-static.sh ``` #### Testing Some tests require a standalone server to be running with authentication enabled. Set up a single server running with the following conditions: | param | value | |-----------|-----------| | host | localhost | | port | 27017 | This is the standard setup for a standalone server with no authentication. Run the test suite using: ```bash npm test ``` # Documentation ## Classes
AutoEncrypter

An internal class to be used by the driver for auto encryption NOTE: Not meant to be instantiated directly, this is for internal use only.

ClientEncryption

The public interface for explicit in-use encryption

MongoCryptError

An error indicating that something went wrong specifically with MongoDB Client Encryption

MongoCryptCreateDataKeyError

An error indicating that ClientEncryption.createEncryptedCollection() failed to create data keys

MongoCryptCreateEncryptedCollectionError

An error indicating that ClientEncryption.createEncryptedCollection() failed to create a collection

MongoCryptAzureKMSRequestError

An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials.

## Typedefs
BSONValue : *

any serializable BSON value

Long : BSON.Long

A 64 bit integer, represented by the js-bson Long type.

KMSProviders : object

Configuration options that are used by specific KMS providers during key generation, encryption, and decryption.

DataKey : object

A data key as stored in the database.

KmsProvider : string

A string containing the name of a kms provider. Valid options are 'aws', 'azure', 'gcp', 'kmip', or 'local'

ClientSession : object

The ClientSession class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/ClientSession.html)

DeleteResult : object

The result of a delete operation from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/interfaces/DeleteResult.html)

BulkWriteResult : object

The BulkWriteResult class from the MongoDB Node driver (https://mongodb.github.io/node-mongodb-native/4.8/classes/BulkWriteResult.html)

FindCursor : object

The FindCursor class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/FindCursor.html)

ClientEncryptionDataKeyId : Binary

The id of an existing dataKey. Is a bson Binary value. Can be used for ClientEncryption.encrypt, and can be used to directly query for the data key itself against the key vault namespace.

ClientEncryptionCreateDataKeyCallback : function
AWSEncryptionKeyOptions : object

Configuration options for making an AWS encryption key

GCPEncryptionKeyOptions : object

Configuration options for making a GCP encryption key

AzureEncryptionKeyOptions : object

Configuration options for making an Azure encryption key

RewrapManyDataKeyResult : object
ClientEncryptionEncryptCallback : function
RangeOptions : object

min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. For double and decimal128, min/max/precision must all be set, or all be unset.

EncryptOptions : object

Options to provide when encrypting data.

## AutoEncrypter An internal class to be used by the driver for auto encryption **NOTE**: Not meant to be instantiated directly, this is for internal use only. * [AutoEncrypter](#AutoEncrypter) * [new AutoEncrypter(client, [options])](#new_AutoEncrypter_new) * _instance_ * [.cryptSharedLibVersionInfo](#AutoEncrypter+cryptSharedLibVersionInfo) * [.askForKMSCredentials()](#AutoEncrypter+askForKMSCredentials) * _inner_ * [~logLevel](#AutoEncrypter..logLevel) * [~AutoEncryptionOptions](#AutoEncrypter..AutoEncryptionOptions) * [~AutoEncryptionExtraOptions](#AutoEncrypter..AutoEncryptionExtraOptions) * [~logger](#AutoEncrypter..logger) ### new AutoEncrypter(client, [options]) | Param | Type | Description | | --- | --- | --- | | client | MongoClient | The client autoEncryption is enabled on | | [options] | [AutoEncryptionOptions](#AutoEncrypter..AutoEncryptionOptions) | Optional settings | Create an AutoEncrypter **Note**: Do not instantiate this class directly. Rather, supply the relevant options to a MongoClient **Note**: Supplying `options.schemaMap` provides more security than relying on JSON Schemas obtained from the server. It protects against a malicious server advertising a false JSON Schema, which could trick the client into sending unencrypted data that should be encrypted. Schemas supplied in the schemaMap only apply to configuring automatic encryption for Client-Side Field Level Encryption. Other validation rules in the JSON schema will not be enforced by the driver and will result in an error. **Example** ```js // Enabling autoEncryption via a MongoClient const { MongoClient } = require('mongodb'); const client = new MongoClient(URL, { autoEncryption: { kmsProviders: { aws: { accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY } } } }); await client.connect(); // From here on, the client will be encrypting / decrypting automatically ``` ### *autoEncrypter*.cryptSharedLibVersionInfo Return the current libmongocrypt's CSFLE shared library version as `{ version: bigint, versionStr: string }`, or `null` if no CSFLE shared library was loaded. ### *autoEncrypter*.askForKMSCredentials() Ask the user for KMS credentials. This returns anything that looks like the kmsProviders original input option. It can be empty, and any provider specified here will override the original ones. ### *AutoEncrypter*~logLevel The level of severity of the log message | Value | Level | |-------|-------| | 0 | Fatal Error | | 1 | Error | | 2 | Warning | | 3 | Info | | 4 | Trace | ### *AutoEncrypter*~AutoEncryptionOptions **Properties** | Name | Type | Description | | --- | --- | --- | | [keyVaultClient] | MongoClient | A `MongoClient` used to fetch keys from a key vault | | [keyVaultNamespace] | string | The namespace where keys are stored in the key vault | | [kmsProviders] | [KMSProviders](#KMSProviders) | Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. | | [schemaMap] | object | A map of namespaces to a local JSON schema for encryption | | [bypassAutoEncryption] | boolean | Allows the user to bypass auto encryption, maintaining implicit decryption | | [options.logger] | [logger](#AutoEncrypter..logger) | An optional hook to catch logging messages from the underlying encryption engine | | [extraOptions] | [AutoEncryptionExtraOptions](#AutoEncrypter..AutoEncryptionExtraOptions) | Extra options related to the mongocryptd process | Configuration options for a automatic client encryption. ### *AutoEncrypter*~AutoEncryptionExtraOptions **Properties** | Name | Type | Default | Description | | --- | --- | --- | --- | | [mongocryptdURI] | string | | A local process the driver communicates with to determine how to encrypt values in a command. Defaults to "mongodb://%2Fvar%2Fmongocryptd.sock" if domain sockets are available or "mongodb://localhost:27020" otherwise | | [mongocryptdBypassSpawn] | boolean | false | If true, autoEncryption will not attempt to spawn a mongocryptd before connecting | | [mongocryptdSpawnPath] | string | | The path to the mongocryptd executable on the system | | [mongocryptdSpawnArgs] | Array.<string> | | Command line arguments to use when auto-spawning a mongocryptd | Extra options related to the mongocryptd process ### *AutoEncrypter*~logger | Param | Type | Description | | --- | --- | --- | | level | [logLevel](#AutoEncrypter..logLevel) | The level of logging. | | message | string | The message to log | A callback that is invoked with logging information from the underlying C++ Bindings. ## ClientEncryption The public interface for explicit in-use encryption * [ClientEncryption](#ClientEncryption) * [new ClientEncryption(client, options)](#new_ClientEncryption_new) * _instance_ * [.createDataKey(provider, [options], [callback])](#ClientEncryption+createDataKey) * [.rewrapManyDataKey(filter, [options])](#ClientEncryption+rewrapManyDataKey) * [.deleteKey(_id)](#ClientEncryption+deleteKey) * [.getKeys()](#ClientEncryption+getKeys) * [.getKey(_id)](#ClientEncryption+getKey) * [.getKeyByAltName(keyAltName)](#ClientEncryption+getKeyByAltName) * [.addKeyAltName(_id, keyAltName)](#ClientEncryption+addKeyAltName) * [.removeKeyAltName(_id, keyAltName)](#ClientEncryption+removeKeyAltName) * [.createEncryptedCollection(db, name, options)](#ClientEncryption+createEncryptedCollection) * [.encrypt(value, options, [callback])](#ClientEncryption+encrypt) * [.encryptExpression(expression, options)](#ClientEncryption+encryptExpression) * [.decrypt(value, callback)](#ClientEncryption+decrypt) * [.askForKMSCredentials()](#ClientEncryption+askForKMSCredentials) * _inner_ * [~decryptCallback](#ClientEncryption..decryptCallback) ### new ClientEncryption(client, options) | Param | Type | Description | | --- | --- | --- | | client | MongoClient | The client used for encryption | | options | object | Additional settings | | options.keyVaultNamespace | string | The namespace of the key vault, used to store encryption keys | | options.tlsOptions | object | An object that maps KMS provider names to TLS options. | | [options.keyVaultClient] | MongoClient | A `MongoClient` used to fetch keys from a key vault. Defaults to `client` | | [options.kmsProviders] | [KMSProviders](#KMSProviders) | options for specific KMS providers to use | Create a new encryption instance **Example** ```js new ClientEncryption(mongoClient, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: masterKey // The master key used for encryption/decryption. A 96-byte long Buffer } } }); ``` **Example** ```js new ClientEncryption(mongoClient, { keyVaultNamespace: 'client.encryption', kmsProviders: { aws: { accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY } } }); ``` ### *clientEncryption*.createDataKey(provider, [options], [callback]) | Param | Type | Description | | --- | --- | --- | | provider | string | The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` | | [options] | object | Options for creating the data key | | [options.masterKey] | [AWSEncryptionKeyOptions](#AWSEncryptionKeyOptions) \| [AzureEncryptionKeyOptions](#AzureEncryptionKeyOptions) \| [GCPEncryptionKeyOptions](#GCPEncryptionKeyOptions) | Idenfities a new KMS-specific key used to encrypt the new data key | | [options.keyAltNames] | Array.<string> | An optional list of string alternate names used to reference a key. If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by _id. | | [callback] | [ClientEncryptionCreateDataKeyCallback](#ClientEncryptionCreateDataKeyCallback) | Optional callback to invoke when key is created | Creates a data key used for explicit encryption and inserts it into the key vault namespace **Returns**: Promise \| void - If no callback is provided, returns a Promise that either resolves with [the id of the created data key](ClientEncryption~dataKeyId), or rejects with an error. If a callback is provided, returns nothing. **Example** ```js // Using callbacks to create a local key clientEncryption.createDataKey('local', (err, dataKey) => { if (err) { // This means creating the key failed. } else { // key creation succeeded } }); ``` **Example** ```js // Using async/await to create a local key const dataKeyId = await clientEncryption.createDataKey('local'); ``` **Example** ```js // Using async/await to create an aws key const dataKeyId = await clientEncryption.createDataKey('aws', { masterKey: { region: 'us-east-1', key: 'xxxxxxxxxxxxxx' // CMK ARN here } }); ``` **Example** ```js // Using async/await to create an aws key with a keyAltName const dataKeyId = await clientEncryption.createDataKey('aws', { masterKey: { region: 'us-east-1', key: 'xxxxxxxxxxxxxx' // CMK ARN here }, keyAltNames: [ 'mySpecialKey' ] }); ``` ### *clientEncryption*.rewrapManyDataKey(filter, [options]) | Param | Type | Description | | --- | --- | --- | | filter | object | A valid MongoDB filter. Any documents matching this filter will be re-wrapped. | | [options] | object | | | options.provider | [KmsProvider](#KmsProvider) | The KMS provider to use when re-wrapping the data keys. | | [options.masterKey] | [AWSEncryptionKeyOptions](#AWSEncryptionKeyOptions) \| [AzureEncryptionKeyOptions](#AzureEncryptionKeyOptions) \| [GCPEncryptionKeyOptions](#GCPEncryptionKeyOptions) | | Searches the keyvault for any data keys matching the provided filter. If there are matches, rewrapManyDataKey then attempts to re-wrap the data keys using the provided options. If no matches are found, then no bulk write is performed. **Example** ```js // rewrapping all data data keys (using a filter that matches all documents) const filter = {}; const result = await clientEncryption.rewrapManyDataKey(filter); if (result.bulkWriteResult != null) { // keys were re-wrapped, results will be available in the bulkWrite object. } ``` **Example** ```js // attempting to rewrap all data keys with no matches const filter = { _id: new Binary() } // assume _id matches no documents in the database const result = await clientEncryption.rewrapManyDataKey(filter); if (result.bulkWriteResult == null) { // no keys matched, `bulkWriteResult` does not exist on the result object } ``` ### *clientEncryption*.deleteKey(_id) | Param | Type | Description | | --- | --- | --- | | _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | the id of the document to delete. | Deletes the key with the provided id from the keyvault, if it exists. **Returns**: [Promise.<DeleteResult>](#DeleteResult) - Returns a promise that either resolves to a [DeleteResult](#DeleteResult) or rejects with an error. **Example** ```js // delete a key by _id const id = new Binary(); // id is a bson binary subtype 4 object const { deletedCount } = await clientEncryption.deleteKey(id); if (deletedCount != null && deletedCount > 0) { // successful deletion } ``` ### *clientEncryption*.getKeys() Finds all the keys currently stored in the keyvault. This method will not throw. **Returns**: [FindCursor](#FindCursor) - a FindCursor over all keys in the keyvault. **Example** ```js // fetching all keys const keys = await clientEncryption.getKeys().toArray(); ``` ### *clientEncryption*.getKey(_id) | Param | Type | Description | | --- | --- | --- | | _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | the id of the document to delete. | Finds a key in the keyvault with the specified _id. **Returns**: [Promise.<DataKey>](#DataKey) - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents match the id. The promise rejects with an error if an error is thrown. **Example** ```js // getting a key by id const id = new Binary(); // id is a bson binary subtype 4 object const key = await clientEncryption.getKey(id); if (!key) { // key is null if there was no matching key } ``` ### *clientEncryption*.getKeyByAltName(keyAltName) | Param | Type | Description | | --- | --- | --- | | keyAltName | string | a keyAltName to search for a key | Finds a key in the keyvault which has the specified keyAltName. **Returns**: Promise.<(DataKey\|null)> - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents match the keyAltName. The promise rejects with an error if an error is thrown. **Example** ```js // get a key by alt name const keyAltName = 'keyAltName'; const key = await clientEncryption.getKeyByAltName(keyAltName); if (!key) { // key is null if there is no matching key } ``` ### *clientEncryption*.addKeyAltName(_id, keyAltName) | Param | Type | Description | | --- | --- | --- | | _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | The id of the document to update. | | keyAltName | string | a keyAltName to search for a key | Adds a keyAltName to a key identified by the provided _id. This method resolves to/returns the *old* key value (prior to adding the new altKeyName). **Returns**: [Promise.<DataKey>](#DataKey) - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents match the id. The promise rejects with an error if an error is thrown. **Example** ```js // adding an keyAltName to a data key const id = new Binary(); // id is a bson binary subtype 4 object const keyAltName = 'keyAltName'; const oldKey = await clientEncryption.addKeyAltName(id, keyAltName); if (!oldKey) { // null is returned if there is no matching document with an id matching the supplied id } ``` ### *clientEncryption*.removeKeyAltName(_id, keyAltName) | Param | Type | Description | | --- | --- | --- | | _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | The id of the document to update. | | keyAltName | string | a keyAltName to search for a key | Adds a keyAltName to a key identified by the provided _id. This method resolves to/returns the *old* key value (prior to removing the new altKeyName). If the removed keyAltName is the last keyAltName for that key, the `altKeyNames` property is unset from the document. **Returns**: Promise.<(DataKey\|null)> - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents match the id. The promise rejects with an error if an error is thrown. **Example** ```js // removing a key alt name from a data key const id = new Binary(); // id is a bson binary subtype 4 object const keyAltName = 'keyAltName'; const oldKey = await clientEncryption.removeKeyAltName(id, keyAltName); if (!oldKey) { // null is returned if there is no matching document with an id matching the supplied id } ``` ### *clientEncryption*.createEncryptedCollection(db, name, options) **Throws**: - [MongoCryptCreateDataKeyError](#MongoCryptCreateDataKeyError) - If part way through the process a createDataKey invocation fails, an error will be rejected that has the partial `encryptedFields` that were created. - [MongoCryptCreateEncryptedCollectionError](#MongoCryptCreateEncryptedCollectionError) - If creating the collection fails, an error will be rejected that has the entire `encryptedFields` that were created. **Experimental**: Public Technical Preview A convenience method for creating an encrypted collection. This method will create data keys for any encryptedFields that do not have a `keyId` defined and then create a new collection with the full set of encryptedFields. | Param | Type | Description | | --- | --- | --- | | db | Db | A Node.js driver Db object with which to create the collection | | name | string | The name of the collection to be created | | options | object | Options for createDataKey and for createCollection | | options.provider | string | KMS provider name | | [options.masterKey] | [AWSEncryptionKeyOptions](#AWSEncryptionKeyOptions) \| [AzureEncryptionKeyOptions](#AzureEncryptionKeyOptions) \| [GCPEncryptionKeyOptions](#GCPEncryptionKeyOptions) | masterKey to pass to createDataKey | | options.createCollectionOptions | CreateCollectionOptions | options to pass to createCollection, must include `encryptedFields` | **Returns**: Promise.<{collection: Collection.<TSchema>, encryptedFields: Document}> - - created collection and generated encryptedFields ### *clientEncryption*.encrypt(value, options, [callback]) | Param | Type | Description | | --- | --- | --- | | value | \* | The value that you wish to serialize. Must be of a type that can be serialized into BSON | | options | [EncryptOptions](#EncryptOptions) | | | [callback] | [ClientEncryptionEncryptCallback](#ClientEncryptionEncryptCallback) | Optional callback to invoke when value is encrypted | Explicitly encrypt a provided value. Note that either `options.keyId` or `options.keyAltName` must be specified. Specifying both `options.keyId` and `options.keyAltName` is considered an error. **Returns**: Promise \| void - If no callback is provided, returns a Promise that either resolves with the encrypted value, or rejects with an error. If a callback is provided, returns nothing. **Example** ```js // Encryption with callback API function encryptMyData(value, callback) { clientEncryption.createDataKey('local', (err, keyId) => { if (err) { return callback(err); } clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }, callback); }); } ``` **Example** ```js // Encryption with async/await api async function encryptMyData(value) { const keyId = await clientEncryption.createDataKey('local'); return clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); } ``` **Example** ```js // Encryption using a keyAltName async function encryptMyData(value) { await clientEncryption.createDataKey('local', { keyAltNames: 'mySpecialKey' }); return clientEncryption.encrypt(value, { keyAltName: 'mySpecialKey', algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); } ``` ### *clientEncryption*.encryptExpression(expression, options) **Experimental**: The Range algorithm is experimental only. It is not intended for production use. It is subject to breaking changes. | Param | Type | Description | | --- | --- | --- | | expression | object | a BSON document of one of the following forms: 1. A Match Expression of this form: `{$and: [{: {$gt: }}, {: {$lt: }}]}` 2. An Aggregate Expression of this form: `{$and: [{$gt: [, ]}, {$lt: [, ]}]}` `$gt` may also be `$gte`. `$lt` may also be `$lte`. | | options | [EncryptOptions](#EncryptOptions) | | Encrypts a Match Expression or Aggregate Expression to query a range index. Only supported when queryType is "rangePreview" and algorithm is "RangePreview". **Returns**: Promise.<object> - Returns a Promise that either resolves with the encrypted value or rejects with an error. ### *clientEncryption*.decrypt(value, callback) | Param | Type | Description | | --- | --- | --- | | value | Buffer \| Binary | An encrypted value | | callback | [decryptCallback](#ClientEncryption..decryptCallback) | Optional callback to invoke when value is decrypted | Explicitly decrypt a provided encrypted value **Returns**: Promise \| void - If no callback is provided, returns a Promise that either resolves with the decrypted value, or rejects with an error. If a callback is provided, returns nothing. **Example** ```js // Decrypting value with callback API function decryptMyValue(value, callback) { clientEncryption.decrypt(value, callback); } ``` **Example** ```js // Decrypting value with async/await API async function decryptMyValue(value) { return clientEncryption.decrypt(value); } ``` ### *clientEncryption*.askForKMSCredentials() Ask the user for KMS credentials. This returns anything that looks like the kmsProviders original input option. It can be empty, and any provider specified here will override the original ones. ### *ClientEncryption*~decryptCallback | Param | Type | Description | | --- | --- | --- | | [err] | Error | If present, indicates an error that occurred in the process of decryption | | [result] | object | If present, is the decrypted result | ## MongoCryptError An error indicating that something went wrong specifically with MongoDB Client Encryption ## MongoCryptCreateDataKeyError **Experimental**: Public Technical Preview An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create data keys ## MongoCryptCreateEncryptedCollectionError **Experimental**: Public Technical Preview An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create a collection ## MongoCryptAzureKMSRequestError An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials. ### new MongoCryptAzureKMSRequestError(message, body) | Param | Type | | --- | --- | | message | string | | body | object \| undefined | ## BSONValue any serializable BSON value ## Long A 64 bit integer, represented by the js-bson Long type. ## KMSProviders **Properties** | Name | Type | Description | | --- | --- | --- | | [aws] | object | Configuration options for using 'aws' as your KMS provider | | [aws.accessKeyId] | string | The access key used for the AWS KMS provider | | [aws.secretAccessKey] | string | The secret access key used for the AWS KMS provider | | [local] | object | Configuration options for using 'local' as your KMS provider | | [local.key] | Buffer | The master key used to encrypt/decrypt data keys. A 96-byte long Buffer. | | [azure] | object | Configuration options for using 'azure' as your KMS provider | | [azure.tenantId] | string | The tenant ID identifies the organization for the account | | [azure.clientId] | string | The client ID to authenticate a registered application | | [azure.clientSecret] | string | The client secret to authenticate a registered application | | [azure.identityPlatformEndpoint] | string | If present, a host with optional port. E.g. "example.com" or "example.com:443". This is optional, and only needed if customer is using a non-commercial Azure instance (e.g. a government or China account, which use different URLs). Defaults to "login.microsoftonline.com" | | [gcp] | object | Configuration options for using 'gcp' as your KMS provider | | [gcp.email] | string | The service account email to authenticate | | [gcp.privateKey] | string \| Binary | A PKCS#8 encrypted key. This can either be a base64 string or a binary representation | | [gcp.endpoint] | string | If present, a host with optional port. E.g. "example.com" or "example.com:443". Defaults to "oauth2.googleapis.com" | Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. ## DataKey **Properties** | Name | Type | Description | | --- | --- | --- | | _id | UUID | A unique identifier for the key. | | version | number | A numeric identifier for the schema version of this document. Implicitly 0 if unset. | | [keyAltNames] | Array.<string> | Alternate names to search for keys by. Used for a per-document key scenario in support of GDPR scenarios. | | keyMaterial | Binary | Encrypted data key material, BinData type General. | | creationDate | Date | The datetime the wrapped data key material was imported into the Key Database. | | updateDate | Date | The datetime the wrapped data key material was last modified. On initial import, this value will be set to creationDate. | | status | number | 0 = enabled, 1 = disabled | | masterKey | object | the encrypted master key | A data key as stored in the database. ## KmsProvider A string containing the name of a kms provider. Valid options are 'aws', 'azure', 'gcp', 'kmip', or 'local' ## ClientSession The ClientSession class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/ClientSession.html) ## DeleteResult **Properties** | Name | Type | Description | | --- | --- | --- | | acknowledged | boolean | Indicates whether this write result was acknowledged. If not, then all other members of this result will be undefined. | | deletedCount | number | The number of documents that were deleted | The result of a delete operation from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/interfaces/DeleteResult.html) ## BulkWriteResult The BulkWriteResult class from the MongoDB Node driver (https://mongodb.github.io/node-mongodb-native/4.8/classes/BulkWriteResult.html) ## FindCursor The FindCursor class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/FindCursor.html) ## ClientEncryptionDataKeyId The id of an existing dataKey. Is a bson Binary value. Can be used for [ClientEncryption.encrypt](ClientEncryption.encrypt), and can be used to directly query for the data key itself against the key vault namespace. ## ClientEncryptionCreateDataKeyCallback | Param | Type | Description | | --- | --- | --- | | [error] | Error | If present, indicates an error that occurred in the creation of the data key | | [dataKeyId] | ClientEncryption~dataKeyId | If present, returns the id of the created data key | ## AWSEncryptionKeyOptions **Properties** | Name | Type | Description | | --- | --- | --- | | region | string | The AWS region of the KMS | | key | string | The Amazon Resource Name (ARN) to the AWS customer master key (CMK) | | [endpoint] | string | An alternate host to send KMS requests to. May include port number | Configuration options for making an AWS encryption key ## GCPEncryptionKeyOptions **Properties** | Name | Type | Description | | --- | --- | --- | | projectId | string | GCP project id | | location | string | Location name (e.g. "global") | | keyRing | string | Key ring name | | keyName | string | Key name | | [keyVersion] | string | Key version | | [endpoint] | string | KMS URL, defaults to `https://www.googleapis.com/auth/cloudkms` | Configuration options for making a GCP encryption key ## AzureEncryptionKeyOptions **Properties** | Name | Type | Description | | --- | --- | --- | | keyName | string | Key name | | keyVaultEndpoint | string | Key vault URL, typically `.vault.azure.net` | | [keyVersion] | string | Key version | Configuration options for making an Azure encryption key ## RewrapManyDataKeyResult **Properties** | Name | Type | Description | | --- | --- | --- | | [bulkWriteResult] | [BulkWriteResult](#BulkWriteResult) | An optional BulkWriteResult, if any keys were matched and attempted to be re-wrapped. | ## ClientEncryptionEncryptCallback | Param | Type | Description | | --- | --- | --- | | [err] | Error | If present, indicates an error that occurred in the process of encryption | | [result] | Buffer | If present, is the encrypted result | ## RangeOptions **Properties** | Name | Type | Description | | --- | --- | --- | | min | [BSONValue](#BSONValue) | is required if precision is set. | | max | [BSONValue](#BSONValue) | is required if precision is set. | | sparsity | BSON.Long | | | precision | number \| undefined | (may only be set for double or decimal128). | min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. For double and decimal128, min/max/precision must all be set, or all be unset. ## EncryptOptions **Properties** | Name | Type | Description | | --- | --- | --- | | [keyId] | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | The id of the Binary dataKey to use for encryption. | | [keyAltName] | string | A unique string name corresponding to an already existing dataKey. | | [algorithm] | string | The algorithm to use for encryption. Must be either `'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'`, `'AEAD_AES_256_CBC_HMAC_SHA_512-Random'`, `'Indexed'` or `'Unindexed'` | | [contentionFactor] | bigint \| number | (experimental) - the contention factor. | | queryType | 'equality' \| 'rangePreview' | (experimental) - the query type supported. | | [rangeOptions] | [RangeOptions](#RangeOptions) | (experimental) The index options for a Queryable Encryption field supporting "rangePreview" queries. | Options to provide when encrypting data. libmongocrypt-1.8.4/bindings/node/binding.gyp000066400000000000000000000042761454530651600213130ustar00rootroot00000000000000{ 'targets': [{ 'target_name': 'mongocrypt', 'include_dirs': [ "main}} libmongocrypt-1.8.4/bindings/node/etc/build-static.sh000077500000000000000000000023421454530651600226460ustar00rootroot00000000000000#!/usr/bin/env bash set -o errexit THIS_DIR="$(dirname "${BASH_SOURCE[0]}")" . "$THIS_DIR/../../../.evergreen/init.sh" NODE_DIR="$(abspath "$THIS_DIR/..")" DEPS_PREFIX="$NODE_DIR/deps" BUILD_DIR=$DEPS_PREFIX/tmp : "${CMAKE_FLAGS:=}" : "${WINDOWS_CMAKE_FLAGS:=}" # build and install libmongocrypt mkdir -p $BUILD_DIR/libmongocrypt-build pushd $BUILD_DIR/libmongocrypt-build #./deps/tmp/libmongocrypt-build CMAKE_FLAGS="-DDISABLE_NATIVE_CRYPTO=1 -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_MORE_WARNINGS_AS_ERRORS=ON" if [ "$OS_NAME" == "windows" ]; then if [ "${WINDOWS_32BIT-}" != "ON" ]; then WINDOWS_CMAKE_FLAGS="-Thost=x64 -A x64 -DENABLE_WINDOWS_STATIC_RUNTIME=ON" else WINDOWS_CMAKE_FLAGS="-DENABLE_WINDOWS_STATIC_RUNTIME=ON" fi run_cmake $CMAKE_FLAGS $WINDOWS_CMAKE_FLAGS -DCMAKE_PREFIX_PATH="$(native_path "$DEPS_PREFIX")" -DCMAKE_INSTALL_PREFIX="$(native_path "$DEPS_PREFIX")" "$(native_path "$LIBMONGOCRYPT_DIR")" else run_cmake $CMAKE_FLAGS -DCMAKE_PREFIX_PATH=$DEPS_PREFIX -DCMAKE_INSTALL_PREFIX=$DEPS_PREFIX -DCMAKE_OSX_DEPLOYMENT_TARGET="10.12" $LIBMONGOCRYPT_DIR fi run_cmake --build . --target install --config RelWithDebInfo popd #./ # build the `mongodb-client-encryption` addon env BUILD_TYPE=static npm install libmongocrypt-1.8.4/bindings/node/index.d.ts000066400000000000000000000456361454530651600210660ustar00rootroot00000000000000import type { MongoClient, BulkWriteResult, DeleteResult, FindCursor, Collection, Db, CreateCollectionOptions, Document, Binary, Long } from 'mongodb'; export type ClientEncryptionDataKeyProvider = 'aws' | 'azure' | 'gcp' | 'local' | 'kmip'; /** * The schema for a DataKey in the key vault collection. */ export interface DataKey { _id: Binary; version?: number; keyAltNames?: string[]; keyMaterial: Binary; creationDate: Date; updateDate: Date; status: number; masterKey: Document; } /** * An error indicating that something went wrong specifically with MongoDB Client Encryption */ export class MongoCryptError extends Error { cause?: Error; } /** * @experimental Public Technical Preview * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create a collection */ export class MongoCryptCreateEncryptedCollectionError extends MongoCryptError { /** * @experimental Public Technical Preview * The entire `encryptedFields` that was completed while attempting createEncryptedCollection */ encryptedFields: Document; /** The error rejected from db.createCollection() */ cause: Error; } /** * @experimental Public Technical Preview * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create data keys */ export class MongoCryptCreateDataKeyError extends MongoCryptError { /** * @experimental Public Technical Preview * The partial `encryptedFields` that was completed while attempting createEncryptedCollection */ encryptedFields: Document; /** The first error encountered when attempting to `createDataKey` */ cause: Error; } /** * An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials. */ export class MongoCryptAzureKMSRequestError extends MongoCryptError { /* The body of the IMDS request that produced the error, if present. */ body?: Document ; } export class MongoCryptKMSRequestNetworkTimeoutError extends MongoCryptError {} /** * A set of options for specifying a Socks5 proxy. */ export interface ProxyOptions { proxyHost: string; proxyPort?: number; proxyUsername?: string; proxyPassword?: string; } export interface ClientEncryptionCreateDataKeyCallback { /** * @param error If present, indicates an error that occurred in the creation of the data key * @param dataKeyId If present, returns the id of the created data key */ (error?: Error, dataKeyId?: Binary): void; } export interface ClientEncryptionEncryptCallback { /** * @param error If present, indicates an error that occurred in the process of encryption * @param result If present, is the encrypted result */ (error?: Error, result?: Binary): void; } export interface ClientEncryptionDecryptCallback { /** * @param error If present, indicates an error that occurred in the process of decryption * @param result If present, is the decrypted result */ (error?: Error, result?: any): void; } /** * Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. */ export interface KMSProviders { /** * Configuration options for using 'aws' as your KMS provider */ aws?: | { /** * The access key used for the AWS KMS provider */ accessKeyId: string; /** * The secret access key used for the AWS KMS provider */ secretAccessKey: string; /** * An optional AWS session token that will be used as the * X-Amz-Security-Token header for AWS requests. */ sessionToken?: string; } | Record; /** * Configuration options for using 'local' as your KMS provider */ local?: { /** * The master key used to encrypt/decrypt data keys. * A 96-byte long Buffer or base64 encoded string. */ key: Buffer | string; }; /** * Configuration options for using 'kmip' as your KMS provider */ kmip?: { /** * The output endpoint string. * The endpoint consists of a hostname and port separated by a colon. * E.g. "example.com:123". A port is always present. */ endpoint?: string; }; /** * Configuration options for using 'azure' as your KMS provider */ azure?: | { /** * The tenant ID identifies the organization for the account */ tenantId: string; /** * The client ID to authenticate a registered application */ clientId: string; /** * The client secret to authenticate a registered application */ clientSecret: string; /** * If present, a host with optional port. E.g. "example.com" or "example.com:443". * This is optional, and only needed if customer is using a non-commercial Azure instance * (e.g. a government or China account, which use different URLs). * Defaults to "login.microsoftonline.com" */ identityPlatformEndpoint?: string | undefined; } | { /** * If present, an access token to authenticate with Azure. */ accessToken: string; } | Record; /** * Configuration options for using 'gcp' as your KMS provider */ gcp?: | { /** * The service account email to authenticate */ email: string; /** * A PKCS#8 encrypted key. This can either be a base64 string or a binary representation */ privateKey: string | Buffer; /** * If present, a host with optional port. E.g. "example.com" or "example.com:443". * Defaults to "oauth2.googleapis.com" */ endpoint?: string | undefined; } | { /** * If present, an access token to authenticate with GCP. */ accessToken: string; } | Record; } /** * TLS options to use when connecting. The spec specifically calls out which insecure * tls options are not allowed: * * - tlsAllowInvalidCertificates * - tlsAllowInvalidHostnames * - tlsInsecure * - tlsDisableOCSPEndpointCheck * - tlsDisableCertificateRevocationCheck */ export interface ClientEncryptionTlsOptions { /** * Specifies the location of a local .pem file that contains * either the client's TLS/SSL certificate and key or only the * client's TLS/SSL key when tlsCertificateFile is used to * provide the certificate. */ tlsCertificateKeyFile?: string; /** * Specifies the password to de-crypt the tlsCertificateKeyFile. */ tlsCertificateKeyFilePassword?: string; /** * Specifies the location of a local .pem file that contains the * root certificate chain from the Certificate Authority. * This file is used to validate the certificate presented by the * KMS provider. */ tlsCAFile?: string; } /** * Additional settings to provide when creating a new `ClientEncryption` instance. */ export interface ClientEncryptionOptions { /** * The namespace of the key vault, used to store encryption keys */ keyVaultNamespace: string; /** * A MongoClient used to fetch keys from a key vault. Defaults to client. */ keyVaultClient?: MongoClient | undefined; /** * Options for specific KMS providers to use */ kmsProviders?: KMSProviders; /** * Optional callback to override KMS providers per-context. * * @deprecated Installing optional dependencies will automatically refresh kms * provider credentials. */ onKmsProviderRefresh?: () => Promise; /** * Options for specifying a Socks5 proxy to use for connecting to the KMS. */ proxyOptions?: ProxyOptions; /** * TLS options for kms providers to use. */ tlsOptions?: { [kms in keyof KMSProviders]?: ClientEncryptionTlsOptions }; } /** * Configuration options for making an AWS encryption key */ export interface AWSEncryptionKeyOptions { /** * The AWS region of the KMS */ region: string; /** * The Amazon Resource Name (ARN) to the AWS customer master key (CMK) */ key: string; /** * An alternate host to send KMS requests to. May include port number. */ endpoint?: string | undefined; } /** * Configuration options for making an AWS encryption key */ export interface GCPEncryptionKeyOptions { /** * GCP project ID */ projectId: string; /** * Location name (e.g. "global") */ location: string; /** * Key ring name */ keyRing: string; /** * Key name */ keyName: string; /** * Key version */ keyVersion?: string | undefined; /** * KMS URL, defaults to `https://www.googleapis.com/auth/cloudkms` */ endpoint?: string | undefined; } /** * Configuration options for making an Azure encryption key */ export interface AzureEncryptionKeyOptions { /** * Key name */ keyName: string; /** * Key vault URL, typically `.vault.azure.net` */ keyVaultEndpoint: string; /** * Key version */ keyVersion?: string | undefined; } /** * Options to provide when creating a new data key. */ export interface ClientEncryptionCreateDataKeyProviderOptions { /** * Identifies a new KMS-specific key used to encrypt the new data key */ masterKey?: | AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions | undefined; /** * An optional list of string alternate names used to reference a key. * If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by _id. */ keyAltNames?: string[] | undefined; /** @experimental */ keyMaterial?: Buffer | Binary; } /** @experimental */ export interface ClientEncryptionRewrapManyDataKeyProviderOptions { provider: ClientEncryptionDataKeyProvider; masterKey?: | AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions | undefined; } /** @experimental */ export interface ClientEncryptionRewrapManyDataKeyResult { /** The result of rewrapping data keys. If unset, no keys matched the filter. */ bulkWriteResult?: BulkWriteResult; } /** * RangeOptions specifies index options for a Queryable Encryption field supporting "rangePreview" queries. * min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. * For double and decimal128, min/max/precision must all be set, or all be unset. */ interface RangeOptions { min?: any; max?: any; sparsity: Long; precision?: number; } /** * Options to provide when encrypting data. */ export interface ClientEncryptionEncryptOptions { /** * The algorithm to use for encryption. */ algorithm: | 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' | 'AEAD_AES_256_CBC_HMAC_SHA_512-Random' | 'Indexed' | 'Unindexed' | 'RangePreview'; /** * The id of the Binary dataKey to use for encryption */ keyId?: Binary; /** * A unique string name corresponding to an already existing dataKey. */ keyAltName?: string; /** @experimental Public Technical Preview: The contention factor. */ contentionFactor?: bigint | number; /** @experimental Public Technical Preview: The query type supported */ queryType?: 'equality' | 'rangePreview'; /** @experimental Public Technical Preview: The index options for a Queryable Encryption field supporting "rangePreview" queries.*/ rangeOptions?: RangeOptions; } /** * The public interface for explicit in-use encryption */ export class ClientEncryption { /** * Create a new encryption instance. * @param client The client used for encryption * @param options Additional settings */ constructor(client: MongoClient, options: ClientEncryptionOptions); /** * Creates a data key used for explicit encryption and inserts it into the key vault namespace * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` */ createDataKey(provider: ClientEncryptionDataKeyProvider): Promise; /** * Creates a data key used for explicit encryption and inserts it into the key vault namespace * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` * @param options Options for creating the data key */ createDataKey( provider: ClientEncryptionDataKeyProvider, options: ClientEncryptionCreateDataKeyProviderOptions ): Promise; /** * Creates a data key used for explicit encryption and inserts it into the key vault namespace * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` * @param callback Callback to invoke when key is created */ createDataKey( provider: ClientEncryptionDataKeyProvider, callback: ClientEncryptionCreateDataKeyCallback ): void; /** * Creates a data key used for explicit encryption and inserts it into the key vault namespace * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` * @param options Options for creating the data key * @param callback Callback to invoke when key is created */ createDataKey( provider: ClientEncryptionDataKeyProvider, options: ClientEncryptionCreateDataKeyProviderOptions, callback: ClientEncryptionCreateDataKeyCallback ): void; /** * Searches the keyvault for any data keys matching the provided filter. If there are matches, rewrapManyDataKey then attempts to re-wrap the data keys using the provided options. * * If no matches are found, then no bulk write is performed. */ rewrapManyDataKey( filter: Document, options?: ClientEncryptionRewrapManyDataKeyProviderOptions ): Promise; /** * Deletes the key with the provided id from the keyvault, if it exists. * * @param id - the id of the document to delete. */ deleteKey(id: Binary): Promise; /** * Finds all the keys currently stored in the keyvault. * * This method will not throw. */ getKeys(): FindCursor; /** * Finds a key in the keyvault with the specified key. * * @param id - the id of the document to delete. */ getKey(id: Binary): Promise; /** * Finds a key in the keyvault which has the specified keyAltNames as a keyAltName. * * @param keyAltName - a potential keyAltName to search for in the keyAltNames array */ getKeyByAltName(keyAltName: string): Promise; /** * Adds a keyAltName to a key identified by the provided `id`. * * This method resolves to/returns the *old* key value (prior to adding the new altKeyName). * * @param id - The id of the document to update. * @param keyAltName - a keyAltName to search for a key */ addKeyAltName(id: Binary, keyAltName: string): Promise; /** * Adds a keyAltName to a key identified by the provided `id`. * * This method resolves to/returns the *old* key value (prior to removing the new altKeyName). * * If the removed keyAltName is the last keyAltName for that key, the `altKeyNames` property is unset from the document. * * @param id - the id of the document to update. * @param keyAltName - a keyAltName to search for a key */ removeKeyAltName(id: Binary, keyAltName: string): Promise; /** * @experimental Public Technical Preview * A convenience method for creating an encrypted collection. * This method will create data keys for any encryptedFields that do not have a `keyId` defined * and then create a new collection with the full set of encryptedFields. * * @param db - A Node.js driver Db object with which to create the collection * @param name - The name of the new collection * @param options - Options for createDataKey and for createCollection. A provider and partially created encryptedFields **must** be provided. * @throws {MongoCryptCreateDataKeyForEncryptedCollectionError} - If part way through the process a createDataKey invocation fails, an error will be rejected that has the partial `encryptedFields` that were created. * @throws {MongoCryptCreateEncryptedCollectionError} - If creating the collection fails, an error will be rejected that has the entire `encryptedFields` that were created. */ createEncryptedCollection( db: Db, name: string, options: { provider: ClientEncryptionDataKeyProvider; createCollectionOptions: Omit & { encryptedFields: Document; }; masterKey?: AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions; } ): Promise<{ collection: Collection; encryptedFields: Document }>; /** * Explicitly encrypt a provided value. * Note that either options.keyId or options.keyAltName must be specified. * Specifying both options.keyId and options.keyAltName is considered an error. * @param value The value that you wish to serialize. Must be of a type that can be serialized into BSON * @param options */ encrypt(value: any, options: ClientEncryptionEncryptOptions): Promise; /** * Explicitly encrypt a provided value. * Note that either options.keyId or options.keyAltName must be specified. * Specifying both options.keyId and options.keyAltName is considered an error. * @param value The value that you wish to serialize. Must be of a type that can be serialized into BSON * @param options * @param callback Callback to invoke when value is encrypted */ encrypt( value: any, options: ClientEncryptionEncryptOptions, callback: ClientEncryptionEncryptCallback ): void; /** * Encrypts a Match Expression or Aggregate Expression to query a range index. * * Only supported when queryType is "rangePreview" and algorithm is "RangePreview". * * @experimental The Range algorithm is experimental only. It is not intended for production use. It is subject to breaking changes.The aggregation or match expression you wish to encrypt. The value must be in the form * * The expression to encrypt must be one of the following: * 1. A Match Expression of this form: * `{$and: [{: {$gt: }}, {: {$lt: }}]}` * 2. An Aggregate Expression of this form: * `{$and: [{$gt: [, ]}, {$lt: [, ]}]}` * * `$gt` may also be `$gte`. `$lt` may also be `$lte`. */ encryptExpression(value: Document, options: ClientEncryptionEncryptOptions): Promise; /** * Explicitly decrypt a provided encrypted value * @param value An encrypted value */ decrypt(value: Buffer | Binary): Promise; /** * Explicitly decrypt a provided encrypted value * @param value An encrypted value * @param callback Callback to invoke when value is decrypted */ decrypt(value: Buffer | Binary, callback: ClientEncryptionDecryptCallback): void; static readonly libmongocryptVersion: string; } libmongocrypt-1.8.4/bindings/node/lib/000077500000000000000000000000001454530651600177155ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/lib/autoEncrypter.js000066400000000000000000000346611454530651600231310ustar00rootroot00000000000000'use strict'; module.exports = function (modules) { const mc = require('bindings')('mongocrypt'); const common = require('./common'); const databaseNamespace = common.databaseNamespace; const StateMachine = modules.stateMachine.StateMachine; const MongocryptdManager = require('./mongocryptdManager').MongocryptdManager; const MongoClient = modules.mongodb.MongoClient; const MongoError = modules.mongodb.MongoError; const BSON = modules.mongodb.BSON; const { loadCredentials } = require('./providers/index'); const cryptoCallbacks = require('./cryptoCallbacks'); /** * Configuration options for a automatic client encryption. * * @typedef {Object} AutoEncrypter~AutoEncryptionOptions * @property {MongoClient} [keyVaultClient] A `MongoClient` used to fetch keys from a key vault * @property {string} [keyVaultNamespace] The namespace where keys are stored in the key vault * @property {KMSProviders} [kmsProviders] Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. * @property {object} [schemaMap] A map of namespaces to a local JSON schema for encryption * @property {boolean} [bypassAutoEncryption] Allows the user to bypass auto encryption, maintaining implicit decryption * @property {AutoEncrypter~logger} [options.logger] An optional hook to catch logging messages from the underlying encryption engine * @property {AutoEncrypter~AutoEncryptionExtraOptions} [extraOptions] Extra options related to the mongocryptd process */ /** * Extra options related to the mongocryptd process * @typedef {object} AutoEncrypter~AutoEncryptionExtraOptions * @property {string} [mongocryptdURI] A local process the driver communicates with to determine how to encrypt values in a command. Defaults to "mongodb://%2Fvar%2Fmongocryptd.sock" if domain sockets are available or "mongodb://localhost:27020" otherwise * @property {boolean} [mongocryptdBypassSpawn=false] If true, autoEncryption will not attempt to spawn a mongocryptd before connecting * @property {string} [mongocryptdSpawnPath] The path to the mongocryptd executable on the system * @property {string[]} [mongocryptdSpawnArgs] Command line arguments to use when auto-spawning a mongocryptd */ /** * @callback AutoEncrypter~logger * @description A callback that is invoked with logging information from * the underlying C++ Bindings. * @param {AutoEncrypter~logLevel} level The level of logging. * @param {string} message The message to log */ /** * @name AutoEncrypter~logLevel * @enum {number} * @description * The level of severity of the log message * * | Value | Level | * |-------|-------| * | 0 | Fatal Error | * | 1 | Error | * | 2 | Warning | * | 3 | Info | * | 4 | Trace | */ /** * @classdesc An internal class to be used by the driver for auto encryption * **NOTE**: Not meant to be instantiated directly, this is for internal use only. */ class AutoEncrypter { /** * Create an AutoEncrypter * * **Note**: Do not instantiate this class directly. Rather, supply the relevant options to a MongoClient * * **Note**: Supplying `options.schemaMap` provides more security than relying on JSON Schemas obtained from the server. * It protects against a malicious server advertising a false JSON Schema, which could trick the client into sending unencrypted data that should be encrypted. * Schemas supplied in the schemaMap only apply to configuring automatic encryption for Client-Side Field Level Encryption. * Other validation rules in the JSON schema will not be enforced by the driver and will result in an error. * @param {MongoClient} client The client autoEncryption is enabled on * @param {AutoEncrypter~AutoEncryptionOptions} [options] Optional settings * * @example * // Enabling autoEncryption via a MongoClient * const { MongoClient } = require('mongodb'); * const client = new MongoClient(URL, { * autoEncryption: { * kmsProviders: { * aws: { * accessKeyId: AWS_ACCESS_KEY, * secretAccessKey: AWS_SECRET_KEY * } * } * } * }); * * await client.connect(); * // From here on, the client will be encrypting / decrypting automatically */ constructor(client, options) { this._client = client; this._bson = options.bson || BSON || client.topology.bson; this._bypassEncryption = options.bypassAutoEncryption === true; this._keyVaultNamespace = options.keyVaultNamespace || 'admin.datakeys'; this._keyVaultClient = options.keyVaultClient || client; this._metaDataClient = options.metadataClient || client; this._proxyOptions = options.proxyOptions || {}; this._tlsOptions = options.tlsOptions || {}; this._onKmsProviderRefresh = options.onKmsProviderRefresh; this._kmsProviders = options.kmsProviders || {}; const mongoCryptOptions = {}; if (options.schemaMap) { mongoCryptOptions.schemaMap = Buffer.isBuffer(options.schemaMap) ? options.schemaMap : this._bson.serialize(options.schemaMap); } if (options.encryptedFieldsMap) { mongoCryptOptions.encryptedFieldsMap = Buffer.isBuffer(options.encryptedFieldsMap) ? options.encryptedFieldsMap : this._bson.serialize(options.encryptedFieldsMap); } mongoCryptOptions.kmsProviders = !Buffer.isBuffer(this._kmsProviders) ? this._bson.serialize(this._kmsProviders) : this._kmsProviders; if (options.logger) { mongoCryptOptions.logger = options.logger; } if (options.extraOptions && options.extraOptions.cryptSharedLibPath) { mongoCryptOptions.cryptSharedLibPath = options.extraOptions.cryptSharedLibPath; } if (options.bypassQueryAnalysis) { mongoCryptOptions.bypassQueryAnalysis = options.bypassQueryAnalysis; } this._bypassMongocryptdAndCryptShared = this._bypassEncryption || options.bypassQueryAnalysis; if (options.extraOptions && options.extraOptions.cryptSharedLibSearchPaths) { // Only for driver testing mongoCryptOptions.cryptSharedLibSearchPaths = options.extraOptions.cryptSharedLibSearchPaths; } else if (!this._bypassMongocryptdAndCryptShared) { mongoCryptOptions.cryptSharedLibSearchPaths = ['$SYSTEM']; } Object.assign(mongoCryptOptions, { cryptoCallbacks }); this._mongocrypt = new mc.MongoCrypt(mongoCryptOptions); this._contextCounter = 0; if ( options.extraOptions && options.extraOptions.cryptSharedLibRequired && !this.cryptSharedLibVersionInfo ) { throw new MongoError('`cryptSharedLibRequired` set but no crypt_shared library loaded'); } // Only instantiate mongocryptd manager/client once we know for sure // that we are not using the CSFLE shared library. if (!this._bypassMongocryptdAndCryptShared && !this.cryptSharedLibVersionInfo) { this._mongocryptdManager = new MongocryptdManager(options.extraOptions); const clientOptions = { useNewUrlParser: true, useUnifiedTopology: true, serverSelectionTimeoutMS: 10000 }; if ( options.extraOptions == null || typeof options.extraOptions.mongocryptdURI !== 'string' ) { clientOptions.family = 4; } this._mongocryptdClient = new MongoClient(this._mongocryptdManager.uri, clientOptions); } } /** * @ignore * @param {Function} callback Invoked when the mongocryptd client either successfully connects or errors */ init(callback) { if (this._bypassMongocryptdAndCryptShared || this.cryptSharedLibVersionInfo) { return callback(); } const _callback = (err, res) => { if ( err && err.message && (err.message.match(/timed out after/) || err.message.match(/ENOTFOUND/)) ) { callback( new MongoError( 'Unable to connect to `mongocryptd`, please make sure it is running or in your PATH for auto-spawn' ) ); return; } callback(err, res); }; if (this._mongocryptdManager.bypassSpawn) { return this._mongocryptdClient.connect().then( result => { return _callback(null, result); }, error => { _callback(error, null); } ); } this._mongocryptdManager.spawn(() => { this._mongocryptdClient.connect().then( result => { return _callback(null, result); }, error => { _callback(error, null); } ); }); } /** * @ignore * @param {Function} callback Invoked when the mongocryptd client either successfully disconnects or errors */ teardown(force, callback) { if (this._mongocryptdClient) { this._mongocryptdClient.close(force).then( result => { return callback(null, result); }, error => { callback(error); } ); } else { callback(); } } /** * @ignore * Encrypt a command for a given namespace. * * @param {string} ns The namespace for this encryption context * @param {object} cmd The command to encrypt * @param {Function} callback */ encrypt(ns, cmd, options, callback) { if (typeof ns !== 'string') { throw new TypeError('Parameter `ns` must be a string'); } if (typeof cmd !== 'object') { throw new TypeError('Parameter `cmd` must be an object'); } if (typeof options === 'function' && callback == null) { callback = options; options = {}; } // If `bypassAutoEncryption` has been specified, don't encrypt if (this._bypassEncryption) { callback(undefined, cmd); return; } const bson = this._bson; const commandBuffer = Buffer.isBuffer(cmd) ? cmd : bson.serialize(cmd, options); let context; try { context = this._mongocrypt.makeEncryptionContext(databaseNamespace(ns), commandBuffer); } catch (err) { callback(err, null); return; } // TODO: should these be accessors from the addon? context.id = this._contextCounter++; context.ns = ns; context.document = cmd; const stateMachine = new StateMachine({ bson, ...options, promoteValues: false, promoteLongs: false, proxyOptions: this._proxyOptions, tlsOptions: this._tlsOptions }); stateMachine.execute(this, context, callback); } /** * @ignore * Decrypt a command response * * @param {Buffer} buffer * @param {Function} callback */ decrypt(response, options, callback) { if (typeof options === 'function' && callback == null) { callback = options; options = {}; } const bson = this._bson; const buffer = Buffer.isBuffer(response) ? response : bson.serialize(response, options); let context; try { context = this._mongocrypt.makeDecryptionContext(buffer); } catch (err) { callback(err, null); return; } // TODO: should this be an accessor from the addon? context.id = this._contextCounter++; const stateMachine = new StateMachine({ bson, ...options, proxyOptions: this._proxyOptions, tlsOptions: this._tlsOptions }); const decorateResult = this[Symbol.for('@@mdb.decorateDecryptionResult')]; stateMachine.execute(this, context, function (err, result) { // Only for testing/internal usage if (!err && result && decorateResult) { err = decorateDecryptionResult(result, response, bson); if (err) return callback(err); } callback(err, result); }); } /** * Ask the user for KMS credentials. * * This returns anything that looks like the kmsProviders original input * option. It can be empty, and any provider specified here will override * the original ones. */ async askForKMSCredentials() { return this._onKmsProviderRefresh ? this._onKmsProviderRefresh() : loadCredentials(this._kmsProviders); } /** * Return the current libmongocrypt's CSFLE shared library version * as `{ version: bigint, versionStr: string }`, or `null` if no CSFLE * shared library was loaded. */ get cryptSharedLibVersionInfo() { return this._mongocrypt.cryptSharedLibVersionInfo; } static get libmongocryptVersion() { return mc.MongoCrypt.libmongocryptVersion; } } return { AutoEncrypter }; }; /** * Recurse through the (identically-shaped) `decrypted` and `original` * objects and attach a `decryptedKeys` property on each sub-object that * contained encrypted fields. Because we only call this on BSON responses, * we do not need to worry about circular references. * * @internal * @ignore */ function decorateDecryptionResult(decrypted, original, bson, isTopLevelDecorateCall = true) { const decryptedKeys = Symbol.for('@@mdb.decryptedKeys'); if (isTopLevelDecorateCall) { // The original value could have been either a JS object or a BSON buffer if (Buffer.isBuffer(original)) { original = bson.deserialize(original); } if (Buffer.isBuffer(decrypted)) { return new Error('Expected result of decryption to be deserialized BSON object'); } } if (!decrypted || typeof decrypted !== 'object') return; for (const k of Object.keys(decrypted)) { const originalValue = original[k]; // An object was decrypted by libmongocrypt if and only if it was // a BSON Binary object with subtype 6. if (originalValue && originalValue._bsontype === 'Binary' && originalValue.sub_type === 6) { if (!decrypted[decryptedKeys]) { Object.defineProperty(decrypted, decryptedKeys, { value: [], configurable: true, enumerable: false, writable: false }); } decrypted[decryptedKeys].push(k); // Do not recurse into this decrypted value. It could be a subdocument/array, // in which case there is no original value associated with its subfields. continue; } decorateDecryptionResult(decrypted[k], originalValue, bson, false); } } libmongocrypt-1.8.4/bindings/node/lib/buffer_pool.js000066400000000000000000000055111454530651600225570ustar00rootroot00000000000000'use strict'; /** * @internal * @ignore * */ const kBuffers = Symbol('buffers'); /** * @internal * @ignore * * */ const kLength = Symbol('length'); /** * A pool of Buffers which allow you to read them as if they were one * @internal * @ignore */ class BufferPool { // [kBuffers]: Buffer[]; // [kLength]: number; constructor() { this[kBuffers] = []; this[kLength] = 0; } get length() { return this[kLength]; } /** * Adds a buffer to the internal buffer pool list * @param {Buffer} buffer - buffer to append to the pool * @returns {void} */ append(buffer) { this[kBuffers].push(buffer); this[kLength] += buffer.length; } /** * Returns the requested number of bytes without consuming them * @param {number} size - the number of bytes to return from the head of the pool * @returns {Buffer} */ peek(size) { return this.read(size, false); } /** * Reads the requested number of bytes, optionally consuming them * @param {number} size - the number of bytes to return from the head of the pool * @param {boolean} [consume] - whether the bytes returned should be removed, defaults to true * @returns {Buffer} */ read(size, consume = true) { if (typeof size !== 'number' || size < 0) { throw new Error('Argument "size" must be a non-negative number'); } if (size > this[kLength]) { return Buffer.alloc(0); } let result; // read the whole buffer if (size === this.length) { result = Buffer.concat(this[kBuffers]); if (consume) { this[kBuffers] = []; this[kLength] = 0; } } // size is within first buffer, no need to concat else if (size <= this[kBuffers][0].length) { result = this[kBuffers][0].slice(0, size); if (consume) { this[kBuffers][0] = this[kBuffers][0].slice(size); this[kLength] -= size; } } // size is beyond first buffer, need to track and copy else { result = Buffer.allocUnsafe(size); let idx; let offset = 0; let bytesToCopy = size; for (idx = 0; idx < this[kBuffers].length; ++idx) { let bytesCopied; if (bytesToCopy > this[kBuffers][idx].length) { bytesCopied = this[kBuffers][idx].copy(result, offset, 0); offset += bytesCopied; } else { bytesCopied = this[kBuffers][idx].copy(result, offset, 0, bytesToCopy); if (consume) { this[kBuffers][idx] = this[kBuffers][idx].slice(bytesCopied); } offset += bytesCopied; break; } bytesToCopy -= bytesCopied; } // compact the internal buffer array if (consume) { this[kBuffers] = this[kBuffers].slice(idx); this[kLength] -= size; } } return result; } } module.exports = { BufferPool }; libmongocrypt-1.8.4/bindings/node/lib/clientEncryption.js000066400000000000000000001045061454530651600236120ustar00rootroot00000000000000'use strict'; module.exports = function (modules) { const mc = require('bindings')('mongocrypt'); const common = require('./common'); const databaseNamespace = common.databaseNamespace; const collectionNamespace = common.collectionNamespace; const promiseOrCallback = common.promiseOrCallback; const maybeCallback = common.maybeCallback; const StateMachine = modules.stateMachine.StateMachine; const BSON = modules.mongodb.BSON; const { MongoCryptCreateEncryptedCollectionError, MongoCryptCreateDataKeyError } = require('./errors'); const { loadCredentials } = require('./providers/index'); const cryptoCallbacks = require('./cryptoCallbacks'); const { promisify } = require('util'); /** @typedef {*} BSONValue - any serializable BSON value */ /** @typedef {BSON.Long} Long A 64 bit integer, represented by the js-bson Long type.*/ /** * @typedef {object} KMSProviders Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. * @property {object} [aws] Configuration options for using 'aws' as your KMS provider * @property {string} [aws.accessKeyId] The access key used for the AWS KMS provider * @property {string} [aws.secretAccessKey] The secret access key used for the AWS KMS provider * @property {object} [local] Configuration options for using 'local' as your KMS provider * @property {Buffer} [local.key] The master key used to encrypt/decrypt data keys. A 96-byte long Buffer. * @property {object} [azure] Configuration options for using 'azure' as your KMS provider * @property {string} [azure.tenantId] The tenant ID identifies the organization for the account * @property {string} [azure.clientId] The client ID to authenticate a registered application * @property {string} [azure.clientSecret] The client secret to authenticate a registered application * @property {string} [azure.identityPlatformEndpoint] If present, a host with optional port. E.g. "example.com" or "example.com:443". This is optional, and only needed if customer is using a non-commercial Azure instance (e.g. a government or China account, which use different URLs). Defaults to "login.microsoftonline.com" * @property {object} [gcp] Configuration options for using 'gcp' as your KMS provider * @property {string} [gcp.email] The service account email to authenticate * @property {string|Binary} [gcp.privateKey] A PKCS#8 encrypted key. This can either be a base64 string or a binary representation * @property {string} [gcp.endpoint] If present, a host with optional port. E.g. "example.com" or "example.com:443". Defaults to "oauth2.googleapis.com" */ /** * @typedef {object} DataKey A data key as stored in the database. * @property {UUID} _id A unique identifier for the key. * @property {number} version A numeric identifier for the schema version of this document. Implicitly 0 if unset. * @property {string[]} [keyAltNames] Alternate names to search for keys by. Used for a per-document key scenario in support of GDPR scenarios. * @property {Binary} keyMaterial Encrypted data key material, BinData type General. * @property {Date} creationDate The datetime the wrapped data key material was imported into the Key Database. * @property {Date} updateDate The datetime the wrapped data key material was last modified. On initial import, this value will be set to creationDate. * @property {number} status 0 = enabled, 1 = disabled * @property {object} masterKey the encrypted master key */ /** * @typedef {string} KmsProvider A string containing the name of a kms provider. Valid options are 'aws', 'azure', 'gcp', 'kmip', or 'local' */ /** * @typedef {object} ClientSession The ClientSession class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/ClientSession.html) */ /** * @typedef {object} DeleteResult The result of a delete operation from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/interfaces/DeleteResult.html) * @property {boolean} acknowledged Indicates whether this write result was acknowledged. If not, then all other members of this result will be undefined. * @property {number} deletedCount The number of documents that were deleted */ /** * @typedef {object} BulkWriteResult The BulkWriteResult class from the MongoDB Node driver (https://mongodb.github.io/node-mongodb-native/4.8/classes/BulkWriteResult.html) */ /** * @typedef {object} FindCursor The FindCursor class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/FindCursor.html) */ /** * The public interface for explicit in-use encryption */ class ClientEncryption { /** * Create a new encryption instance * * @param {MongoClient} client The client used for encryption * @param {object} options Additional settings * @param {string} options.keyVaultNamespace The namespace of the key vault, used to store encryption keys * @param {object} options.tlsOptions An object that maps KMS provider names to TLS options. * @param {MongoClient} [options.keyVaultClient] A `MongoClient` used to fetch keys from a key vault. Defaults to `client` * @param {KMSProviders} [options.kmsProviders] options for specific KMS providers to use * * @example * new ClientEncryption(mongoClient, { * keyVaultNamespace: 'client.encryption', * kmsProviders: { * local: { * key: masterKey // The master key used for encryption/decryption. A 96-byte long Buffer * } * } * }); * * @example * new ClientEncryption(mongoClient, { * keyVaultNamespace: 'client.encryption', * kmsProviders: { * aws: { * accessKeyId: AWS_ACCESS_KEY, * secretAccessKey: AWS_SECRET_KEY * } * } * }); */ constructor(client, options) { this._client = client; this._bson = options.bson || BSON || client.topology.bson; this._proxyOptions = options.proxyOptions; this._tlsOptions = options.tlsOptions; this._kmsProviders = options.kmsProviders || {}; if (options.keyVaultNamespace == null) { throw new TypeError('Missing required option `keyVaultNamespace`'); } const mongoCryptOptions = { ...options, cryptoCallbacks }; mongoCryptOptions.kmsProviders = !Buffer.isBuffer(this._kmsProviders) ? this._bson.serialize(this._kmsProviders) : this._kmsProviders; this._onKmsProviderRefresh = options.onKmsProviderRefresh; this._keyVaultNamespace = options.keyVaultNamespace; this._keyVaultClient = options.keyVaultClient || client; this._mongoCrypt = new mc.MongoCrypt(mongoCryptOptions); } /** * @typedef {Binary} ClientEncryptionDataKeyId * The id of an existing dataKey. Is a bson Binary value. * Can be used for {@link ClientEncryption.encrypt}, and can be used to directly * query for the data key itself against the key vault namespace. */ /** * @callback ClientEncryptionCreateDataKeyCallback * @param {Error} [error] If present, indicates an error that occurred in the creation of the data key * @param {ClientEncryption~dataKeyId} [dataKeyId] If present, returns the id of the created data key */ /** * @typedef {object} AWSEncryptionKeyOptions Configuration options for making an AWS encryption key * @property {string} region The AWS region of the KMS * @property {string} key The Amazon Resource Name (ARN) to the AWS customer master key (CMK) * @property {string} [endpoint] An alternate host to send KMS requests to. May include port number */ /** * @typedef {object} GCPEncryptionKeyOptions Configuration options for making a GCP encryption key * @property {string} projectId GCP project id * @property {string} location Location name (e.g. "global") * @property {string} keyRing Key ring name * @property {string} keyName Key name * @property {string} [keyVersion] Key version * @property {string} [endpoint] KMS URL, defaults to `https://www.googleapis.com/auth/cloudkms` */ /** * @typedef {object} AzureEncryptionKeyOptions Configuration options for making an Azure encryption key * @property {string} keyName Key name * @property {string} keyVaultEndpoint Key vault URL, typically `.vault.azure.net` * @property {string} [keyVersion] Key version */ /** * Creates a data key used for explicit encryption and inserts it into the key vault namespace * * @param {string} provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` * @param {object} [options] Options for creating the data key * @param {AWSEncryptionKeyOptions|AzureEncryptionKeyOptions|GCPEncryptionKeyOptions} [options.masterKey] Idenfities a new KMS-specific key used to encrypt the new data key * @param {string[]} [options.keyAltNames] An optional list of string alternate names used to reference a key. If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by _id. * @param {ClientEncryptionCreateDataKeyCallback} [callback] Optional callback to invoke when key is created * @returns {Promise|void} If no callback is provided, returns a Promise that either resolves with {@link ClientEncryption~dataKeyId the id of the created data key}, or rejects with an error. If a callback is provided, returns nothing. * @example * // Using callbacks to create a local key * clientEncryption.createDataKey('local', (err, dataKey) => { * if (err) { * // This means creating the key failed. * } else { * // key creation succeeded * } * }); * * @example * // Using async/await to create a local key * const dataKeyId = await clientEncryption.createDataKey('local'); * * @example * // Using async/await to create an aws key * const dataKeyId = await clientEncryption.createDataKey('aws', { * masterKey: { * region: 'us-east-1', * key: 'xxxxxxxxxxxxxx' // CMK ARN here * } * }); * * @example * // Using async/await to create an aws key with a keyAltName * const dataKeyId = await clientEncryption.createDataKey('aws', { * masterKey: { * region: 'us-east-1', * key: 'xxxxxxxxxxxxxx' // CMK ARN here * }, * keyAltNames: [ 'mySpecialKey' ] * }); */ createDataKey(provider, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } if (options == null) { options = {}; } const bson = this._bson; const dataKey = Object.assign({ provider }, options.masterKey); if (options.keyAltNames && !Array.isArray(options.keyAltNames)) { throw new TypeError( `Option "keyAltNames" must be an array of strings, but was of type ${typeof options.keyAltNames}.` ); } let keyAltNames = undefined; if (options.keyAltNames && options.keyAltNames.length > 0) { keyAltNames = options.keyAltNames.map((keyAltName, i) => { if (typeof keyAltName !== 'string') { throw new TypeError( `Option "keyAltNames" must be an array of strings, but item at index ${i} was of type ${typeof keyAltName}` ); } return bson.serialize({ keyAltName }); }); } let keyMaterial = undefined; if (options.keyMaterial) { keyMaterial = bson.serialize({ keyMaterial: options.keyMaterial }); } const dataKeyBson = bson.serialize(dataKey); const context = this._mongoCrypt.makeDataKeyContext(dataKeyBson, { keyAltNames, keyMaterial }); const stateMachine = new StateMachine({ bson, proxyOptions: this._proxyOptions, tlsOptions: this._tlsOptions }); return promiseOrCallback(callback, cb => { stateMachine.execute(this, context, (err, dataKey) => { if (err) { cb(err, null); return; } const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); this._keyVaultClient .db(dbName) .collection(collectionName) .insertOne(dataKey, { writeConcern: { w: 'majority' } }) .then( result => { return cb(null, result.insertedId); }, err => { cb(err, null); } ); }); }); } /** * @typedef {object} RewrapManyDataKeyResult * @property {BulkWriteResult} [bulkWriteResult] An optional BulkWriteResult, if any keys were matched and attempted to be re-wrapped. */ /** * Searches the keyvault for any data keys matching the provided filter. If there are matches, rewrapManyDataKey then attempts to re-wrap the data keys using the provided options. * * If no matches are found, then no bulk write is performed. * * @param {object} filter A valid MongoDB filter. Any documents matching this filter will be re-wrapped. * @param {object} [options] * @param {KmsProvider} options.provider The KMS provider to use when re-wrapping the data keys. * @param {AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions} [options.masterKey] * @returns {Promise} * * @example * // rewrapping all data data keys (using a filter that matches all documents) * const filter = {}; * * const result = await clientEncryption.rewrapManyDataKey(filter); * if (result.bulkWriteResult != null) { * // keys were re-wrapped, results will be available in the bulkWrite object. * } * * @example * // attempting to rewrap all data keys with no matches * const filter = { _id: new Binary() } // assume _id matches no documents in the database * const result = await clientEncryption.rewrapManyDataKey(filter); * * if (result.bulkWriteResult == null) { * // no keys matched, `bulkWriteResult` does not exist on the result object * } */ async rewrapManyDataKey(filter, options) { const bson = this._bson; let keyEncryptionKeyBson = undefined; if (options) { const keyEncryptionKey = Object.assign({ provider: options.provider }, options.masterKey); keyEncryptionKeyBson = bson.serialize(keyEncryptionKey); } else { // Always make sure `options` is an object below. options = {}; } const filterBson = bson.serialize(filter); const context = this._mongoCrypt.makeRewrapManyDataKeyContext( filterBson, keyEncryptionKeyBson ); const stateMachine = new StateMachine({ bson, proxyOptions: this._proxyOptions, tlsOptions: this._tlsOptions }); const execute = promisify(stateMachine.execute.bind(stateMachine)); const dataKey = await execute(this, context); if (!dataKey || dataKey.v.length === 0) { return {}; } const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); const replacements = dataKey.v.map(key => ({ updateOne: { filter: { _id: key._id }, update: { $set: { masterKey: key.masterKey, keyMaterial: key.keyMaterial }, $currentDate: { updateDate: true } } } })); const result = await this._keyVaultClient .db(dbName) .collection(collectionName) .bulkWrite(replacements, { writeConcern: { w: 'majority' } }); return { bulkWriteResult: result }; } /** * Deletes the key with the provided id from the keyvault, if it exists. * * @param {ClientEncryptionDataKeyId} _id - the id of the document to delete. * @returns {Promise} Returns a promise that either resolves to a {@link DeleteResult} or rejects with an error. * * @example * // delete a key by _id * const id = new Binary(); // id is a bson binary subtype 4 object * const { deletedCount } = await clientEncryption.deleteKey(id); * * if (deletedCount != null && deletedCount > 0) { * // successful deletion * } * */ async deleteKey(_id) { const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); return await this._keyVaultClient .db(dbName) .collection(collectionName) .deleteOne({ _id }, { writeConcern: { w: 'majority' } }); } /** * Finds all the keys currently stored in the keyvault. * * This method will not throw. * * @returns {FindCursor} a FindCursor over all keys in the keyvault. * @example * // fetching all keys * const keys = await clientEncryption.getKeys().toArray(); */ getKeys() { const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); return this._keyVaultClient .db(dbName) .collection(collectionName) .find({}, { readConcern: { level: 'majority' } }); } /** * Finds a key in the keyvault with the specified _id. * * @param {ClientEncryptionDataKeyId} _id - the id of the document to delete. * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents * match the id. The promise rejects with an error if an error is thrown. * @example * // getting a key by id * const id = new Binary(); // id is a bson binary subtype 4 object * const key = await clientEncryption.getKey(id); * if (!key) { * // key is null if there was no matching key * } */ async getKey(_id) { const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); return await this._keyVaultClient .db(dbName) .collection(collectionName) .findOne({ _id }, { readConcern: { level: 'majority' } }); } /** * Finds a key in the keyvault which has the specified keyAltName. * * @param {string} keyAltName - a keyAltName to search for a key * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents * match the keyAltName. The promise rejects with an error if an error is thrown. * @example * // get a key by alt name * const keyAltName = 'keyAltName'; * const key = await clientEncryption.getKeyByAltName(keyAltName); * if (!key) { * // key is null if there is no matching key * } */ async getKeyByAltName(keyAltName) { const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); return await this._keyVaultClient .db(dbName) .collection(collectionName) .findOne({ keyAltNames: keyAltName }, { readConcern: { level: 'majority' } }); } /** * Adds a keyAltName to a key identified by the provided _id. * * This method resolves to/returns the *old* key value (prior to adding the new altKeyName). * * @param {ClientEncryptionDataKeyId} _id The id of the document to update. * @param {string} keyAltName - a keyAltName to search for a key * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents * match the id. The promise rejects with an error if an error is thrown. * @example * // adding an keyAltName to a data key * const id = new Binary(); // id is a bson binary subtype 4 object * const keyAltName = 'keyAltName'; * const oldKey = await clientEncryption.addKeyAltName(id, keyAltName); * if (!oldKey) { * // null is returned if there is no matching document with an id matching the supplied id * } */ async addKeyAltName(_id, keyAltName) { const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); const { value } = await this._keyVaultClient .db(dbName) .collection(collectionName) .findOneAndUpdate( { _id }, { $addToSet: { keyAltNames: keyAltName } }, { writeConcern: { w: 'majority' }, returnDocument: 'before' } ); return value; } /** * Adds a keyAltName to a key identified by the provided _id. * * This method resolves to/returns the *old* key value (prior to removing the new altKeyName). * * If the removed keyAltName is the last keyAltName for that key, the `altKeyNames` property is unset from the document. * * @param {ClientEncryptionDataKeyId} _id The id of the document to update. * @param {string} keyAltName - a keyAltName to search for a key * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents * match the id. The promise rejects with an error if an error is thrown. * @example * // removing a key alt name from a data key * const id = new Binary(); // id is a bson binary subtype 4 object * const keyAltName = 'keyAltName'; * const oldKey = await clientEncryption.removeKeyAltName(id, keyAltName); * * if (!oldKey) { * // null is returned if there is no matching document with an id matching the supplied id * } */ async removeKeyAltName(_id, keyAltName) { const dbName = databaseNamespace(this._keyVaultNamespace); const collectionName = collectionNamespace(this._keyVaultNamespace); const pipeline = [ { $set: { keyAltNames: { $cond: [ { $eq: ['$keyAltNames', [keyAltName]] }, '$$REMOVE', { $filter: { input: '$keyAltNames', cond: { $ne: ['$$this', keyAltName] } } } ] } } } ]; const { value } = await this._keyVaultClient .db(dbName) .collection(collectionName) .findOneAndUpdate({ _id }, pipeline, { writeConcern: { w: 'majority' }, returnDocument: 'before' }); return value; } /** * @experimental Public Technical Preview * * A convenience method for creating an encrypted collection. * This method will create data keys for any encryptedFields that do not have a `keyId` defined * and then create a new collection with the full set of encryptedFields. * * @template {TSchema} - Schema for the collection being created * @param {Db} db - A Node.js driver Db object with which to create the collection * @param {string} name - The name of the collection to be created * @param {object} options - Options for createDataKey and for createCollection * @param {string} options.provider - KMS provider name * @param {AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions} [options.masterKey] - masterKey to pass to createDataKey * @param {CreateCollectionOptions} options.createCollectionOptions - options to pass to createCollection, must include `encryptedFields` * @returns {Promise<{ collection: Collection, encryptedFields: Document }>} - created collection and generated encryptedFields * @throws {MongoCryptCreateDataKeyError} - If part way through the process a createDataKey invocation fails, an error will be rejected that has the partial `encryptedFields` that were created. * @throws {MongoCryptCreateEncryptedCollectionError} - If creating the collection fails, an error will be rejected that has the entire `encryptedFields` that were created. */ async createEncryptedCollection(db, name, options) { const { provider, masterKey, createCollectionOptions: { encryptedFields: { ...encryptedFields }, ...createCollectionOptions } } = options; if (Array.isArray(encryptedFields.fields)) { const createDataKeyPromises = encryptedFields.fields.map(async field => field == null || typeof field !== 'object' || field.keyId != null ? field : { ...field, keyId: await this.createDataKey(provider, { masterKey }) } ); const createDataKeyResolutions = await Promise.allSettled(createDataKeyPromises); encryptedFields.fields = createDataKeyResolutions.map((resolution, index) => resolution.status === 'fulfilled' ? resolution.value : encryptedFields.fields[index] ); const rejection = createDataKeyResolutions.find(({ status }) => status === 'rejected'); if (rejection != null) { throw new MongoCryptCreateDataKeyError({ encryptedFields, cause: rejection.reason }); } } try { const collection = await db.createCollection(name, { ...createCollectionOptions, encryptedFields }); return { collection, encryptedFields }; } catch (cause) { throw new MongoCryptCreateEncryptedCollectionError({ encryptedFields, cause }); } } /** * @callback ClientEncryptionEncryptCallback * @param {Error} [err] If present, indicates an error that occurred in the process of encryption * @param {Buffer} [result] If present, is the encrypted result */ /** * @typedef {object} RangeOptions * min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. * For double and decimal128, min/max/precision must all be set, or all be unset. * @property {BSONValue} min is required if precision is set. * @property {BSONValue} max is required if precision is set. * @property {BSON.Long} sparsity * @property {number | undefined} precision (may only be set for double or decimal128). */ /** * @typedef {object} EncryptOptions Options to provide when encrypting data. * @property {ClientEncryptionDataKeyId} [keyId] The id of the Binary dataKey to use for encryption. * @property {string} [keyAltName] A unique string name corresponding to an already existing dataKey. * @property {string} [algorithm] The algorithm to use for encryption. Must be either `'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'`, `'AEAD_AES_256_CBC_HMAC_SHA_512-Random'`, `'Indexed'` or `'Unindexed'` * @property {bigint | number} [contentionFactor] (experimental) - the contention factor. * @property {'equality' | 'rangePreview'} queryType (experimental) - the query type supported. * @property {RangeOptions} [rangeOptions] (experimental) The index options for a Queryable Encryption field supporting "rangePreview" queries. */ /** * Explicitly encrypt a provided value. Note that either `options.keyId` or `options.keyAltName` must * be specified. Specifying both `options.keyId` and `options.keyAltName` is considered an error. * * @param {*} value The value that you wish to serialize. Must be of a type that can be serialized into BSON * @param {EncryptOptions} options * @param {ClientEncryptionEncryptCallback} [callback] Optional callback to invoke when value is encrypted * @returns {Promise|void} If no callback is provided, returns a Promise that either resolves with the encrypted value, or rejects with an error. If a callback is provided, returns nothing. * * @example * // Encryption with callback API * function encryptMyData(value, callback) { * clientEncryption.createDataKey('local', (err, keyId) => { * if (err) { * return callback(err); * } * clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }, callback); * }); * } * * @example * // Encryption with async/await api * async function encryptMyData(value) { * const keyId = await clientEncryption.createDataKey('local'); * return clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); * } * * @example * // Encryption using a keyAltName * async function encryptMyData(value) { * await clientEncryption.createDataKey('local', { keyAltNames: 'mySpecialKey' }); * return clientEncryption.encrypt(value, { keyAltName: 'mySpecialKey', algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); * } */ encrypt(value, options, callback) { return maybeCallback(() => this._encrypt(value, false, options), callback); } /** * Encrypts a Match Expression or Aggregate Expression to query a range index. * * Only supported when queryType is "rangePreview" and algorithm is "RangePreview". * * @experimental The Range algorithm is experimental only. It is not intended for production use. It is subject to breaking changes. * * @param {object} expression a BSON document of one of the following forms: * 1. A Match Expression of this form: * `{$and: [{: {$gt: }}, {: {$lt: }}]}` * 2. An Aggregate Expression of this form: * `{$and: [{$gt: [, ]}, {$lt: [, ]}]}` * * `$gt` may also be `$gte`. `$lt` may also be `$lte`. * * @param {EncryptOptions} options * @returns {Promise} Returns a Promise that either resolves with the encrypted value or rejects with an error. */ async encryptExpression(expression, options) { return this._encrypt(expression, true, options); } /** * @callback ClientEncryption~decryptCallback * @param {Error} [err] If present, indicates an error that occurred in the process of decryption * @param {object} [result] If present, is the decrypted result */ /** * Explicitly decrypt a provided encrypted value * * @param {Buffer | Binary} value An encrypted value * @param {ClientEncryption~decryptCallback} callback Optional callback to invoke when value is decrypted * @returns {Promise|void} If no callback is provided, returns a Promise that either resolves with the decrypted value, or rejects with an error. If a callback is provided, returns nothing. * * @example * // Decrypting value with callback API * function decryptMyValue(value, callback) { * clientEncryption.decrypt(value, callback); * } * * @example * // Decrypting value with async/await API * async function decryptMyValue(value) { * return clientEncryption.decrypt(value); * } */ decrypt(value, callback) { const bson = this._bson; const valueBuffer = bson.serialize({ v: value }); const context = this._mongoCrypt.makeExplicitDecryptionContext(valueBuffer); const stateMachine = new StateMachine({ bson, proxyOptions: this._proxyOptions, tlsOptions: this._tlsOptions }); return promiseOrCallback(callback, cb => { stateMachine.execute(this, context, (err, result) => { if (err) { cb(err, null); return; } cb(null, result.v); }); }); } /** * Ask the user for KMS credentials. * * This returns anything that looks like the kmsProviders original input * option. It can be empty, and any provider specified here will override * the original ones. */ async askForKMSCredentials() { return this._onKmsProviderRefresh ? this._onKmsProviderRefresh() : loadCredentials(this._kmsProviders); } static get libmongocryptVersion() { return mc.MongoCrypt.libmongocryptVersion; } /** * A helper that perform explicit encryption of values and expressions. * Explicitly encrypt a provided value. Note that either `options.keyId` or `options.keyAltName` must * be specified. Specifying both `options.keyId` and `options.keyAltName` is considered an error. * * @param {*} value The value that you wish to encrypt. Must be of a type that can be serialized into BSON * @param {boolean} expressionMode - a boolean that indicates whether or not to encrypt the value as an expression * @param {EncryptOptions} options * @returns the raw result of the call to stateMachine.execute(). When expressionMode is set to true, the return * value will be a bson document. When false, the value will be a BSON Binary. * * @ignore * */ async _encrypt(value, expressionMode, options) { const bson = this._bson; const valueBuffer = bson.serialize({ v: value }); const contextOptions = Object.assign({}, options, { expressionMode }); if (options.keyId) { contextOptions.keyId = options.keyId.buffer; } if (options.keyAltName) { const keyAltName = options.keyAltName; if (options.keyId) { throw new TypeError(`"options" cannot contain both "keyId" and "keyAltName"`); } const keyAltNameType = typeof keyAltName; if (keyAltNameType !== 'string') { throw new TypeError( `"options.keyAltName" must be of type string, but was of type ${keyAltNameType}` ); } contextOptions.keyAltName = bson.serialize({ keyAltName }); } if ('rangeOptions' in options) { contextOptions.rangeOptions = bson.serialize(options.rangeOptions); } const stateMachine = new StateMachine({ bson, proxyOptions: this._proxyOptions, tlsOptions: this._tlsOptions }); const context = this._mongoCrypt.makeExplicitEncryptionContext(valueBuffer, contextOptions); const result = await stateMachine.executeAsync(this, context); return result.v; } } return { ClientEncryption }; }; libmongocrypt-1.8.4/bindings/node/lib/common.js000066400000000000000000000045261454530651600215520ustar00rootroot00000000000000'use strict'; /** * @ignore * Helper function for logging. Enabled by setting the environment flag MONGODB_CRYPT_DEBUG. * @param {*} msg Anything you want to be logged. */ function debug(msg) { if (process.env.MONGODB_CRYPT_DEBUG) { // eslint-disable-next-line no-console console.error(msg); } } /** * @ignore * Gets the database portion of a namespace string * @param {string} ns A string in the format of a namespace (database.collection) * @returns {string} The database portion of the namespace */ function databaseNamespace(ns) { return ns.split('.')[0]; } /** * @ignore * Gets the collection portion of a namespace string * @param {string} ns A string in the format of a namespace (database.collection) * @returns {string} The collection portion of the namespace */ function collectionNamespace(ns) { return ns.split('.').slice(1).join('.'); } function maybeCallback(promiseFn, callback) { const promise = promiseFn(); if (callback == null) { return promise; } promise.then( result => process.nextTick(callback, undefined, result), error => process.nextTick(callback, error) ); return; } /** * @ignore * A helper function. Invokes a function that takes a callback as the final * parameter. If a callback is supplied, then it is passed to the function. * If not, a Promise is returned that resolves/rejects with the result of the * callback * @param {Function} [callback] an optional callback. * @param {Function} fn A function that takes a callback * @returns {Promise|void} Returns nothing if a callback is supplied, else returns a Promise. */ function promiseOrCallback(callback, fn) { if (typeof callback === 'function') { fn(function (err) { if (err != null) { try { callback(err); } catch (error) { return process.nextTick(() => { throw error; }); } return; } callback.apply(this, arguments); }); return; } return new Promise((resolve, reject) => { fn(function (err, res) { if (err != null) { return reject(err); } if (arguments.length > 2) { return resolve(Array.prototype.slice.call(arguments, 1)); } resolve(res); }); }); } module.exports = { debug, databaseNamespace, collectionNamespace, promiseOrCallback, maybeCallback }; libmongocrypt-1.8.4/bindings/node/lib/cryptoCallbacks.js000066400000000000000000000037111454530651600233750ustar00rootroot00000000000000'use strict'; const crypto = require('crypto'); function makeAES256Hook(method, mode) { return function (key, iv, input, output) { let result; try { let cipher = crypto[method](mode, key, iv); cipher.setAutoPadding(false); result = cipher.update(input); const final = cipher.final(); if (final.length > 0) { result = Buffer.concat([result, final]); } } catch (e) { return e; } result.copy(output); return result.length; }; } function randomHook(buffer, count) { try { crypto.randomFillSync(buffer, 0, count); } catch (e) { return e; } return count; } function sha256Hook(input, output) { let result; try { result = crypto.createHash('sha256').update(input).digest(); } catch (e) { return e; } result.copy(output); return result.length; } function makeHmacHook(algorithm) { return (key, input, output) => { let result; try { result = crypto.createHmac(algorithm, key).update(input).digest(); } catch (e) { return e; } result.copy(output); return result.length; }; } function signRsaSha256Hook(key, input, output) { let result; try { const signer = crypto.createSign('sha256WithRSAEncryption'); const privateKey = Buffer.from( `-----BEGIN PRIVATE KEY-----\n${key.toString('base64')}\n-----END PRIVATE KEY-----\n` ); result = signer.update(input).end().sign(privateKey); } catch (e) { return e; } result.copy(output); return result.length; } module.exports = { aes256CbcEncryptHook: makeAES256Hook('createCipheriv', 'aes-256-cbc'), aes256CbcDecryptHook: makeAES256Hook('createDecipheriv', 'aes-256-cbc'), aes256CtrEncryptHook: makeAES256Hook('createCipheriv', 'aes-256-ctr'), aes256CtrDecryptHook: makeAES256Hook('createDecipheriv', 'aes-256-ctr'), randomHook, hmacSha512Hook: makeHmacHook('sha512'), hmacSha256Hook: makeHmacHook('sha256'), sha256Hook, signRsaSha256Hook }; libmongocrypt-1.8.4/bindings/node/lib/errors.js000066400000000000000000000035551454530651600215770ustar00rootroot00000000000000'use strict'; /** * @class * An error indicating that something went wrong specifically with MongoDB Client Encryption */ class MongoCryptError extends Error { constructor(message, options = {}) { super(message); if (options.cause != null) { this.cause = options.cause; } } get name() { return 'MongoCryptError'; } } /** * @experimental Public Technical Preview * @class * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create data keys */ class MongoCryptCreateDataKeyError extends MongoCryptError { constructor({ encryptedFields, cause }) { super(`Unable to complete creating data keys: ${cause.message}`, { cause }); this.encryptedFields = encryptedFields; } get name() { return 'MongoCryptCreateDataKeyError'; } } /** * @experimental Public Technical Preview * @class * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create a collection */ class MongoCryptCreateEncryptedCollectionError extends MongoCryptError { constructor({ encryptedFields, cause }) { super(`Unable to create collection: ${cause.message}`, { cause }); this.encryptedFields = encryptedFields; } get name() { return 'MongoCryptCreateEncryptedCollectionError'; } } /** * @class * An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials. */ class MongoCryptAzureKMSRequestError extends MongoCryptError { /** * @param {string} message * @param {object | undefined} body */ constructor(message, body) { super(message); this.body = body; } } class MongoCryptKMSRequestNetworkTimeoutError extends MongoCryptError {} module.exports = { MongoCryptError, MongoCryptKMSRequestNetworkTimeoutError, MongoCryptAzureKMSRequestError, MongoCryptCreateDataKeyError, MongoCryptCreateEncryptedCollectionError }; libmongocrypt-1.8.4/bindings/node/lib/index.js000066400000000000000000000036161454530651600213700ustar00rootroot00000000000000'use strict'; let defaultModule; function loadDefaultModule() { if (!defaultModule) { defaultModule = extension(require('mongodb')); } return defaultModule; } const { MongoCryptError, MongoCryptCreateEncryptedCollectionError, MongoCryptCreateDataKeyError, MongoCryptAzureKMSRequestError, MongoCryptKMSRequestNetworkTimeoutError } = require('./errors'); const { fetchAzureKMSToken } = require('./providers/index'); function extension(mongodb) { const modules = { mongodb }; modules.stateMachine = require('./stateMachine')(modules); modules.autoEncrypter = require('./autoEncrypter')(modules); modules.clientEncryption = require('./clientEncryption')(modules); const exports = { AutoEncrypter: modules.autoEncrypter.AutoEncrypter, ClientEncryption: modules.clientEncryption.ClientEncryption, MongoCryptError, MongoCryptCreateEncryptedCollectionError, MongoCryptCreateDataKeyError, MongoCryptAzureKMSRequestError, MongoCryptKMSRequestNetworkTimeoutError }; Object.defineProperty(exports, '___azureKMSProseTestExports', { enumerable: false, configurable: false, value: fetchAzureKMSToken }); return exports; } module.exports = { extension, MongoCryptError, MongoCryptCreateEncryptedCollectionError, MongoCryptCreateDataKeyError, MongoCryptAzureKMSRequestError, MongoCryptKMSRequestNetworkTimeoutError, get AutoEncrypter() { const m = loadDefaultModule(); delete module.exports.AutoEncrypter; module.exports.AutoEncrypter = m.AutoEncrypter; return m.AutoEncrypter; }, get ClientEncryption() { const m = loadDefaultModule(); delete module.exports.ClientEncryption; module.exports.ClientEncryption = m.ClientEncryption; return m.ClientEncryption; } }; Object.defineProperty(module.exports, '___azureKMSProseTestExports', { enumerable: false, configurable: false, value: fetchAzureKMSToken }); libmongocrypt-1.8.4/bindings/node/lib/mongocryptdManager.js000066400000000000000000000036551454530651600241240ustar00rootroot00000000000000'use strict'; const spawn = require('child_process').spawn; /** * @ignore * An internal class that handles spawning a mongocryptd. */ class MongocryptdManager { /** * @ignore * Creates a new Mongocryptd Manager * @param {AutoEncrypter~AutoEncryptionExtraOptions} [extraOptions] extra options that determine how/when to spawn a mongocryptd */ constructor(extraOptions) { extraOptions = extraOptions || {}; this.uri = typeof extraOptions.mongocryptdURI === 'string' && extraOptions.mongocryptdURI.length > 0 ? extraOptions.mongocryptdURI : MongocryptdManager.DEFAULT_MONGOCRYPTD_URI; this.bypassSpawn = !!extraOptions.mongocryptdBypassSpawn; this.spawnPath = extraOptions.mongocryptdSpawnPath || ''; this.spawnArgs = []; if (Array.isArray(extraOptions.mongocryptdSpawnArgs)) { this.spawnArgs = this.spawnArgs.concat(extraOptions.mongocryptdSpawnArgs); } if ( this.spawnArgs .filter(arg => typeof arg === 'string') .every(arg => arg.indexOf('--idleShutdownTimeoutSecs') < 0) ) { this.spawnArgs.push('--idleShutdownTimeoutSecs', 60); } } /** * @ignore * Will check to see if a mongocryptd is up. If it is not up, it will attempt * to spawn a mongocryptd in a detached process, and then wait for it to be up. * @param {Function} callback Invoked when we think a mongocryptd is up */ spawn(callback) { const cmdName = this.spawnPath || 'mongocryptd'; // Spawned with stdio: ignore and detatched:true // to ensure child can outlive parent. this._child = spawn(cmdName, this.spawnArgs, { stdio: 'ignore', detached: true }); this._child.on('error', () => {}); // unref child to remove handle from event loop this._child.unref(); process.nextTick(callback); } } MongocryptdManager.DEFAULT_MONGOCRYPTD_URI = 'mongodb://localhost:27020'; module.exports = { MongocryptdManager }; libmongocrypt-1.8.4/bindings/node/lib/providers/000077500000000000000000000000001454530651600217325ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/lib/providers/aws.js000066400000000000000000000014151454530651600230630ustar00rootroot00000000000000'use strict'; let awsCredentialProviders = null; /** @ignore */ async function loadAWSCredentials(kmsProviders) { if (awsCredentialProviders == null) { try { // Ensure you always wrap an optional require in the try block NODE-3199 awsCredentialProviders = require('@aws-sdk/credential-providers'); // eslint-disable-next-line no-empty } catch {} } if (awsCredentialProviders != null) { const { fromNodeProviderChain } = awsCredentialProviders; const provider = fromNodeProviderChain(); // The state machine is the only place calling this so it will // catch if there is a rejection here. const aws = await provider(); return { ...kmsProviders, aws }; } return kmsProviders; } module.exports = { loadAWSCredentials }; libmongocrypt-1.8.4/bindings/node/lib/providers/azure.js000066400000000000000000000100761454530651600234220ustar00rootroot00000000000000'use strict'; const { MongoCryptAzureKMSRequestError, MongoCryptKMSRequestNetworkTimeoutError } = require('../errors'); const utils = require('./utils'); const MINIMUM_TOKEN_REFRESH_IN_MILLISECONDS = 6000; /** * @class * @ignore */ class AzureCredentialCache { constructor() { /** * @type { { accessToken: string, expiresOnTimestamp: number } | null} */ this.cachedToken = null; } async getToken() { if (this.needsRefresh(this.cachedToken)) { this.cachedToken = await this._getToken(); } return { accessToken: this.cachedToken.accessToken }; } needsRefresh(token) { if (token == null) { return true; } const timeUntilExpirationMS = token.expiresOnTimestamp - Date.now(); return timeUntilExpirationMS <= MINIMUM_TOKEN_REFRESH_IN_MILLISECONDS; } /** * exposed for testing * @ignore */ resetCache() { this.cachedToken = null; } /** * exposed for testing * @ignore */ _getToken() { return fetchAzureKMSToken(); } } /** * @type{ AzureCredentialCache } * @ignore */ let tokenCache = new AzureCredentialCache(); /** * @typedef {object} KmsRequestResponsePayload * @property {string | undefined} access_token * @property {string | undefined} expires_in * * @ignore */ /** * @param { {body: string, status: number }} response * @returns { Promise<{ accessToken: string, expiresOnTimestamp: number } >} * @ignore */ async function parseResponse(response) { const { status, body: rawBody } = response; /** * @type { KmsRequestResponsePayload } */ const body = (() => { try { return JSON.parse(rawBody); } catch { throw new MongoCryptAzureKMSRequestError('Malformed JSON body in GET request.'); } })(); if (status !== 200) { throw new MongoCryptAzureKMSRequestError('Unable to complete request.', body); } if (!body.access_token) { throw new MongoCryptAzureKMSRequestError( 'Malformed response body - missing field `access_token`.' ); } if (!body.expires_in) { throw new MongoCryptAzureKMSRequestError( 'Malformed response body - missing field `expires_in`.' ); } const expiresInMS = Number(body.expires_in) * 1000; if (Number.isNaN(expiresInMS)) { throw new MongoCryptAzureKMSRequestError( 'Malformed response body - unable to parse int from `expires_in` field.' ); } return { accessToken: body.access_token, expiresOnTimestamp: Date.now() + expiresInMS }; } /** * @param {object} options * @param {object | undefined} [options.headers] * @param {URL | undefined} [options.url] * * @ignore */ function prepareRequest(options) { const url = options.url == null ? new URL('http://169.254.169.254/metadata/identity/oauth2/token') : new URL(options.url); url.searchParams.append('api-version', '2018-02-01'); url.searchParams.append('resource', 'https://vault.azure.net'); const headers = { ...options.headers, 'Content-Type': 'application/json', Metadata: true }; return { headers, url }; } /** * @typedef {object} AzureKMSRequestOptions * @property {object | undefined} headers * @property {URL | undefined} url * @ignore */ /** * @typedef {object} AzureKMSRequestResponse * @property {string} accessToken * @property {number} expiresOnTimestamp * @ignore */ /** * exported only for testing purposes in the driver * * @param {AzureKMSRequestOptions} options * @returns {Promise} * * @ignore */ async function fetchAzureKMSToken(options = {}) { const { headers, url } = prepareRequest(options); const response = await utils.get(url, { headers }).catch(error => { if (error instanceof MongoCryptKMSRequestNetworkTimeoutError) { throw new MongoCryptAzureKMSRequestError(`[Azure KMS] ${error.message}`); } throw error; }); return parseResponse(response); } /** * @ignore */ async function loadAzureCredentials(kmsProviders) { const azure = await tokenCache.getToken(); return { ...kmsProviders, azure }; } module.exports = { loadAzureCredentials, AzureCredentialCache, fetchAzureKMSToken, tokenCache }; libmongocrypt-1.8.4/bindings/node/lib/providers/gcp.js000066400000000000000000000011451454530651600230420ustar00rootroot00000000000000'use strict'; let gcpMetadata = null; /** @ignore */ async function loadGCPCredentials(kmsProviders) { if (gcpMetadata == null) { try { // Ensure you always wrap an optional require in the try block NODE-3199 gcpMetadata = require('gcp-metadata'); // eslint-disable-next-line no-empty } catch {} } if (gcpMetadata != null) { const { access_token: accessToken } = await gcpMetadata.instance({ property: 'service-accounts/default/token' }); return { ...kmsProviders, gcp: { accessToken } }; } return kmsProviders; } module.exports = { loadGCPCredentials }; libmongocrypt-1.8.4/bindings/node/lib/providers/index.js000066400000000000000000000031311454530651600233750ustar00rootroot00000000000000'use strict'; const { loadAWSCredentials } = require('./aws'); const { loadAzureCredentials, fetchAzureKMSToken } = require('./azure'); const { loadGCPCredentials } = require('./gcp'); /** * Auto credential fetching should only occur when the provider is defined on the kmsProviders map * and the settings are an empty object. * * This is distinct from a nullish provider key. * * @param {'aws' | 'gcp' | 'azure'} provider * @param {object} kmsProviders * * @ignore */ function isEmptyCredentials(provider, kmsProviders) { return ( provider in kmsProviders && kmsProviders[provider] != null && typeof kmsProviders[provider] === 'object' && Object.keys(kmsProviders[provider]).length === 0 ); } /** * Load cloud provider credentials for the user provided KMS providers. * Credentials will only attempt to get loaded if they do not exist * and no existing credentials will get overwritten. * * @param {object} kmsProviders - The user provided KMS providers. * @returns {object} The new kms providers. * * @ignore */ async function loadCredentials(kmsProviders) { let finalKMSProviders = kmsProviders; if (isEmptyCredentials('aws', kmsProviders)) { finalKMSProviders = await loadAWSCredentials(finalKMSProviders); } if (isEmptyCredentials('gcp', kmsProviders)) { finalKMSProviders = await loadGCPCredentials(finalKMSProviders); } if (isEmptyCredentials('azure', kmsProviders)) { finalKMSProviders = await loadAzureCredentials(finalKMSProviders); } return finalKMSProviders; } module.exports = { loadCredentials, isEmptyCredentials, fetchAzureKMSToken }; libmongocrypt-1.8.4/bindings/node/lib/providers/utils.js000066400000000000000000000017631454530651600234370ustar00rootroot00000000000000'use strict'; const { MongoCryptKMSRequestNetworkTimeoutError } = require('../errors'); const http = require('http'); /** * @param {URL | string} url * @param {http.RequestOptions} options * * @returns { Promise<{ body: string, status: number }> } * @ignore */ function get(url, options = {}) { return new Promise((resolve, reject) => { let timeoutId; const request = http .get(url, options, response => { response.setEncoding('utf8'); let body = ''; response.on('data', chunk => (body += chunk)); response.on('end', () => { clearTimeout(timeoutId); resolve({ status: response.statusCode, body }); }); }) .on('error', error => { clearTimeout(timeoutId); reject(error); }) .end(); timeoutId = setTimeout(() => { request.destroy( new MongoCryptKMSRequestNetworkTimeoutError(`request timed out after 10 seconds`) ); }, 10000); }); } module.exports = { get }; libmongocrypt-1.8.4/bindings/node/lib/stateMachine.js000066400000000000000000000416701454530651600226700ustar00rootroot00000000000000'use strict'; const { promisify } = require('util'); module.exports = function (modules) { const tls = require('tls'); const net = require('net'); const fs = require('fs'); const { once } = require('events'); const { SocksClient } = require('socks'); // Try first to import 4.x name, fallback to 3.x name const MongoNetworkTimeoutError = modules.mongodb.MongoNetworkTimeoutError || modules.mongodb.MongoTimeoutError; const common = require('./common'); const debug = common.debug; const databaseNamespace = common.databaseNamespace; const collectionNamespace = common.collectionNamespace; const { MongoCryptError } = require('./errors'); const { BufferPool } = require('./buffer_pool'); // libmongocrypt states const MONGOCRYPT_CTX_ERROR = 0; const MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1; const MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2; const MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3; const MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7; const MONGOCRYPT_CTX_NEED_KMS = 4; const MONGOCRYPT_CTX_READY = 5; const MONGOCRYPT_CTX_DONE = 6; const HTTPS_PORT = 443; const stateToString = new Map([ [MONGOCRYPT_CTX_ERROR, 'MONGOCRYPT_CTX_ERROR'], [MONGOCRYPT_CTX_NEED_MONGO_COLLINFO, 'MONGOCRYPT_CTX_NEED_MONGO_COLLINFO'], [MONGOCRYPT_CTX_NEED_MONGO_MARKINGS, 'MONGOCRYPT_CTX_NEED_MONGO_MARKINGS'], [MONGOCRYPT_CTX_NEED_MONGO_KEYS, 'MONGOCRYPT_CTX_NEED_MONGO_KEYS'], [MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS, 'MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS'], [MONGOCRYPT_CTX_NEED_KMS, 'MONGOCRYPT_CTX_NEED_KMS'], [MONGOCRYPT_CTX_READY, 'MONGOCRYPT_CTX_READY'], [MONGOCRYPT_CTX_DONE, 'MONGOCRYPT_CTX_DONE'] ]); const INSECURE_TLS_OPTIONS = [ 'tlsInsecure', 'tlsAllowInvalidCertificates', 'tlsAllowInvalidHostnames', 'tlsDisableOCSPEndpointCheck', 'tlsDisableCertificateRevocationCheck' ]; /** * @ignore * @callback StateMachine~executeCallback * @param {Error} [err] If present, indicates that the execute call failed with the given error * @param {object} [result] If present, is the result of executing the state machine. * @returns {void} */ /** * @ignore * @callback StateMachine~fetchCollectionInfoCallback * @param {Error} [err] If present, indicates that fetching the collection info failed with the given error * @param {object} [result] If present, is the fetched collection info for the first collection to match the given filter * @returns {void} */ /** * @ignore * @callback StateMachine~markCommandCallback * @param {Error} [err] If present, indicates that marking the command failed with the given error * @param {Buffer} [result] If present, is the marked command serialized into bson * @returns {void} */ /** * @ignore * @callback StateMachine~fetchKeysCallback * @param {Error} [err] If present, indicates that fetching the keys failed with the given error * @param {object[]} [result] If present, is all the keys from the keyVault collection that matched the given filter */ /** * @ignore * An internal class that executes across a MongoCryptContext until either * a finishing state or an error is reached. Do not instantiate directly. * @class StateMachine */ class StateMachine { constructor(options) { this.options = options || {}; this.bson = options.bson; this.executeAsync = promisify((autoEncrypter, context, callback) => this.execute(autoEncrypter, context, callback) ); } /** * @ignore * Executes the state machine according to the specification * @param {AutoEncrypter|ClientEncryption} autoEncrypter The JS encryption object * @param {object} context The C++ context object returned from the bindings * @param {StateMachine~executeCallback} callback Invoked with the result/error of executing the state machine * @returns {void} */ execute(autoEncrypter, context, callback) { const bson = this.bson; const keyVaultNamespace = autoEncrypter._keyVaultNamespace; const keyVaultClient = autoEncrypter._keyVaultClient; const metaDataClient = autoEncrypter._metaDataClient; const mongocryptdClient = autoEncrypter._mongocryptdClient; const mongocryptdManager = autoEncrypter._mongocryptdManager; debug(`[context#${context.id}] ${stateToString.get(context.state) || context.state}`); switch (context.state) { case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: { const filter = bson.deserialize(context.nextMongoOperation()); this.fetchCollectionInfo(metaDataClient, context.ns, filter, (err, collInfo) => { if (err) { return callback(err, null); } if (collInfo) { context.addMongoOperationResponse(collInfo); } context.finishMongoOperation(); this.execute(autoEncrypter, context, callback); }); return; } case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: { const command = context.nextMongoOperation(); this.markCommand(mongocryptdClient, context.ns, command, (err, markedCommand) => { if (err) { // If we are not bypassing spawning, then we should retry once on a MongoTimeoutError (server selection error) if ( err instanceof MongoNetworkTimeoutError && mongocryptdManager && !mongocryptdManager.bypassSpawn ) { mongocryptdManager.spawn(() => { // TODO: should we be shadowing the variables here? this.markCommand(mongocryptdClient, context.ns, command, (err, markedCommand) => { if (err) return callback(err, null); context.addMongoOperationResponse(markedCommand); context.finishMongoOperation(); this.execute(autoEncrypter, context, callback); }); }); return; } return callback(err, null); } context.addMongoOperationResponse(markedCommand); context.finishMongoOperation(); this.execute(autoEncrypter, context, callback); }); return; } case MONGOCRYPT_CTX_NEED_MONGO_KEYS: { const filter = context.nextMongoOperation(); this.fetchKeys(keyVaultClient, keyVaultNamespace, filter, (err, keys) => { if (err) return callback(err, null); keys.forEach(key => { context.addMongoOperationResponse(bson.serialize(key)); }); context.finishMongoOperation(); this.execute(autoEncrypter, context, callback); }); return; } case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: { autoEncrypter .askForKMSCredentials() .then(kmsProviders => { context.provideKMSProviders( !Buffer.isBuffer(kmsProviders) ? bson.serialize(kmsProviders) : kmsProviders ); this.execute(autoEncrypter, context, callback); }) .catch(err => { callback(err, null); }); return; } case MONGOCRYPT_CTX_NEED_KMS: { const promises = []; let request; while ((request = context.nextKMSRequest())) { promises.push(this.kmsRequest(request)); } Promise.all(promises) .then(() => { context.finishKMSRequests(); this.execute(autoEncrypter, context, callback); }) .catch(err => { callback(err, null); }); return; } // terminal states case MONGOCRYPT_CTX_READY: { const finalizedContext = context.finalize(); // TODO: Maybe rework the logic here so that instead of doing // the callback here, finalize stores the result, and then // we wait to MONGOCRYPT_CTX_DONE to do the callback if (context.state === MONGOCRYPT_CTX_ERROR) { const message = context.status.message || 'Finalization error'; callback(new MongoCryptError(message)); return; } callback(null, bson.deserialize(finalizedContext, this.options)); return; } case MONGOCRYPT_CTX_ERROR: { const message = context.status.message; callback(new MongoCryptError(message)); return; } case MONGOCRYPT_CTX_DONE: callback(); return; default: callback(new MongoCryptError(`Unknown state: ${context.state}`)); return; } } /** * @ignore * Handles the request to the KMS service. Exposed for testing purposes. Do not directly invoke. * @param {*} kmsContext A C++ KMS context returned from the bindings * @returns {Promise} A promise that resolves when the KMS reply has be fully parsed */ kmsRequest(request) { const parsedUrl = request.endpoint.split(':'); const port = parsedUrl[1] != null ? Number.parseInt(parsedUrl[1], 10) : HTTPS_PORT; const options = { host: parsedUrl[0], servername: parsedUrl[0], port }; const message = request.message; // TODO(NODE-3959): We can adopt `for-await on(socket, 'data')` with logic to control abort // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { const buffer = new BufferPool(); let socket; let rawSocket; function destroySockets() { for (const sock of [socket, rawSocket]) { if (sock) { sock.removeAllListeners(); sock.destroy(); } } } function ontimeout() { destroySockets(); reject(new MongoCryptError('KMS request timed out')); } function onerror(err) { destroySockets(); const mcError = new MongoCryptError('KMS request failed'); mcError.originalError = err; reject(mcError); } if (this.options.proxyOptions && this.options.proxyOptions.proxyHost) { rawSocket = net.connect({ host: this.options.proxyOptions.proxyHost, port: this.options.proxyOptions.proxyPort || 1080 }); rawSocket.on('timeout', ontimeout); rawSocket.on('error', onerror); try { await once(rawSocket, 'connect'); options.socket = ( await SocksClient.createConnection({ existing_socket: rawSocket, command: 'connect', destination: { host: options.host, port: options.port }, proxy: { // host and port are ignored because we pass existing_socket host: 'iLoveJavaScript', port: 0, type: 5, userId: this.options.proxyOptions.proxyUsername, password: this.options.proxyOptions.proxyPassword } }) ).socket; } catch (err) { return onerror(err); } } const tlsOptions = this.options.tlsOptions; if (tlsOptions) { const kmsProvider = request.kmsProvider; const providerTlsOptions = tlsOptions[kmsProvider]; if (providerTlsOptions) { const error = this.validateTlsOptions(kmsProvider, providerTlsOptions); if (error) reject(error); this.setTlsOptions(providerTlsOptions, options); } } socket = tls.connect(options, () => { socket.write(message); }); socket.once('timeout', ontimeout); socket.once('error', onerror); socket.on('data', data => { buffer.append(data); while (request.bytesNeeded > 0 && buffer.length) { const bytesNeeded = Math.min(request.bytesNeeded, buffer.length); request.addResponse(buffer.read(bytesNeeded)); } if (request.bytesNeeded <= 0) { // There's no need for any more activity on this socket at this point. destroySockets(); resolve(); } }); }); } /** * @ignore * Validates the provided TLS options are secure. * * @param {string} kmsProvider The KMS provider name. * @param {ClientEncryptionTLSOptions} tlsOptions The client TLS options for the provider. * * @returns {Error} If any option is invalid. */ validateTlsOptions(kmsProvider, tlsOptions) { const tlsOptionNames = Object.keys(tlsOptions); for (const option of INSECURE_TLS_OPTIONS) { if (tlsOptionNames.includes(option)) { return new MongoCryptError( `Insecure TLS options prohibited for ${kmsProvider}: ${option}` ); } } } /** * @ignore * Sets only the valid secure TLS options. * * @param {ClientEncryptionTLSOptions} tlsOptions The client TLS options for the provider. * @param {Object} options The existing connection options. */ setTlsOptions(tlsOptions, options) { if (tlsOptions.tlsCertificateKeyFile) { const cert = fs.readFileSync(tlsOptions.tlsCertificateKeyFile); options.cert = options.key = cert; } if (tlsOptions.tlsCAFile) { options.ca = fs.readFileSync(tlsOptions.tlsCAFile); } if (tlsOptions.tlsCertificateKeyFilePassword) { options.passphrase = tlsOptions.tlsCertificateKeyFilePassword; } } /** * @ignore * Fetches collection info for a provided namespace, when libmongocrypt * enters the `MONGOCRYPT_CTX_NEED_MONGO_COLLINFO` state. The result is * used to inform libmongocrypt of the schema associated with this * namespace. Exposed for testing purposes. Do not directly invoke. * * @param {MongoClient} client A MongoClient connected to the topology * @param {string} ns The namespace to list collections from * @param {object} filter A filter for the listCollections command * @param {StateMachine~fetchCollectionInfoCallback} callback Invoked with the info of the requested collection, or with an error */ fetchCollectionInfo(client, ns, filter, callback) { const bson = this.bson; const dbName = databaseNamespace(ns); client .db(dbName) .listCollections(filter, { promoteLongs: false, promoteValues: false }) .toArray() .then( collections => { const info = collections.length > 0 ? bson.serialize(collections[0]) : null; return callback(null, info); }, err => { callback(err, null); } ); } /** * @ignore * Calls to the mongocryptd to provide markings for a command. * Exposed for testing purposes. Do not directly invoke. * @param {MongoClient} client A MongoClient connected to a mongocryptd * @param {string} ns The namespace (database.collection) the command is being executed on * @param {object} command The command to execute. * @param {StateMachine~markCommandCallback} callback Invoked with the serialized and marked bson command, or with an error * @returns {void} */ markCommand(client, ns, command, callback) { const bson = this.bson; const options = { promoteLongs: false, promoteValues: false }; const dbName = databaseNamespace(ns); const rawCommand = bson.deserialize(command, options); client .db(dbName) .command(rawCommand, options) .then( response => { return callback(null, bson.serialize(response, this.options)); }, err => { callback(err, null); } ); } /** * @ignore * Requests keys from the keyVault collection on the topology. * Exposed for testing purposes. Do not directly invoke. * @param {MongoClient} client A MongoClient connected to the topology * @param {string} keyVaultNamespace The namespace (database.collection) of the keyVault Collection * @param {object} filter The filter for the find query against the keyVault Collection * @param {StateMachine~fetchKeysCallback} callback Invoked with the found keys, or with an error * @returns {void} */ fetchKeys(client, keyVaultNamespace, filter, callback) { const bson = this.bson; const dbName = databaseNamespace(keyVaultNamespace); const collectionName = collectionNamespace(keyVaultNamespace); filter = bson.deserialize(filter); client .db(dbName) .collection(collectionName, { readConcern: { level: 'majority' } }) .find(filter) .toArray() .then( keys => { return callback(null, keys); }, err => { callback(err, null); } ); } } return { StateMachine }; }; libmongocrypt-1.8.4/bindings/node/package-lock.json000066400000000000000000021160351454530651600223730ustar00rootroot00000000000000{ "name": "mongodb-client-encryption", "version": "2.8.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mongodb-client-encryption", "version": "2.8.0-alpha.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^4.3.0", "prebuild-install": "^7.1.1", "socks": "^2.6.1" }, "devDependencies": { "@types/sinon": "^10.0.13", "@types/sinon-chai": "^3.2.9", "chai": "^4.3.6", "chai-subset": "^1.6.0", "chalk": "^4.1.2", "clang-format": "^1.6.0", "dmd-clear": "^0.1.2", "eslint": "^8.8.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "jsdoc-to-markdown": "^7.1.1", "mocha": "^9.2.0", "mongodb": "^4.9.0", "node-gyp": "^9.3.1", "prebuild": "^11.0.2", "prettier": "^2.5.1", "sinon": "^13.0.1", "sinon-chai": "^3.7.0", "standard-version": "^9.3.2", "tar": "^6.1.11", "tsd": "^0.25.0" }, "engines": { "node": ">=12.9.0" }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.186.0", "gcp-metadata": "^5.2.0", "mongodb": ">=3.4.0" }, "peerDependenciesMeta": { "@aws-sdk/credential-providers": { "optional": true }, "gcp-metadata": { "optional": true } } }, "node_modules/@babel/code-frame": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dev": true, "dependencies": { "@babel/highlight": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/parser": { "version": "7.16.12", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", "dev": true, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.2.0", "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.4" }, "engines": { "node": ">=10.10.0" } }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" }, "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" }, "engines": { "node": ">= 8" } }, "node_modules/@npmcli/fs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/@npmcli/move-file": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.0.0.tgz", "integrity": "sha512-+shXA2X7KNP7H7qNbQTJ3SA+NQc0pZDSBrdvFSRwF8sAo/ohw+ZQFD8Moc+gnz51+1eRXtEQBpKWPiQ4jsRC/w==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.7.0" } }, "node_modules/@sinonjs/samsam": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.6.0", "lodash.get": "^4.4.2", "type-detect": "^4.0.8" } }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, "engines": { "node": ">= 10" } }, "node_modules/@tsd/typescript": { "version": "4.9.4", "resolved": "https://registry.npmjs.org/@tsd/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-70j1vy95LsMvciXWJLrQ9pQaaG1inJJ+gZ/dW/bPdzHUH1VTeSl3BBU6QxqFWh5IjPy6s7xHcUw45R71dw4J3w==", "dev": true }, "node_modules/@types/chai": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "node_modules/@types/eslint": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "node_modules/@types/estree": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, "node_modules/@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", "dev": true }, "node_modules/@types/markdown-it": { "version": "12.2.3", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", "dev": true, "dependencies": { "@types/linkify-it": "*", "@types/mdurl": "*" } }, "node_modules/@types/mdurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", "dev": true }, "node_modules/@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, "node_modules/@types/node": { "version": "18.7.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.6.tgz", "integrity": "sha512-EdxgKRXgYsNITy5mjjXjVE/CS8YENSdhiagGrLqjG0pvA2owgJ6i4l7wy/PFZGC0B1/H20lWKN7ONVDNYDZm7A==", "dev": true }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, "node_modules/@types/sinon": { "version": "10.0.13", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinon-chai": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.9.tgz", "integrity": "sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ==", "dev": true, "dependencies": { "@types/chai": "*", "@types/sinon": "*" } }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", "dev": true }, "node_modules/@types/webidl-conversions": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==", "dev": true }, "node_modules/@types/whatwg-url": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", "dev": true, "dependencies": { "@types/node": "*", "@types/webidl-conversions": "*" } }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "node_modules/acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true, "bin": { "acorn": "bin/acorn" }, "engines": { "node": ">=0.4.0" } }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/add-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", "dev": true }, "node_modules/after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "dependencies": { "debug": "4" }, "engines": { "node": ">= 6.0.0" } }, "node_modules/agentkeepalive": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", "dev": true, "dependencies": { "debug": "^4.1.0", "depd": "^2.0.0", "humanize-ms": "^1.2.1" }, "engines": { "node": ">= 8.0.0" } }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true, "engines": { "node": ">=0.4.2" } }, "node_modules/ansi": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", "dev": true }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/ansi-escape-sequences": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", "dev": true, "dependencies": { "array-back": "^3.0.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/ansi-escape-sequences/node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "dependencies": { "type-fest": "^0.21.3" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ansi-escapes/node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, "node_modules/are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "dev": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" }, "engines": { "node": ">=10" } }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "node_modules/array-back": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", "dev": true, "engines": { "node": ">=12.17" } }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, "node_modules/array-index": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz", "integrity": "sha1-7FanSe4QPk4Ix5C5w1PfFgVbl/k=", "dev": true, "dependencies": { "debug": "^2.2.0", "es6-symbol": "^3.0.2" }, "engines": { "node": "*" } }, "node_modules/array-index/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { "ms": "2.0.0" } }, "node_modules/array-index/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "dependencies": { "safer-buffer": "~2.1.0" } }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true, "engines": { "node": ">=0.8" } }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, "engines": { "node": "*" } }, "node_modules/async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true, "engines": { "node": "*" } }, "node_modules/aws4": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "dependencies": { "tweetnacl": "^0.14.3" } }, "node_modules/big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", "dev": true, "engines": { "node": ">=0.6" } }, "node_modules/binary": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", "dev": true, "dependencies": { "buffers": "~0.1.1", "chainsaw": "~0.1.0" }, "engines": { "node": "*" } }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dependencies": { "file-uri-to-path": "1.0.0" } }, "node_modules/bl": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz", "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==", "dev": true, "dependencies": { "readable-stream": "^3.0.1" } }, "node_modules/block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "dev": true, "dependencies": { "inherits": "~2.0.0" }, "engines": { "node": "0.4 || >=0.5.8" } }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "node_modules/bson": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", "dev": true, "dependencies": { "buffer": "^5.6.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "node_modules/buffer-from": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", "dev": true }, "node_modules/buffer-indexof-polyfill": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", "dev": true, "engines": { "node": ">=0.10" } }, "node_modules/buffer-shims": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, "node_modules/buffers": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true, "engines": { "node": ">=0.2.0" } }, "node_modules/cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "glob": "^8.0.1", "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", "unique-filename": "^2.0.0" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/cacache/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/cacache/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacache/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" } }, "node_modules/cacache/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" } }, "node_modules/cache-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", "dev": true, "dependencies": { "array-back": "^4.0.1", "fs-then-native": "^2.0.0", "mkdirp2": "^1.0.4" }, "engines": { "node": ">=8" } }, "node_modules/cache-point/node_modules/array-back": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/camelcase-keys": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", "quick-lru": "^4.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "dev": true, "dependencies": { "lodash": "^4.17.15" }, "engines": { "node": ">= 10" } }, "node_modules/chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" }, "engines": { "node": ">=4" } }, "node_modules/chai-subset": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/chai-subset/-/chai-subset-1.6.0.tgz", "integrity": "sha1-pdDKFOMpp5WW7XAFi2ZGvWmIz+k=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", "dev": true, "dependencies": { "traverse": ">=0.3.0 <0.4" }, "engines": { "node": "*" } }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true, "engines": { "node": "*" } }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/clang-format": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.6.0.tgz", "integrity": "sha512-W3/L7fWkA8DoLkz9UGjrRnNi+J5a5TuS2HDLqk6WsicpOzb66MBu4eY/EcXhicHriVnAXWQVyk5/VeHWY6w4ow==", "dev": true, "dependencies": { "async": "^1.5.2", "glob": "^7.0.0", "resolve": "^1.1.6" }, "bin": { "check-clang-format": "bin/check-clang-format.js", "clang-format": "index.js", "git-clang-format": "bin/git-clang-format" } }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "node_modules/cmake-js": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-5.2.0.tgz", "integrity": "sha512-/HLhzoBEOLKGdE1FLwH5ggzRt67AWTb4IErg4rm+bTC+R0DKUobojDyp17dSswDVPosdoPmHXjKxbJiyBZfQeg==", "dev": true, "dependencies": { "bluebird": "^3", "debug": "^4", "fs-extra": "^5.0.0", "is-iojs": "^1.0.1", "lodash": "^4", "memory-stream": "0", "npmlog": "^1.2.0", "rc": "^1.2.7", "request": "^2.54.0", "semver": "^5.0.3", "splitargs": "0", "tar": "^4", "traceur": "0.0.x", "unzipper": "^0.8.13", "url-join": "0", "which": "^1.0.9", "yargs": "^3.6.0" }, "bin": { "cmake-js": "bin/cmake-js" }, "engines": { "node": ">= 4.0.0" } }, "node_modules/cmake-js/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/cmake-js/node_modules/are-we-there-yet": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.0.6.tgz", "integrity": "sha1-otKMkxAqpsyWJFomy5VN4G7FPww=", "dev": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.0 || ^1.1.13" } }, "node_modules/cmake-js/node_modules/camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/cmake-js/node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "node_modules/cmake-js/node_modules/cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" } }, "node_modules/cmake-js/node_modules/fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "dependencies": { "minipass": "^2.6.0" } }, "node_modules/cmake-js/node_modules/gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", "dev": true, "dependencies": { "ansi": "^0.3.0", "has-unicode": "^2.0.0", "lodash.pad": "^4.1.0", "lodash.padend": "^4.1.0", "lodash.padstart": "^4.1.0" } }, "node_modules/cmake-js/node_modules/is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "dependencies": { "number-is-nan": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/cmake-js/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "node_modules/cmake-js/node_modules/minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "node_modules/cmake-js/node_modules/minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "dependencies": { "minipass": "^2.9.0" } }, "node_modules/cmake-js/node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { "minimist": "^1.2.5" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/cmake-js/node_modules/npmlog": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-1.2.1.tgz", "integrity": "sha1-KOe+YZYJtT960d0wChDWTXFiaLY=", "dev": true, "dependencies": { "ansi": "~0.3.0", "are-we-there-yet": "~1.0.0", "gauge": "~1.2.0" } }, "node_modules/cmake-js/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "node_modules/cmake-js/node_modules/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/cmake-js/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/cmake-js/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/cmake-js/node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/cmake-js/node_modules/string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/cmake-js/node_modules/strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/cmake-js/node_modules/tar": { "version": "4.4.19", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, "dependencies": { "chownr": "^1.1.4", "fs-minipass": "^1.2.7", "minipass": "^2.9.0", "minizlib": "^1.3.3", "mkdirp": "^0.5.5", "safe-buffer": "^5.2.1", "yallist": "^3.1.1" }, "engines": { "node": ">=4.5" } }, "node_modules/cmake-js/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/cmake-js/node_modules/wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/cmake-js/node_modules/y18n": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", "dev": true }, "node_modules/cmake-js/node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, "node_modules/cmake-js/node_modules/yargs": { "version": "3.32.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "dev": true, "dependencies": { "camelcase": "^2.0.1", "cliui": "^3.0.3", "decamelize": "^1.1.1", "os-locale": "^1.4.0", "string-width": "^1.0.1", "window-size": "^0.1.4", "y18n": "^3.2.0" } }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/collect-all": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", "dev": true, "dependencies": { "stream-connect": "^1.0.2", "stream-via": "^1.0.4" }, "engines": { "node": ">=0.10.0" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "node_modules/color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true, "bin": { "color-support": "bin.js" } }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, "dependencies": { "array-back": "^3.1.0", "find-replace": "^3.0.0", "lodash.camelcase": "^4.3.0", "typical": "^4.0.0" }, "engines": { "node": ">=4.0.0" } }, "node_modules/command-line-args/node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/command-line-args/node_modules/typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/command-line-tool": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", "dev": true, "dependencies": { "ansi-escape-sequences": "^4.0.0", "array-back": "^2.0.0", "command-line-args": "^5.0.0", "command-line-usage": "^4.1.0", "typical": "^2.6.1" }, "engines": { "node": ">=4.0.0" } }, "node_modules/command-line-tool/node_modules/array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "dependencies": { "typical": "^2.6.1" }, "engines": { "node": ">=4" } }, "node_modules/command-line-usage": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", "dev": true, "dependencies": { "ansi-escape-sequences": "^4.0.0", "array-back": "^2.0.0", "table-layout": "^0.4.2", "typical": "^2.6.1" }, "engines": { "node": ">=4.0.0" } }, "node_modules/command-line-usage/node_modules/array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "dependencies": { "typical": "^2.6.1" }, "engines": { "node": ">=4" } }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, "node_modules/common-sequence": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" } }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "node_modules/concat-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "engines": [ "node >= 6.0" ], "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.0.2", "typedarray": "^0.0.6" } }, "node_modules/concat-stream/node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "node_modules/config-master": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", "dev": true, "dependencies": { "walk-back": "^2.0.1" } }, "node_modules/config-master/node_modules/walk-back": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "node_modules/conventional-changelog": { "version": "3.1.24", "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", "dev": true, "dependencies": { "conventional-changelog-angular": "^5.0.12", "conventional-changelog-atom": "^2.0.8", "conventional-changelog-codemirror": "^2.0.8", "conventional-changelog-conventionalcommits": "^4.5.0", "conventional-changelog-core": "^4.2.1", "conventional-changelog-ember": "^2.0.9", "conventional-changelog-eslint": "^3.0.9", "conventional-changelog-express": "^2.0.6", "conventional-changelog-jquery": "^3.0.11", "conventional-changelog-jshint": "^2.0.9", "conventional-changelog-preset-loader": "^2.3.4" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-angular": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", "dev": true, "dependencies": { "compare-func": "^2.0.0", "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-atom": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", "dev": true, "dependencies": { "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-codemirror": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", "dev": true, "dependencies": { "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-config-spec": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", "dev": true }, "node_modules/conventional-changelog-conventionalcommits": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", "dev": true, "dependencies": { "compare-func": "^2.0.0", "lodash": "^4.17.15", "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-core": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", "dev": true, "dependencies": { "add-stream": "^1.0.0", "conventional-changelog-writer": "^5.0.0", "conventional-commits-parser": "^3.2.0", "dateformat": "^3.0.0", "get-pkg-repo": "^4.0.0", "git-raw-commits": "^2.0.8", "git-remote-origin-url": "^2.0.0", "git-semver-tags": "^4.1.1", "lodash": "^4.17.15", "normalize-package-data": "^3.0.0", "q": "^1.5.1", "read-pkg": "^3.0.0", "read-pkg-up": "^3.0.0", "through2": "^4.0.0" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-core/node_modules/through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "dependencies": { "readable-stream": "3" } }, "node_modules/conventional-changelog-ember": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", "dev": true, "dependencies": { "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-eslint": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", "dev": true, "dependencies": { "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-express": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", "dev": true, "dependencies": { "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-jquery": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", "dev": true, "dependencies": { "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-jshint": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", "dev": true, "dependencies": { "compare-func": "^2.0.0", "q": "^1.5.1" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-preset-loader": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-writer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", "dev": true, "dependencies": { "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", "handlebars": "^4.7.7", "json-stringify-safe": "^5.0.1", "lodash": "^4.17.15", "meow": "^8.0.0", "semver": "^6.0.0", "split": "^1.0.0", "through2": "^4.0.0" }, "bin": { "conventional-changelog-writer": "cli.js" }, "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-writer/node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/conventional-changelog-writer/node_modules/through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "dependencies": { "readable-stream": "3" } }, "node_modules/conventional-commits-filter": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, "dependencies": { "lodash.ismatch": "^4.4.0", "modify-values": "^1.0.0" }, "engines": { "node": ">=10" } }, "node_modules/conventional-commits-parser": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", "dev": true, "dependencies": { "is-text-path": "^1.0.1", "JSONStream": "^1.0.4", "lodash": "^4.17.15", "meow": "^8.0.0", "split2": "^3.0.0", "through2": "^4.0.0" }, "bin": { "conventional-commits-parser": "cli.js" }, "engines": { "node": ">=10" } }, "node_modules/conventional-commits-parser/node_modules/through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "dependencies": { "readable-stream": "3" } }, "node_modules/conventional-recommended-bump": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", "dev": true, "dependencies": { "concat-stream": "^2.0.0", "conventional-changelog-preset-loader": "^2.3.4", "conventional-commits-filter": "^2.0.7", "conventional-commits-parser": "^3.2.0", "git-raw-commits": "^2.0.8", "git-semver-tags": "^4.1.1", "meow": "^8.0.0", "q": "^1.5.1" }, "bin": { "conventional-recommended-bump": "cli.js" }, "engines": { "node": ">=10" } }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "dependencies": { "es5-ext": "^0.10.50", "type": "^1.0.1" } }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "dependencies": { "assert-plus": "^1.0.0" }, "engines": { "node": ">=0.10" } }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true, "engines": { "node": "*" } }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/decamelize-keys": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", "dev": true, "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/decamelize-keys/node_modules/map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dependencies": { "mimic-response": "^3.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "dependencies": { "type-detect": "^4.0.0" }, "engines": { "node": ">=0.12" } }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "engines": { "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", "dev": true, "engines": { "node": ">=0.10" } }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { "node": ">= 0.8" } }, "node_modules/detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/detect-libc": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.0.tgz", "integrity": "sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw==", "engines": { "node": ">=8" } }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, "engines": { "node": ">=0.3.1" } }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { "path-type": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/dir-glob/node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/dmd": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.1.0.tgz", "integrity": "sha512-0zQIJ873gay1scCTFZvHPWM9mVJBnaylB2NQDI8O9u8O32m00Jb6uxDKexZm8hjTRM7RiWe0FJ32pExHoXdwoQ==", "dev": true, "dependencies": { "array-back": "^6.2.2", "cache-point": "^2.0.0", "common-sequence": "^2.0.2", "file-set": "^4.0.2", "handlebars": "^4.7.7", "marked": "^4.0.12", "object-get": "^2.1.1", "reduce-flatten": "^3.0.1", "reduce-unique": "^2.0.1", "reduce-without": "^1.0.1", "test-value": "^3.0.0", "walk-back": "^5.1.0" }, "engines": { "node": ">=12" } }, "node_modules/dmd-clear": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/dmd-clear/-/dmd-clear-0.1.2.tgz", "integrity": "sha1-8GHFsHKya6IxZN1ajAvIZogzvhI=", "dev": true }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { "esutils": "^2.0.2" }, "engines": { "node": ">=6.0.0" } }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "dependencies": { "is-obj": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/dotgitignore": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", "dev": true, "dependencies": { "find-up": "^3.0.0", "minimatch": "^3.0.4" }, "engines": { "node": ">=6" } }, "node_modules/dotgitignore/node_modules/find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "dependencies": { "locate-path": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/dotgitignore/node_modules/locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/dotgitignore/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/dotgitignore/node_modules/p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "dependencies": { "p-limit": "^2.0.0" }, "engines": { "node": ">=6" } }, "node_modules/dotgitignore/node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "dependencies": { "readable-stream": "~1.1.9" } }, "node_modules/duplexer2/node_modules/readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "node_modules/duplexer2/node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "node_modules/each-series-async": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/each-series-async/-/each-series-async-1.0.1.tgz", "integrity": "sha512-G4zip/Ewpwr6JQxW7+2RNgkPd09h/UNec5UlvA/xKwl4qf5blyBNK6a/zjQc3MojgsxaOb93B9v3T92QU6IMVg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "node_modules/encoding": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "optional": true, "dependencies": { "iconv-lite": "^0.6.2" } }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dependencies": { "once": "^1.4.0" } }, "node_modules/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "dependencies": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.3", "next-tick": "~1.0.0" } }, "node_modules/es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "dependencies": { "d": "1", "es5-ext": "^0.10.35", "es6-symbol": "^3.1.1" } }, "node_modules/es6-symbol": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "dependencies": { "d": "^1.0.1", "ext": "^1.1.2" } }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.5", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.2.0", "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-config-prettier": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-formatter-pretty": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz", "integrity": "sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==", "dev": true, "dependencies": { "@types/eslint": "^7.2.13", "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", "eslint-rule-docs": "^1.1.5", "log-symbols": "^4.0.0", "plur": "^4.0.0", "string-width": "^4.2.0", "supports-hyperlinks": "^2.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint-plugin-prettier": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0" }, "engines": { "node": ">=6.0.0" }, "peerDependencies": { "eslint": ">=7.28.0", "prettier": ">=2.0.0" }, "peerDependenciesMeta": { "eslint-config-prettier": { "optional": true } } }, "node_modules/eslint-rule-docs": { "version": "1.1.235", "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz", "integrity": "sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==", "dev": true }, "node_modules/eslint-scope": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "dependencies": { "eslint-visitor-keys": "^2.0.0" }, "engines": { "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { "url": "https://github.com/sponsors/mysticatea" }, "peerDependencies": { "eslint": ">=5" } }, "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/eslint-visitor-keys": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/espree": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", "dev": true, "dependencies": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^3.1.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "dependencies": { "estraverse": "^5.1.0" }, "engines": { "node": ">=0.10" } }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/execspawn": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/execspawn/-/execspawn-1.0.1.tgz", "integrity": "sha1-gob53efOzeeQX73ATiTzaPI/jaY=", "dev": true, "dependencies": { "util-extend": "^1.0.1" } }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "engines": { "node": ">=6" } }, "node_modules/ext": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", "dev": true, "dependencies": { "type": "^2.5.0" } }, "node_modules/ext/node_modules/type": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", "dev": true }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true, "engines": [ "node >=0.6.0" ] }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "node_modules/fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" }, "engines": { "node": ">=8.6.0" } }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/figures/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, "engines": { "node": "^10.12.0 || >=12.0.0" } }, "node_modules/file-set": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", "dev": true, "dependencies": { "array-back": "^5.0.0", "glob": "^7.1.6" }, "engines": { "node": ">=10" } }, "node_modules/file-set/node_modules/array-back": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, "dependencies": { "array-back": "^3.0.1" }, "engines": { "node": ">=4.0.0" } }, "node_modules/find-replace/node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" }, "engines": { "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true, "engines": { "node": "*" } }, "node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" }, "engines": { "node": ">= 0.12" } }, "node_modules/fs-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", "dev": true, "dependencies": { "null-check": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "node_modules/fs-extra": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/fs-then-native": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", "dev": true, "engines": { "node": ">=4.0.0" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/fstream": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" }, "engines": { "node": ">=0.6" } }, "node_modules/fstream/node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { "minimist": "^1.2.5" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/fstream/node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, "node_modules/gauge": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.0.tgz", "integrity": "sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16" } }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true, "engines": { "node": "*" } }, "node_modules/get-pkg-repo": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", "dev": true, "dependencies": { "@hutson/parse-repository-url": "^3.0.0", "hosted-git-info": "^4.0.0", "through2": "^2.0.0", "yargs": "^16.2.0" }, "bin": { "get-pkg-repo": "src/cli.js" }, "engines": { "node": ">=6.9.0" } }, "node_modules/get-pkg-repo/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "node_modules/get-pkg-repo/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "node_modules/get-pkg-repo/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/get-pkg-repo/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/get-pkg-repo/node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "dependencies": { "assert-plus": "^1.0.0" } }, "node_modules/ghreleases": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/ghreleases/-/ghreleases-3.0.2.tgz", "integrity": "sha512-QiR9mIYvRG7hd8JuQYoxeBNOelVuTp2DpdiByRywbCDBSJufK9Vq7VuhD8B+5uviMxZx2AEkCzye61Us9gYgnw==", "dev": true, "dependencies": { "after": "~0.8.1", "ghrepos": "~2.1.0", "ghutils": "~3.2.0", "lodash.uniq": "^4.5.0", "simple-mime": "~0.1.0", "url-template": "~2.0.6" }, "engines": { "node": ">=6" } }, "node_modules/ghrepos": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ghrepos/-/ghrepos-2.1.0.tgz", "integrity": "sha512-6GM0ohSDTAv7xD6GsKfxJiV/CajoofRyUwu0E8l29d1o6lFAUxmmyMP/FH33afA20ZrXzxxcTtN6TsYvudMoAg==", "dev": true, "dependencies": { "ghutils": "~3.2.0" } }, "node_modules/ghutils": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/ghutils/-/ghutils-3.2.6.tgz", "integrity": "sha512-WpYHgLQkqU7Cv147wKUEThyj6qKHCdnAG2CL9RRsRQImVdLGdVqblJ3JUnj3ToQwgm1ALPS+FXgR0448AgGPUg==", "dev": true, "dependencies": { "jsonist": "~2.1.0", "xtend": "~4.0.1" } }, "node_modules/git-raw-commits": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", "dev": true, "dependencies": { "dargs": "^7.0.0", "lodash": "^4.17.15", "meow": "^8.0.0", "split2": "^3.0.0", "through2": "^4.0.0" }, "bin": { "git-raw-commits": "cli.js" }, "engines": { "node": ">=10" } }, "node_modules/git-raw-commits/node_modules/through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "dependencies": { "readable-stream": "3" } }, "node_modules/git-remote-origin-url": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", "dev": true, "dependencies": { "gitconfiglocal": "^1.0.0", "pify": "^2.3.0" }, "engines": { "node": ">=4" } }, "node_modules/git-semver-tags": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", "dev": true, "dependencies": { "meow": "^8.0.0", "semver": "^6.0.0" }, "bin": { "git-semver-tags": "cli.js" }, "engines": { "node": ">=10" } }, "node_modules/git-semver-tags/node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/gitconfiglocal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", "dev": true, "dependencies": { "ini": "^1.3.2" } }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" } }, "node_modules/globals": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, "node_modules/graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true, "engines": { "node": ">=4.x" } }, "node_modules/handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.0", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "bin": { "handlebars": "bin/handlebars" }, "engines": { "node": ">=0.4.7" }, "optionalDependencies": { "uglify-js": "^3.1.4" } }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", "dev": true, "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" }, "engines": { "node": ">=6" } }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { "function-bind": "^1.1.1" }, "engines": { "node": ">= 0.4.0" } }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "bin": { "he": "bin/he" } }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, "engines": { "node": ">=10" } }, "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "node_modules/http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" }, "engines": { "node": ">= 6" } }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" }, "engines": { "node": ">=0.8", "npm": ">=1.3.7" } }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "dependencies": { "agent-base": "6", "debug": "4" }, "engines": { "node": ">= 6" } }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "dependencies": { "ms": "^2.0.0" } }, "node_modules/hyperquest": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/hyperquest/-/hyperquest-2.1.3.tgz", "integrity": "sha512-fUuDOrB47PqNK/BAMOS13v41UoaqIxqSLHX6CAbOD7OfT+/GCWO1/vPLfTNutOeXrv1ikuaZ3yux+33Z9vh+rw==", "dev": true, "dependencies": { "buffer-from": "^0.1.1", "duplexer2": "~0.0.2", "through2": "~0.6.3" } }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true, "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, "node_modules/irregular-plurals": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.4.0.tgz", "integrity": "sha512-YXxECO/W6N9aMBVKMKKZ8TXESgq7EFrp3emCGGUcrYY1cgJIeZjoB75MTu8qi+NAKntS9NwPU8VdcQ3r6E6aWQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dev": true, "dependencies": { "has": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-iojs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-iojs/-/is-iojs-1.1.0.tgz", "integrity": "sha1-TBEDO11dlNbqs3dd7cm+fQCDJfE=", "dev": true }, "node_modules/is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "engines": { "node": ">=0.12.0" } }, "node_modules/is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", "dev": true, "dependencies": { "text-extensions": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/js2xmlparser": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", "dev": true, "dependencies": { "xmlcreate": "^2.0.4" } }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, "node_modules/jsdoc": { "version": "3.6.10", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.10.tgz", "integrity": "sha512-IdQ8ppSo5LKZ9o3M+LKIIK8i00DIe5msDvG3G81Km+1dhy0XrOWD0Ji8H61ElgyEj/O9KRLokgKbAM9XX9CJAg==", "dev": true, "dependencies": { "@babel/parser": "^7.9.4", "@types/markdown-it": "^12.2.3", "bluebird": "^3.7.2", "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.2", "klaw": "^4.0.1", "markdown-it": "^12.3.2", "markdown-it-anchor": "^8.4.1", "marked": "^4.0.10", "mkdirp": "^1.0.4", "requizzle": "^0.2.3", "strip-json-comments": "^3.1.0", "taffydb": "2.6.2", "underscore": "~1.13.2" }, "bin": { "jsdoc": "jsdoc.js" }, "engines": { "node": ">=8.15.0" } }, "node_modules/jsdoc-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.1.tgz", "integrity": "sha512-0pkuPCzVXiqsDAsVrNFXCkHzlyNepBIDVtwwehry4RJAnZmXtlAz7rh8F9FRz53u3NeynGbex+bpYWwi8lE66A==", "dev": true, "dependencies": { "array-back": "^6.2.2", "cache-point": "^2.0.0", "collect-all": "^1.0.4", "file-set": "^4.0.2", "fs-then-native": "^2.0.0", "jsdoc": "^3.6.10", "object-to-spawn-args": "^2.0.1", "temp-path": "^1.0.0", "walk-back": "^5.1.0" }, "engines": { "node": ">=12.17" } }, "node_modules/jsdoc-parse": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", "integrity": "sha512-n/hDGQJa69IBun1yZAjqzV4gVR41+flZ3bIlm9fKvNe2Xjsd1/+zCo2+R9ls8LxtePgIWbpA1jU7xkB2lRdLLg==", "dev": true, "dependencies": { "array-back": "^6.2.2", "lodash.omit": "^4.5.0", "lodash.pick": "^4.4.0", "reduce-extract": "^1.0.0", "sort-array": "^4.1.4", "test-value": "^3.0.0" }, "engines": { "node": ">=12" } }, "node_modules/jsdoc-to-markdown": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", "dev": true, "dependencies": { "array-back": "^6.2.2", "command-line-tool": "^0.8.0", "config-master": "^3.1.0", "dmd": "^6.1.0", "jsdoc-api": "^7.1.1", "jsdoc-parse": "^6.1.0", "walk-back": "^5.1.0" }, "bin": { "jsdoc2md": "bin/cli.js" }, "engines": { "node": ">=12.17" } }, "node_modules/jsdoc/node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/jsonist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/jsonist/-/jsonist-2.1.2.tgz", "integrity": "sha512-8yqmWJAC2VaYoSKQAbsfgCpGY5o/1etWzx6ZxaZrC4iGaHrHUZEo+a2MyF8w+2uTavTlHdLWaZUoR19UfBstxQ==", "dev": true, "dependencies": { "bl": "~3.0.0", "hyperquest": "~2.1.3", "json-stringify-safe": "~5.0.1", "xtend": "~4.0.1" } }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true, "engines": [ "node >= 0.2.0" ] }, "node_modules/JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "dependencies": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" }, "bin": { "JSONStream": "bin.js" }, "engines": { "node": "*" } }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" }, "engines": { "node": ">=0.6.0" } }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/klaw": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz", "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==", "dev": true, "engines": { "node": ">=14.14.0" } }, "node_modules/lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "dependencies": { "invert-kv": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, "node_modules/linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "dev": true, "dependencies": { "uc.micro": "^1.0.1" } }, "node_modules/listenercount": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", "dev": true }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/load-json-file/node_modules/pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, "node_modules/lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, "node_modules/lodash.omit": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", "dev": true }, "node_modules/lodash.pad": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", "dev": true }, "node_modules/lodash.padend": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", "dev": true }, "node_modules/lodash.padstart": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", "dev": true }, "node_modules/lodash.pick": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", "dev": true }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/loupe": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", "dev": true, "dependencies": { "get-func-name": "^2.0.0" } }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, "node_modules/make-fetch-happen": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" } }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", "dev": true, "dependencies": { "argparse": "^2.0.1", "entities": "~2.1.0", "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" }, "bin": { "markdown-it": "bin/markdown-it.js" } }, "node_modules/markdown-it-anchor": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.4.1.tgz", "integrity": "sha512-sLODeRetZ/61KkKLJElaU3NuU2z7MhXf12Ml1WJMSdwpngeofneCRF+JBbat8HiSqhniOMuTemXMrsI7hA6XyA==", "dev": true, "peerDependencies": { "@types/markdown-it": "*", "markdown-it": "*" } }, "node_modules/marked": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", "dev": true, "bin": { "marked": "bin/marked.js" }, "engines": { "node": ">= 12" } }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", "dev": true, "optional": true }, "node_modules/memory-stream": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-0.0.3.tgz", "integrity": "sha1-6+jdHDuLw4wOeUHp3dWuvmtN6D8=", "dev": true, "dependencies": { "readable-stream": "~1.0.26-2" } }, "node_modules/memory-stream/node_modules/readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "node_modules/memory-stream/node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "node_modules/meow": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "dependencies": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", "normalize-package-data": "^3.0.0", "read-pkg-up": "^7.0.1", "redent": "^3.0.0", "trim-newlines": "^3.0.0", "type-fest": "^0.18.0", "yargs-parser": "^20.2.3" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/meow/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/meow/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/meow/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/meow/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/meow/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/meow/node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/meow/node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", "parse-json": "^5.0.0", "type-fest": "^0.6.0" }, "engines": { "node": ">=8" } }, "node_modules/meow/node_modules/read-pkg-up": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/meow/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/meow/node_modules/type-fest": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "engines": { "node": ">= 8" } }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, "node_modules/mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.34", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "dev": true, "dependencies": { "mime-db": "1.51.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/minimist-options": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", "kind-of": "^6.0.3" }, "engines": { "node": ">= 6" } }, "node_modules/minipass": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", "dev": true, "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/minipass-collect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/minipass-fetch": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" } }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/mkdirp2": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", "dev": true }, "node_modules/mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha/node_modules/minimatch": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": ">=10" } }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/mongodb": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.0.tgz", "integrity": "sha512-tJJEFJz7OQTQPZeVHZJIeSOjMRqc5eSyXTt86vSQENEErpkiG7279tM/GT5AVZ7TgXNh9HQxoa2ZkbrANz5GQw==", "dev": true, "dependencies": { "bson": "^4.7.0", "denque": "^2.1.0", "mongodb-connection-string-url": "^2.5.3", "socks": "^2.7.0" }, "engines": { "node": ">=12.9.0" }, "optionalDependencies": { "saslprep": "^1.0.3" } }, "node_modules/mongodb-connection-string-url": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", "dev": true, "dependencies": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" } }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "node_modules/next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "node_modules/nise": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.8.3", "@sinonjs/fake-timers": ">=5", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "path-to-regexp": "^1.7.0" } }, "node_modules/node-abi": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.7.0.tgz", "integrity": "sha512-3J+U4CvxVNEk9+lGdJkmYbN8cIN0HMTDT9R0ezX7pmp7aD6BaKsfAHwVn3IvVg6pYIRUuQ+gHW1eawrvywnSQQ==", "dependencies": { "semver": "^7.3.5" }, "engines": { "node": ">=10" } }, "node_modules/node-addon-api": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" }, "node_modules/node-gyp": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.2", "which": "^2.0.2" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { "node": "^12.13 || ^14.13 || >=16" } }, "node_modules/node-ninja": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/node-ninja/-/node-ninja-1.0.2.tgz", "integrity": "sha1-IKCeV7kuLfWRmT1L8JisPnJwYrY=", "dev": true, "dependencies": { "fstream": "^1.0.0", "glob": "3 || 4 || 5 || 6 || 7", "graceful-fs": "^4.1.2", "minimatch": "3", "mkdirp": "^0.5.0", "nopt": "2 || 3", "npmlog": "0 || 1 || 2", "osenv": "0", "path-array": "^1.0.0", "request": "2", "rimraf": "2", "semver": "2.x || 3.x || 4 || 5", "tar": "^2.0.0", "which": "1" }, "bin": { "node-ninja": "bin/node-ninja.js" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/node-ninja/node_modules/are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "node_modules/node-ninja/node_modules/gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", "dev": true, "dependencies": { "ansi": "^0.3.0", "has-unicode": "^2.0.0", "lodash.pad": "^4.1.0", "lodash.padend": "^4.1.0", "lodash.padstart": "^4.1.0" } }, "node_modules/node-ninja/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "node_modules/node-ninja/node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { "minimist": "^1.2.5" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/node-ninja/node_modules/nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "node_modules/node-ninja/node_modules/npmlog": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", "dev": true, "dependencies": { "ansi": "~0.3.1", "are-we-there-yet": "~1.1.2", "gauge": "~1.2.5" } }, "node_modules/node-ninja/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "node_modules/node-ninja/node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "node_modules/node-ninja/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/node-ninja/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/node-ninja/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/node-ninja/node_modules/tar": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", "deprecated": "This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.", "dev": true, "dependencies": { "block-stream": "*", "fstream": "^1.0.12", "inherits": "2" } }, "node_modules/node-ninja/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/noop-logger": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", "dev": true }, "node_modules/nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, "dependencies": { "abbrev": "^1.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" }, "engines": { "node": ">=10" } }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/npm-path": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", "dev": true, "dependencies": { "which": "^1.2.10" }, "bin": { "npm-path": "bin/npm-path" }, "engines": { "node": ">=0.8" } }, "node_modules/npm-path/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/npm-which": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", "dev": true, "dependencies": { "commander": "^2.9.0", "npm-path": "^2.0.2", "which": "^1.2.10" }, "bin": { "npm-which": "bin/npm-which.js" }, "engines": { "node": ">=4.2.0" } }, "node_modules/npm-which/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/npmlog": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.0.tgz", "integrity": "sha512-03ppFRGlsyUaQFbGC2C8QWJN/C/K7PsfyD9aQdhVKAQIH4sQBc8WASqFBP7O+Ut4d2oo5LoeoboB3cGdBZSp6Q==", "dev": true, "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", "gauge": "^4.0.0", "set-blocking": "^2.0.0" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16" } }, "node_modules/null-check": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/nw-gyp": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/nw-gyp/-/nw-gyp-3.6.5.tgz", "integrity": "sha512-vYrOIYJEKpq9CfaHuiqEjV1rBYgr6uaUrPhPRiznb91LujkAUqGhQ5QqDC1bLdd+zo9jf2H0Zkl2M5zQB7+CuQ==", "dev": true, "dependencies": { "fstream": "^1.0.0", "glob": "^7.0.3", "graceful-fs": "^4.1.2", "minimatch": "^3.0.2", "mkdirp": "^0.5.0", "nopt": "2 || 3", "npmlog": "0 || 1 || 2 || 3 || 4", "osenv": "0", "request": "2", "rimraf": "2", "semver": "~5.3.0", "tar": "^2.0.0", "which": "1" }, "bin": { "nw-gyp": "bin/nw-gyp.js" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/nw-gyp/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/nw-gyp/node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "node_modules/nw-gyp/node_modules/are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "node_modules/nw-gyp/node_modules/gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "dependencies": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" } }, "node_modules/nw-gyp/node_modules/is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "dependencies": { "number-is-nan": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/nw-gyp/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "node_modules/nw-gyp/node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { "minimist": "^1.2.5" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/nw-gyp/node_modules/nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "node_modules/nw-gyp/node_modules/npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "dependencies": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", "gauge": "~2.7.3", "set-blocking": "~2.0.0" } }, "node_modules/nw-gyp/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "node_modules/nw-gyp/node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "node_modules/nw-gyp/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/nw-gyp/node_modules/semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/nw-gyp/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/nw-gyp/node_modules/string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/nw-gyp/node_modules/strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/nw-gyp/node_modules/tar": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", "deprecated": "This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.", "dev": true, "dependencies": { "block-stream": "*", "fstream": "^1.0.12", "inherits": "2" } }, "node_modules/nw-gyp/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true, "engines": { "node": "*" } }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/object-get": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", "dev": true }, "node_modules/object-to-spawn-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", "dev": true, "engines": { "node": ">=8.0.0" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dependencies": { "wrappy": "1" } }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.3" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "dependencies": { "lcid": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/osenv": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "dependencies": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "dependencies": { "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" }, "engines": { "node": ">=4" } }, "node_modules/path-array": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz", "integrity": "sha1-fi8PNfB6IBUSK4aLfqwOssT+wnE=", "dev": true, "dependencies": { "array-index": "^1.0.0" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "dev": true, "dependencies": { "isarray": "0.0.1" } }, "node_modules/path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "dependencies": { "pify": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/path-type/node_modules/pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, "engines": { "node": "*" } }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/plur": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", "dev": true, "dependencies": { "irregular-plurals": "^3.2.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/prebuild": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/prebuild/-/prebuild-11.0.3.tgz", "integrity": "sha512-0synbTNdYD9nkVFtVl0nbslM6AefnKRcvyvtDwv6qswh4gYCbdWGmir4G7YPPDa3VmKCZADVBYnkqNI3qKJy5Q==", "dev": true, "dependencies": { "cmake-js": "~5.2.0", "detect-libc": "^2.0.0", "each-series-async": "^1.0.1", "execspawn": "^1.0.1", "ghreleases": "^3.0.2", "github-from-package": "0.0.0", "glob": "^7.1.6", "minimist": "^1.1.2", "mkdirp": "^0.5.1", "napi-build-utils": "^1.0.1", "node-abi": "^3.0.0", "node-gyp": "^6.0.1", "node-ninja": "^1.0.1", "noop-logger": "^0.1.0", "npm-which": "^3.0.1", "npmlog": "^4.0.1", "nw-gyp": "^3.6.3", "rc": "^1.0.3", "run-waterfall": "^1.1.6", "tar-stream": "^2.1.0" }, "bin": { "prebuild": "bin.js" }, "engines": { "node": ">=10" } }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" }, "engines": { "node": ">=10" } }, "node_modules/prebuild/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/prebuild/node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "node_modules/prebuild/node_modules/are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "node_modules/prebuild/node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "node_modules/prebuild/node_modules/fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "dependencies": { "minipass": "^2.6.0" } }, "node_modules/prebuild/node_modules/gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "dependencies": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" } }, "node_modules/prebuild/node_modules/is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "dependencies": { "number-is-nan": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/prebuild/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "node_modules/prebuild/node_modules/minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "node_modules/prebuild/node_modules/minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "dependencies": { "minipass": "^2.9.0" } }, "node_modules/prebuild/node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { "minimist": "^1.2.5" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/prebuild/node_modules/node-gyp": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-6.1.0.tgz", "integrity": "sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw==", "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.2", "mkdirp": "^0.5.1", "nopt": "^4.0.1", "npmlog": "^4.1.2", "request": "^2.88.0", "rimraf": "^2.6.3", "semver": "^5.7.1", "tar": "^4.4.12", "which": "^1.3.1" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { "node": ">= 6.0.0" } }, "node_modules/prebuild/node_modules/nopt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dev": true, "dependencies": { "abbrev": "1", "osenv": "^0.1.4" }, "bin": { "nopt": "bin/nopt.js" } }, "node_modules/prebuild/node_modules/npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "dependencies": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", "gauge": "~2.7.3", "set-blocking": "~2.0.0" } }, "node_modules/prebuild/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "node_modules/prebuild/node_modules/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/prebuild/node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "node_modules/prebuild/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/prebuild/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/prebuild/node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/prebuild/node_modules/string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/prebuild/node_modules/strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/prebuild/node_modules/tar": { "version": "4.4.19", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, "dependencies": { "chownr": "^1.1.4", "fs-minipass": "^1.2.7", "minipass": "^2.9.0", "minizlib": "^1.3.3", "mkdirp": "^0.5.5", "safe-buffer": "^5.2.1", "yallist": "^3.1.1" }, "engines": { "node": ">=4.5" } }, "node_modules/prebuild/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/prebuild/node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" } }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, "engines": { "node": ">=6.0.0" } }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" }, "engines": { "node": ">=10" } }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true, "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" } }, "node_modules/qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true, "engines": { "node": ">=0.6" } }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "cli.js" } }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "engines": { "node": ">=0.10.0" } }, "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "dependencies": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/read-pkg-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "dependencies": { "find-up": "^2.0.0", "read-pkg": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/read-pkg-up/node_modules/find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "dependencies": { "locate-path": "^2.0.0" }, "engines": { "node": ">=4" } }, "node_modules/read-pkg-up/node_modules/locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/read-pkg-up/node_modules/p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "dependencies": { "p-try": "^1.0.0" }, "engines": { "node": ">=4" } }, "node_modules/read-pkg-up/node_modules/p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "dependencies": { "p-limit": "^1.1.0" }, "engines": { "node": ">=4" } }, "node_modules/read-pkg-up/node_modules/p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/read-pkg-up/node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/read-pkg/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "node_modules/read-pkg/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": ">=8.10.0" } }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/reduce-extract": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", "dev": true, "dependencies": { "test-value": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/reduce-extract/node_modules/array-back": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", "dev": true, "dependencies": { "typical": "^2.6.0" }, "engines": { "node": ">=0.12.0" } }, "node_modules/reduce-extract/node_modules/test-value": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", "dev": true, "dependencies": { "array-back": "^1.0.2", "typical": "^2.4.2" }, "engines": { "node": ">=0.10.0" } }, "node_modules/reduce-flatten": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/reduce-unique": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/reduce-without": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", "dev": true, "dependencies": { "test-value": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/reduce-without/node_modules/array-back": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", "dev": true, "dependencies": { "typical": "^2.6.0" }, "engines": { "node": ">=0.12.0" } }, "node_modules/reduce-without/node_modules/test-value": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", "dev": true, "dependencies": { "array-back": "^1.0.3", "typical": "^2.6.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/mysticatea" } }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, "engines": { "node": ">= 6" } }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", "dev": true, "dependencies": { "lodash": "^4.17.14" } }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "dependencies": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/rsvp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", "dev": true, "engines": { "node": "0.12.* || 4.* || 6.* || >= 7.*" } }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/run-waterfall": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.7.tgz", "integrity": "sha512-iFPgh7SatHXOG1ClcpdwHI63geV3Hc/iL6crGSyBlH2PY7Rm/za+zoKz6FfY/Qlw5K7JwSol8pseO8fN6CMhhQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "node_modules/saslprep": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", "dev": true, "optional": true, "dependencies": { "sparse-bitfield": "^3.0.3" }, "engines": { "node": ">=6" } }, "node_modules/semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/simple-get": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "node_modules/simple-mime": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/simple-mime/-/simple-mime-0.1.0.tgz", "integrity": "sha1-lfUXxPRm18/1YacfydqyWW6p7y4=", "dev": true, "engines": [ "node >= 0.2.0" ] }, "node_modules/sinon": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz", "integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.8.3", "@sinonjs/fake-timers": "^9.0.0", "@sinonjs/samsam": "^6.1.1", "diff": "^5.0.0", "nise": "^5.1.1", "supports-color": "^7.2.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/sinon" } }, "node_modules/sinon-chai": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", "dev": true, "peerDependencies": { "chai": "^4.0.0", "sinon": ">=4.0.0" } }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, "node_modules/socks": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" }, "engines": { "node": ">= 10.13.0", "npm": ">= 3.0.0" } }, "node_modules/socks-proxy-agent": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" }, "engines": { "node": ">= 10" } }, "node_modules/sort-array": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", "integrity": "sha512-GVFN6Y1sHKrWaSYOJTk9093ZnrBMc9sP3nuhANU44S4xg3rE6W5Z5WyamuT8VpMBbssnetx5faKCua0LEmUnSw==", "dev": true, "dependencies": { "array-back": "^5.0.0", "typical": "^6.0.1" }, "engines": { "node": ">=10" } }, "node_modules/sort-array/node_modules/array-back": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/sort-array/node_modules/typical": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", "dev": true, "dependencies": { "source-map": "0.1.32" } }, "node_modules/source-map-support/node_modules/source-map": { "version": "0.1.32", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", "dev": true, "dependencies": { "amdefine": ">=0.0.4" }, "engines": { "node": ">=0.8.0" } }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", "dev": true, "optional": true, "dependencies": { "memory-pager": "^1.0.2" } }, "node_modules/spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "dev": true }, "node_modules/split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "dependencies": { "through": "2" }, "engines": { "node": "*" } }, "node_modules/split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "dependencies": { "readable-stream": "^3.0.0" } }, "node_modules/splitargs": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", "integrity": "sha1-/p965lc3GzOxDLgNoUPPgknPazs=", "dev": true }, "node_modules/sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dev": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, "bin": { "sshpk-conv": "bin/sshpk-conv", "sshpk-sign": "bin/sshpk-sign", "sshpk-verify": "bin/sshpk-verify" }, "engines": { "node": ">=0.10.0" } }, "node_modules/ssri": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, "dependencies": { "minipass": "^3.1.1" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/standard-version": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", "dev": true, "dependencies": { "chalk": "^2.4.2", "conventional-changelog": "3.1.24", "conventional-changelog-config-spec": "2.1.0", "conventional-changelog-conventionalcommits": "4.6.1", "conventional-recommended-bump": "6.1.0", "detect-indent": "^6.0.0", "detect-newline": "^3.1.0", "dotgitignore": "^2.1.0", "figures": "^3.1.0", "find-up": "^5.0.0", "fs-access": "^1.0.1", "git-semver-tags": "^4.0.0", "semver": "^7.1.1", "stringify-package": "^1.0.1", "yargs": "^16.0.0" }, "bin": { "standard-version": "bin/cli.js" }, "engines": { "node": ">=10" } }, "node_modules/standard-version/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/standard-version/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/standard-version/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { "color-name": "1.1.3" } }, "node_modules/standard-version/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "node_modules/standard-version/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/standard-version/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/standard-version/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/stream-connect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", "dev": true, "dependencies": { "array-back": "^1.0.2" }, "engines": { "node": ">=0.10.0" } }, "node_modules/stream-connect/node_modules/array-back": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", "dev": true, "dependencies": { "typical": "^2.6.0" }, "engines": { "node": ">=0.12.0" } }, "node_modules/stream-via": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/stringify-package": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", "dev": true }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "dependencies": { "min-indent": "^1.0.0" }, "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/supports-hyperlinks": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" }, "engines": { "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/table-layout": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", "dev": true, "dependencies": { "array-back": "^2.0.0", "deep-extend": "~0.6.0", "lodash.padend": "^4.6.1", "typical": "^2.6.1", "wordwrapjs": "^3.0.0" }, "engines": { "node": ">=4.0.0" } }, "node_modules/table-layout/node_modules/array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "dependencies": { "typical": "^2.6.1" }, "engines": { "node": ">=4" } }, "node_modules/taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", "dev": true }, "node_modules/tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "dev": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^3.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, "engines": { "node": ">= 10" } }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "node_modules/tar-fs/node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" }, "engines": { "node": ">=6" } }, "node_modules/tar-stream/node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "node_modules/temp-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", "dev": true }, "node_modules/test-value": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", "dev": true, "dependencies": { "array-back": "^2.0.0", "typical": "^2.6.1" }, "engines": { "node": ">=4.0.0" } }, "node_modules/test-value/node_modules/array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "dependencies": { "typical": "^2.6.1" }, "engines": { "node": ">=4" } }, "node_modules/text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true, "engines": { "node": ">=0.10" } }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "node_modules/through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "dependencies": { "readable-stream": ">=1.0.33-1 <1.1.0-0", "xtend": ">=4.0.0 <4.1.0-0" } }, "node_modules/through2/node_modules/readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "node_modules/through2/node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" }, "engines": { "node": ">=0.8" } }, "node_modules/tr46": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "dev": true, "dependencies": { "punycode": "^2.1.1" }, "engines": { "node": ">=12" } }, "node_modules/traceur": { "version": "0.0.111", "resolved": "https://registry.npmjs.org/traceur/-/traceur-0.0.111.tgz", "integrity": "sha1-wE3nTRRpbDNzQn3k/Ajsr5E/w6E=", "dev": true, "dependencies": { "commander": "2.9.x", "glob": "5.0.x", "rsvp": "^3.0.13", "semver": "^4.3.3", "source-map-support": "~0.2.8" }, "bin": { "traceur": "traceur" }, "engines": { "node": ">=0.10" } }, "node_modules/traceur/node_modules/commander": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "dependencies": { "graceful-readlink": ">= 1.0.0" }, "engines": { "node": ">= 0.6.x" } }, "node_modules/traceur/node_modules/glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "dependencies": { "inflight": "^1.0.4", "inherits": "2", "minimatch": "2 || 3", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" } }, "node_modules/traceur/node_modules/semver": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/traverse": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", "dev": true, "engines": { "node": "*" } }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/tsd": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.25.0.tgz", "integrity": "sha512-liUlvKtsdr+70XEZP/kkF6U8+Q9URZi4Pw58ih7a9x3kjJblG8rdVgvG62xcvkgRva1q3yWX5qAxfYZuYiC5CA==", "dev": true, "dependencies": { "@tsd/typescript": "~4.9.3", "eslint-formatter-pretty": "^4.1.0", "globby": "^11.0.1", "meow": "^9.0.0", "path-exists": "^4.0.0", "read-pkg-up": "^7.0.0" }, "bin": { "tsd": "dist/cli.js" }, "engines": { "node": ">=14.16" } }, "node_modules/tsd/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tsd/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/tsd/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/tsd/node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", "dev": true, "dependencies": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", "decamelize": "^1.2.0", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", "normalize-package-data": "^3.0.0", "read-pkg-up": "^7.0.1", "redent": "^3.0.0", "trim-newlines": "^3.0.0", "type-fest": "^0.18.0", "yargs-parser": "^20.2.3" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tsd/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tsd/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/tsd/node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tsd/node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", "parse-json": "^5.0.0", "type-fest": "^0.6.0" }, "engines": { "node": ">=8" } }, "node_modules/tsd/node_modules/read-pkg-up": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tsd/node_modules/read-pkg-up/node_modules/type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/tsd/node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "node_modules/tsd/node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/tsd/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/tsd/node_modules/type-fest": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dependencies": { "safe-buffer": "^5.0.1" }, "engines": { "node": "*" } }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, "node_modules/type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", "dev": true }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "node_modules/typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", "dev": true }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, "node_modules/uglify-js": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.0.tgz", "integrity": "sha512-x+xdeDWq7FiORDvyIJ0q/waWd4PhjBNOm5dQUOq2AKC0IEjxOS66Ha9tctiVDGcRQuh69K7fgU5oRuTK4cysSg==", "dev": true, "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" }, "engines": { "node": ">=0.8.0" } }, "node_modules/underscore": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz", "integrity": "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==", "dev": true }, "node_modules/unique-filename": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, "dependencies": { "unique-slug": "^3.0.0" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/unique-slug": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "engines": { "node": ">= 4.0.0" } }, "node_modules/unzipper": { "version": "0.8.14", "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.8.14.tgz", "integrity": "sha512-8rFtE7EP5ssOwGpN2dt1Q4njl0N1hUXJ7sSPz0leU2hRdq6+pra57z4YPBlVqm40vcgv6ooKZEAx48fMTv9x4w==", "dev": true, "dependencies": { "big-integer": "^1.6.17", "binary": "~0.3.0", "bluebird": "~3.4.1", "buffer-indexof-polyfill": "~1.0.0", "duplexer2": "~0.1.4", "fstream": "~1.0.10", "listenercount": "~1.0.1", "readable-stream": "~2.1.5", "setimmediate": "~1.0.4" } }, "node_modules/unzipper/node_modules/bluebird": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true }, "node_modules/unzipper/node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "dependencies": { "readable-stream": "^2.0.2" } }, "node_modules/unzipper/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "node_modules/unzipper/node_modules/process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, "node_modules/unzipper/node_modules/readable-stream": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", "dev": true, "dependencies": { "buffer-shims": "^1.0.0", "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "~1.0.0", "process-nextick-args": "~1.0.6", "string_decoder": "~0.10.x", "util-deprecate": "~1.0.1" } }, "node_modules/unzipper/node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { "punycode": "^2.1.0" } }, "node_modules/url-join": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=", "dev": true }, "node_modules/url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=", "dev": true }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "node_modules/util-extend": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", "dev": true }, "node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true, "bin": { "uuid": "bin/uuid" } }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "engines": [ "node >=0.6.0" ], "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "node_modules/walk-back": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", "dev": true, "engines": { "node": ">=12.17" } }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, "engines": { "node": ">=12" } }, "node_modules/whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, "dependencies": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" }, "engines": { "node": ">=12" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "node_modules/window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", "dev": true, "bin": { "window-size": "cli.js" }, "engines": { "node": ">= 0.10.0" } }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "node_modules/wordwrapjs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", "dev": true, "dependencies": { "reduce-flatten": "^1.0.1", "typical": "^2.6.1" }, "engines": { "node": ">=4.0.0" } }, "node_modules/wordwrapjs/node_modules/reduce-flatten": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, "engines": { "node": ">=0.4" } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" } }, "node_modules/yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" }, "engines": { "node": ">=10" } }, "node_modules/yargs-unparser/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yargs-unparser/node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } }, "dependencies": { "@babel/code-frame": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dev": true, "requires": { "@babel/highlight": "^7.16.7" } }, "@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", "dev": true }, "@babel/highlight": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" } }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" } }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" } } } }, "@babel/parser": { "version": "7.16.12", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", "dev": true }, "@eslint/eslintrc": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.2.0", "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true } } }, "@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, "@humanwhocodes/config-array": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.4" } }, "@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, "@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", "dev": true }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "@npmcli/fs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "requires": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "@npmcli/move-file": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "dev": true, "requires": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.0.0.tgz", "integrity": "sha512-+shXA2X7KNP7H7qNbQTJ3SA+NQc0pZDSBrdvFSRwF8sAo/ohw+ZQFD8Moc+gnz51+1eRXtEQBpKWPiQ4jsRC/w==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" } }, "@sinonjs/samsam": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", "lodash.get": "^4.4.2", "type-detect": "^4.0.8" } }, "@sinonjs/text-encoding": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true }, "@tsd/typescript": { "version": "4.9.4", "resolved": "https://registry.npmjs.org/@tsd/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-70j1vy95LsMvciXWJLrQ9pQaaG1inJJ+gZ/dW/bPdzHUH1VTeSl3BBU6QxqFWh5IjPy6s7xHcUw45R71dw4J3w==", "dev": true }, "@types/chai": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "@types/eslint": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", "dev": true, "requires": { "@types/estree": "*", "@types/json-schema": "*" } }, "@types/estree": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", "dev": true }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, "@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", "dev": true }, "@types/markdown-it": { "version": "12.2.3", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", "dev": true, "requires": { "@types/linkify-it": "*", "@types/mdurl": "*" } }, "@types/mdurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", "dev": true }, "@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, "@types/node": { "version": "18.7.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.6.tgz", "integrity": "sha512-EdxgKRXgYsNITy5mjjXjVE/CS8YENSdhiagGrLqjG0pvA2owgJ6i4l7wy/PFZGC0B1/H20lWKN7ONVDNYDZm7A==", "dev": true }, "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, "@types/sinon": { "version": "10.0.13", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", "dev": true, "requires": { "@types/sinonjs__fake-timers": "*" } }, "@types/sinon-chai": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.9.tgz", "integrity": "sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ==", "dev": true, "requires": { "@types/chai": "*", "@types/sinon": "*" } }, "@types/sinonjs__fake-timers": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", "dev": true }, "@types/webidl-conversions": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==", "dev": true }, "@types/whatwg-url": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", "dev": true, "requires": { "@types/node": "*", "@types/webidl-conversions": "*" } }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "requires": {} }, "add-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", "dev": true }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "requires": { "debug": "4" } }, "agentkeepalive": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", "dev": true, "requires": { "debug": "^4.1.0", "depd": "^2.0.0", "humanize-ms": "^1.2.1" } }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, "ansi": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", "dev": true }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-escape-sequences": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", "dev": true, "requires": { "array-back": "^3.0.1" }, "dependencies": { "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true } } }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { "type-fest": "^0.21.3" }, "dependencies": { "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true } } }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { "color-convert": "^2.0.1" } }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, "are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" } }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "array-back": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", "dev": true }, "array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, "array-index": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz", "integrity": "sha1-7FanSe4QPk4Ix5C5w1PfFgVbl/k=", "dev": true, "requires": { "debug": "^2.2.0", "es6-symbol": "^3.0.2" }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "requires": { "safer-buffer": "~2.1.0" } }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, "aws4": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "requires": { "tweetnacl": "^0.14.3" } }, "big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", "dev": true }, "binary": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", "dev": true, "requires": { "buffers": "~0.1.1", "chainsaw": "~0.1.0" } }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "requires": { "file-uri-to-path": "1.0.0" } }, "bl": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz", "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==", "dev": true, "requires": { "readable-stream": "^3.0.1" } }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "dev": true, "requires": { "inherits": "~2.0.0" } }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { "fill-range": "^7.0.1" } }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "bson": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", "dev": true, "requires": { "buffer": "^5.6.0" } }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "buffer-from": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", "dev": true }, "buffer-indexof-polyfill": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", "dev": true }, "buffer-shims": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, "buffers": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true }, "cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "requires": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "glob": "^8.0.1", "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", "unique-filename": "^2.0.0" }, "dependencies": { "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "requires": { "balanced-match": "^1.0.0" } }, "glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true }, "minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } } } }, "cache-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", "dev": true, "requires": { "array-back": "^4.0.1", "fs-then-native": "^2.0.0", "mkdirp2": "^1.0.4" }, "dependencies": { "array-back": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true } } }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "camelcase-keys": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "requires": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", "quick-lru": "^4.0.1" } }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "dev": true, "requires": { "lodash": "^4.17.15" } }, "chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" } }, "chai-subset": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/chai-subset/-/chai-subset-1.6.0.tgz", "integrity": "sha1-pdDKFOMpp5WW7XAFi2ZGvWmIz+k=", "dev": true }, "chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", "dev": true, "requires": { "traverse": ">=0.3.0 <0.4" } }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "dependencies": { "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" } } } }, "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true }, "clang-format": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.6.0.tgz", "integrity": "sha512-W3/L7fWkA8DoLkz9UGjrRnNi+J5a5TuS2HDLqk6WsicpOzb66MBu4eY/EcXhicHriVnAXWQVyk5/VeHWY6w4ow==", "dev": true, "requires": { "async": "^1.5.2", "glob": "^7.0.0", "resolve": "^1.1.6" } }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "cmake-js": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-5.2.0.tgz", "integrity": "sha512-/HLhzoBEOLKGdE1FLwH5ggzRt67AWTb4IErg4rm+bTC+R0DKUobojDyp17dSswDVPosdoPmHXjKxbJiyBZfQeg==", "dev": true, "requires": { "bluebird": "^3", "debug": "^4", "fs-extra": "^5.0.0", "is-iojs": "^1.0.1", "lodash": "^4", "memory-stream": "0", "npmlog": "^1.2.0", "rc": "^1.2.7", "request": "^2.54.0", "semver": "^5.0.3", "splitargs": "0", "tar": "^4", "traceur": "0.0.x", "unzipper": "^0.8.13", "url-join": "0", "which": "^1.0.9", "yargs": "^3.6.0" }, "dependencies": { "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "are-we-there-yet": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.0.6.tgz", "integrity": "sha1-otKMkxAqpsyWJFomy5VN4G7FPww=", "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.0 || ^1.1.13" } }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" } }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "requires": { "minipass": "^2.6.0" } }, "gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", "dev": true, "requires": { "ansi": "^0.3.0", "has-unicode": "^2.0.0", "lodash.pad": "^4.1.0", "lodash.padend": "^4.1.0", "lodash.padstart": "^4.1.0" } }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "requires": { "minipass": "^2.9.0" } }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { "minimist": "^1.2.5" } }, "npmlog": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-1.2.1.tgz", "integrity": "sha1-KOe+YZYJtT960d0wChDWTXFiaLY=", "dev": true, "requires": { "ansi": "~0.3.0", "are-we-there-yet": "~1.0.0", "gauge": "~1.2.0" } }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" }, "dependencies": { "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true } } }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" }, "dependencies": { "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true } } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, "tar": { "version": "4.4.19", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, "requires": { "chownr": "^1.1.4", "fs-minipass": "^1.2.7", "minipass": "^2.9.0", "minizlib": "^1.3.3", "mkdirp": "^0.5.5", "safe-buffer": "^5.2.1", "yallist": "^3.1.1" } }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" } }, "y18n": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", "dev": true }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, "yargs": { "version": "3.32.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "dev": true, "requires": { "camelcase": "^2.0.1", "cliui": "^3.0.3", "decamelize": "^1.1.1", "os-locale": "^1.4.0", "string-width": "^1.0.1", "window-size": "^0.1.4", "y18n": "^3.2.0" } } } }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "collect-all": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", "dev": true, "requires": { "stream-connect": "^1.0.2", "stream-via": "^1.0.4" } }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { "color-name": "~1.1.4" } }, "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, "command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, "requires": { "array-back": "^3.1.0", "find-replace": "^3.0.0", "lodash.camelcase": "^4.3.0", "typical": "^4.0.0" }, "dependencies": { "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true }, "typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", "dev": true } } }, "command-line-tool": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", "dev": true, "requires": { "ansi-escape-sequences": "^4.0.0", "array-back": "^2.0.0", "command-line-args": "^5.0.0", "command-line-usage": "^4.1.0", "typical": "^2.6.1" }, "dependencies": { "array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "requires": { "typical": "^2.6.1" } } } }, "command-line-usage": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", "dev": true, "requires": { "ansi-escape-sequences": "^4.0.0", "array-back": "^2.0.0", "table-layout": "^0.4.2", "typical": "^2.6.1" }, "dependencies": { "array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "requires": { "typical": "^2.6.1" } } } }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, "common-sequence": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", "dev": true }, "compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "requires": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" } }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "concat-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.0.2", "typedarray": "^0.0.6" }, "dependencies": { "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true } } }, "config-master": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", "dev": true, "requires": { "walk-back": "^2.0.1" }, "dependencies": { "walk-back": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", "dev": true } } }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "conventional-changelog": { "version": "3.1.24", "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", "dev": true, "requires": { "conventional-changelog-angular": "^5.0.12", "conventional-changelog-atom": "^2.0.8", "conventional-changelog-codemirror": "^2.0.8", "conventional-changelog-conventionalcommits": "^4.5.0", "conventional-changelog-core": "^4.2.1", "conventional-changelog-ember": "^2.0.9", "conventional-changelog-eslint": "^3.0.9", "conventional-changelog-express": "^2.0.6", "conventional-changelog-jquery": "^3.0.11", "conventional-changelog-jshint": "^2.0.9", "conventional-changelog-preset-loader": "^2.3.4" } }, "conventional-changelog-angular": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", "dev": true, "requires": { "compare-func": "^2.0.0", "q": "^1.5.1" } }, "conventional-changelog-atom": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-codemirror": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-config-spec": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", "dev": true }, "conventional-changelog-conventionalcommits": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", "dev": true, "requires": { "compare-func": "^2.0.0", "lodash": "^4.17.15", "q": "^1.5.1" } }, "conventional-changelog-core": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", "dev": true, "requires": { "add-stream": "^1.0.0", "conventional-changelog-writer": "^5.0.0", "conventional-commits-parser": "^3.2.0", "dateformat": "^3.0.0", "get-pkg-repo": "^4.0.0", "git-raw-commits": "^2.0.8", "git-remote-origin-url": "^2.0.0", "git-semver-tags": "^4.1.1", "lodash": "^4.17.15", "normalize-package-data": "^3.0.0", "q": "^1.5.1", "read-pkg": "^3.0.0", "read-pkg-up": "^3.0.0", "through2": "^4.0.0" }, "dependencies": { "through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { "readable-stream": "3" } } } }, "conventional-changelog-ember": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-eslint": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-express": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jquery": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jshint": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", "dev": true, "requires": { "compare-func": "^2.0.0", "q": "^1.5.1" } }, "conventional-changelog-preset-loader": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", "dev": true }, "conventional-changelog-writer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", "dev": true, "requires": { "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", "handlebars": "^4.7.7", "json-stringify-safe": "^5.0.1", "lodash": "^4.17.15", "meow": "^8.0.0", "semver": "^6.0.0", "split": "^1.0.0", "through2": "^4.0.0" }, "dependencies": { "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { "readable-stream": "3" } } } }, "conventional-commits-filter": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, "requires": { "lodash.ismatch": "^4.4.0", "modify-values": "^1.0.0" } }, "conventional-commits-parser": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", "dev": true, "requires": { "is-text-path": "^1.0.1", "JSONStream": "^1.0.4", "lodash": "^4.17.15", "meow": "^8.0.0", "split2": "^3.0.0", "through2": "^4.0.0" }, "dependencies": { "through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { "readable-stream": "3" } } } }, "conventional-recommended-bump": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", "dev": true, "requires": { "concat-stream": "^2.0.0", "conventional-changelog-preset-loader": "^2.3.4", "conventional-commits-filter": "^2.0.7", "conventional-commits-parser": "^3.2.0", "git-raw-commits": "^2.0.8", "git-semver-tags": "^4.1.1", "meow": "^8.0.0", "q": "^1.5.1" } }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { "es5-ext": "^0.10.50", "type": "^1.0.1" } }, "dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { "assert-plus": "^1.0.0" } }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { "ms": "2.1.2" } }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decamelize-keys": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", "dev": true, "requires": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" }, "dependencies": { "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true } } }, "decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { "mimic-response": "^3.1.0" } }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { "type-detect": "^4.0.0" } }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, "denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", "dev": true }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true }, "detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true }, "detect-libc": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.0.tgz", "integrity": "sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw==" }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "requires": { "path-type": "^4.0.0" }, "dependencies": { "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true } } }, "dmd": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.1.0.tgz", "integrity": "sha512-0zQIJ873gay1scCTFZvHPWM9mVJBnaylB2NQDI8O9u8O32m00Jb6uxDKexZm8hjTRM7RiWe0FJ32pExHoXdwoQ==", "dev": true, "requires": { "array-back": "^6.2.2", "cache-point": "^2.0.0", "common-sequence": "^2.0.2", "file-set": "^4.0.2", "handlebars": "^4.7.7", "marked": "^4.0.12", "object-get": "^2.1.1", "reduce-flatten": "^3.0.1", "reduce-unique": "^2.0.1", "reduce-without": "^1.0.1", "test-value": "^3.0.0", "walk-back": "^5.1.0" } }, "dmd-clear": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/dmd-clear/-/dmd-clear-0.1.2.tgz", "integrity": "sha1-8GHFsHKya6IxZN1ajAvIZogzvhI=", "dev": true }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" } }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "requires": { "is-obj": "^2.0.0" } }, "dotgitignore": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", "dev": true, "requires": { "find-up": "^3.0.0", "minimatch": "^3.0.4" }, "dependencies": { "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" } }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" } }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { "p-limit": "^2.0.0" } }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } } }, "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { "readable-stream": "~1.1.9" }, "dependencies": { "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "each-series-async": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/each-series-async/-/each-series-async-1.0.1.tgz", "integrity": "sha512-G4zip/Ewpwr6JQxW7+2RNgkPd09h/UNec5UlvA/xKwl4qf5blyBNK6a/zjQc3MojgsxaOb93B9v3T92QU6IMVg==", "dev": true }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "encoding": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "optional": true, "requires": { "iconv-lite": "^0.6.2" } }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "requires": { "once": "^1.4.0" } }, "entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true }, "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true }, "err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, "es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.3", "next-tick": "~1.0.0" } }, "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.35", "es6-symbol": "^3.1.1" } }, "es6-symbol": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { "d": "^1.0.1", "ext": "^1.1.2" } }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, "eslint": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", "dev": true, "requires": { "@eslint/eslintrc": "^1.0.5", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.2.0", "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" } }, "eslint-config-prettier": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", "dev": true, "requires": {} }, "eslint-formatter-pretty": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz", "integrity": "sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==", "dev": true, "requires": { "@types/eslint": "^7.2.13", "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", "eslint-rule-docs": "^1.1.5", "log-symbols": "^4.0.0", "plur": "^4.0.0", "string-width": "^4.2.0", "supports-hyperlinks": "^2.0.0" } }, "eslint-plugin-prettier": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" } }, "eslint-rule-docs": { "version": "1.1.235", "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz", "integrity": "sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==", "dev": true }, "eslint-scope": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "requires": { "eslint-visitor-keys": "^2.0.0" }, "dependencies": { "eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true } } }, "eslint-visitor-keys": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", "dev": true }, "espree": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", "dev": true, "requires": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^3.1.0" } }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" } }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { "estraverse": "^5.2.0" } }, "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "execspawn": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/execspawn/-/execspawn-1.0.1.tgz", "integrity": "sha1-gob53efOzeeQX73ATiTzaPI/jaY=", "dev": true, "requires": { "util-extend": "^1.0.1" } }, "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, "ext": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", "dev": true, "requires": { "type": "^2.5.0" }, "dependencies": { "type": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", "dev": true } } }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, "fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" }, "dependencies": { "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" } } } }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" } }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" }, "dependencies": { "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true } } }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { "flat-cache": "^3.0.4" } }, "file-set": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", "dev": true, "requires": { "array-back": "^5.0.0", "glob": "^7.1.6" }, "dependencies": { "array-back": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", "dev": true } } }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { "to-regex-range": "^5.0.1" } }, "find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, "requires": { "array-back": "^3.0.1" }, "dependencies": { "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true } } }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" } }, "flatted": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, "fs-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", "dev": true, "requires": { "null-check": "^1.0.0" } }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "requires": { "minipass": "^3.0.0" } }, "fs-then-native": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", "dev": true }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "fstream": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" }, "dependencies": { "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { "minimist": "^1.2.5" } }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" } } } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, "gauge": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.0.tgz", "integrity": "sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw==", "dev": true, "requires": { "ansi-regex": "^5.0.1", "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" } }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, "get-pkg-repo": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", "dev": true, "requires": { "@hutson/parse-repository-url": "^3.0.0", "hosted-git-info": "^4.0.0", "through2": "^2.0.0", "yargs": "^16.2.0" }, "dependencies": { "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" } }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } } } }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { "assert-plus": "^1.0.0" } }, "ghreleases": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/ghreleases/-/ghreleases-3.0.2.tgz", "integrity": "sha512-QiR9mIYvRG7hd8JuQYoxeBNOelVuTp2DpdiByRywbCDBSJufK9Vq7VuhD8B+5uviMxZx2AEkCzye61Us9gYgnw==", "dev": true, "requires": { "after": "~0.8.1", "ghrepos": "~2.1.0", "ghutils": "~3.2.0", "lodash.uniq": "^4.5.0", "simple-mime": "~0.1.0", "url-template": "~2.0.6" } }, "ghrepos": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ghrepos/-/ghrepos-2.1.0.tgz", "integrity": "sha512-6GM0ohSDTAv7xD6GsKfxJiV/CajoofRyUwu0E8l29d1o6lFAUxmmyMP/FH33afA20ZrXzxxcTtN6TsYvudMoAg==", "dev": true, "requires": { "ghutils": "~3.2.0" } }, "ghutils": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/ghutils/-/ghutils-3.2.6.tgz", "integrity": "sha512-WpYHgLQkqU7Cv147wKUEThyj6qKHCdnAG2CL9RRsRQImVdLGdVqblJ3JUnj3ToQwgm1ALPS+FXgR0448AgGPUg==", "dev": true, "requires": { "jsonist": "~2.1.0", "xtend": "~4.0.1" } }, "git-raw-commits": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", "dev": true, "requires": { "dargs": "^7.0.0", "lodash": "^4.17.15", "meow": "^8.0.0", "split2": "^3.0.0", "through2": "^4.0.0" }, "dependencies": { "through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { "readable-stream": "3" } } } }, "git-remote-origin-url": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", "dev": true, "requires": { "gitconfiglocal": "^1.0.0", "pify": "^2.3.0" } }, "git-semver-tags": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", "dev": true, "requires": { "meow": "^8.0.0", "semver": "^6.0.0" }, "dependencies": { "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, "gitconfiglocal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", "dev": true, "requires": { "ini": "^1.3.2" } }, "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "requires": { "is-glob": "^4.0.3" } }, "globals": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "dev": true, "requires": { "type-fest": "^0.20.2" } }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "graceful-fs": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, "graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, "handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { "minimist": "^1.2.5", "neo-async": "^2.6.0", "source-map": "^0.6.1", "uglify-js": "^3.1.4", "wordwrap": "^1.0.0" } }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true }, "har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, "hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" } }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "requires": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "requires": { "agent-base": "6", "debug": "4" } }, "humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "requires": { "ms": "^2.0.0" } }, "hyperquest": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/hyperquest/-/hyperquest-2.1.3.tgz", "integrity": "sha512-fUuDOrB47PqNK/BAMOS13v41UoaqIxqSLHX6CAbOD7OfT+/GCWO1/vPLfTNutOeXrv1ikuaZ3yux+33Z9vh+rw==", "dev": true, "requires": { "buffer-from": "^0.1.1", "duplexer2": "~0.0.2", "through2": "~0.6.3" } }, "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "optional": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, "irregular-plurals": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.4.0.tgz", "integrity": "sha512-YXxECO/W6N9aMBVKMKKZ8TXESgq7EFrp3emCGGUcrYY1cgJIeZjoB75MTu8qi+NAKntS9NwPU8VdcQ3r6E6aWQ==", "dev": true }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { "binary-extensions": "^2.0.0" } }, "is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dev": true, "requires": { "has": "^1.0.3" } }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, "is-iojs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-iojs/-/is-iojs-1.1.0.tgz", "integrity": "sha1-TBEDO11dlNbqs3dd7cm+fQCDJfE=", "dev": true }, "is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", "dev": true, "requires": { "text-extensions": "^1.0.0" } }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" } }, "js2xmlparser": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", "dev": true, "requires": { "xmlcreate": "^2.0.4" } }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, "jsdoc": { "version": "3.6.10", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.10.tgz", "integrity": "sha512-IdQ8ppSo5LKZ9o3M+LKIIK8i00DIe5msDvG3G81Km+1dhy0XrOWD0Ji8H61ElgyEj/O9KRLokgKbAM9XX9CJAg==", "dev": true, "requires": { "@babel/parser": "^7.9.4", "@types/markdown-it": "^12.2.3", "bluebird": "^3.7.2", "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.2", "klaw": "^4.0.1", "markdown-it": "^12.3.2", "markdown-it-anchor": "^8.4.1", "marked": "^4.0.10", "mkdirp": "^1.0.4", "requizzle": "^0.2.3", "strip-json-comments": "^3.1.0", "taffydb": "2.6.2", "underscore": "~1.13.2" }, "dependencies": { "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true } } }, "jsdoc-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.1.tgz", "integrity": "sha512-0pkuPCzVXiqsDAsVrNFXCkHzlyNepBIDVtwwehry4RJAnZmXtlAz7rh8F9FRz53u3NeynGbex+bpYWwi8lE66A==", "dev": true, "requires": { "array-back": "^6.2.2", "cache-point": "^2.0.0", "collect-all": "^1.0.4", "file-set": "^4.0.2", "fs-then-native": "^2.0.0", "jsdoc": "^3.6.10", "object-to-spawn-args": "^2.0.1", "temp-path": "^1.0.0", "walk-back": "^5.1.0" } }, "jsdoc-parse": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", "integrity": "sha512-n/hDGQJa69IBun1yZAjqzV4gVR41+flZ3bIlm9fKvNe2Xjsd1/+zCo2+R9ls8LxtePgIWbpA1jU7xkB2lRdLLg==", "dev": true, "requires": { "array-back": "^6.2.2", "lodash.omit": "^4.5.0", "lodash.pick": "^4.4.0", "reduce-extract": "^1.0.0", "sort-array": "^4.1.4", "test-value": "^3.0.0" } }, "jsdoc-to-markdown": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", "dev": true, "requires": { "array-back": "^6.2.2", "command-line-tool": "^0.8.0", "config-master": "^3.1.0", "dmd": "^6.1.0", "jsdoc-api": "^7.1.1", "jsdoc-parse": "^6.1.0", "walk-back": "^5.1.0" } }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, "json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { "graceful-fs": "^4.1.6" } }, "jsonist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/jsonist/-/jsonist-2.1.2.tgz", "integrity": "sha512-8yqmWJAC2VaYoSKQAbsfgCpGY5o/1etWzx6ZxaZrC4iGaHrHUZEo+a2MyF8w+2uTavTlHdLWaZUoR19UfBstxQ==", "dev": true, "requires": { "bl": "~3.0.0", "hyperquest": "~2.1.3", "json-stringify-safe": "~5.0.1", "xtend": "~4.0.1" } }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "requires": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" } }, "jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, "just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, "klaw": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz", "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==", "dev": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { "invert-kv": "^1.0.0" } }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, "linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "dev": true, "requires": { "uc.micro": "^1.0.1" } }, "listenercount": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", "dev": true }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" }, "dependencies": { "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true } } }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { "p-locate": "^5.0.0" } }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, "lodash.omit": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", "dev": true }, "lodash.pad": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", "dev": true }, "lodash.padend": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", "dev": true }, "lodash.padstart": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", "dev": true }, "lodash.pick": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", "dev": true }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "loupe": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", "dev": true, "requires": { "get-func-name": "^2.0.0" } }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { "yallist": "^4.0.0" } }, "make-fetch-happen": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, "requires": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" }, "dependencies": { "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true } } }, "map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, "markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", "dev": true, "requires": { "argparse": "^2.0.1", "entities": "~2.1.0", "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" } }, "markdown-it-anchor": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.4.1.tgz", "integrity": "sha512-sLODeRetZ/61KkKLJElaU3NuU2z7MhXf12Ml1WJMSdwpngeofneCRF+JBbat8HiSqhniOMuTemXMrsI7hA6XyA==", "dev": true, "requires": {} }, "marked": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", "dev": true }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, "memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", "dev": true, "optional": true }, "memory-stream": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-0.0.3.tgz", "integrity": "sha1-6+jdHDuLw4wOeUHp3dWuvmtN6D8=", "dev": true, "requires": { "readable-stream": "~1.0.26-2" }, "dependencies": { "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "meow": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "requires": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", "normalize-package-data": "^3.0.0", "read-pkg-up": "^7.0.1", "redent": "^3.0.0", "trim-newlines": "^3.0.0", "type-fest": "^0.18.0", "yargs-parser": "^20.2.3" }, "dependencies": { "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { "p-locate": "^4.1.0" } }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" } }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { "p-limit": "^2.2.0" } }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "requires": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", "parse-json": "^5.0.0", "type-fest": "^0.6.0" }, "dependencies": { "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true } } }, "read-pkg-up": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" }, "dependencies": { "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true } } }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "type-fest": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true } } }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" } }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "dev": true }, "mime-types": { "version": "2.1.34", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "dev": true, "requires": { "mime-db": "1.51.0" } }, "mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "minimist-options": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", "kind-of": "^6.0.3" } }, "minipass": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", "dev": true, "requires": { "yallist": "^4.0.0" } }, "minipass-collect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, "requires": { "minipass": "^3.0.0" } }, "minipass-fetch": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, "requires": { "encoding": "^0.1.13", "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" } }, "minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "requires": { "minipass": "^3.0.0" } }, "minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "requires": { "minipass": "^3.0.0" } }, "minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "requires": { "minipass": "^3.0.0" } }, "minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "requires": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "mkdirp2": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", "dev": true }, "mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "dependencies": { "minimatch": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, "modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true }, "mongodb": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.0.tgz", "integrity": "sha512-tJJEFJz7OQTQPZeVHZJIeSOjMRqc5eSyXTt86vSQENEErpkiG7279tM/GT5AVZ7TgXNh9HQxoa2ZkbrANz5GQw==", "dev": true, "requires": { "bson": "^4.7.0", "denque": "^2.1.0", "mongodb-connection-string-url": "^2.5.3", "saslprep": "^1.0.3", "socks": "^2.7.0" } }, "mongodb-connection-string-url": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", "dev": true, "requires": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" } }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, "napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "nise": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.3", "@sinonjs/fake-timers": ">=5", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "path-to-regexp": "^1.7.0" } }, "node-abi": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.7.0.tgz", "integrity": "sha512-3J+U4CvxVNEk9+lGdJkmYbN8cIN0HMTDT9R0ezX7pmp7aD6BaKsfAHwVn3IvVg6pYIRUuQ+gHW1eawrvywnSQQ==", "requires": { "semver": "^7.3.5" } }, "node-addon-api": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" }, "node-gyp": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", "dev": true, "requires": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.2", "which": "^2.0.2" } }, "node-ninja": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/node-ninja/-/node-ninja-1.0.2.tgz", "integrity": "sha1-IKCeV7kuLfWRmT1L8JisPnJwYrY=", "dev": true, "requires": { "fstream": "^1.0.0", "glob": "3 || 4 || 5 || 6 || 7", "graceful-fs": "^4.1.2", "minimatch": "3", "mkdirp": "^0.5.0", "nopt": "2 || 3", "npmlog": "0 || 1 || 2", "osenv": "0", "path-array": "^1.0.0", "request": "2", "rimraf": "2", "semver": "2.x || 3.x || 4 || 5", "tar": "^2.0.0", "which": "1" }, "dependencies": { "are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", "dev": true, "requires": { "ansi": "^0.3.0", "has-unicode": "^2.0.0", "lodash.pad": "^4.1.0", "lodash.padend": "^4.1.0", "lodash.padstart": "^4.1.0" } }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { "minimist": "^1.2.5" } }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { "abbrev": "1" } }, "npmlog": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", "dev": true, "requires": { "ansi": "~0.3.1", "are-we-there-yet": "~1.1.2", "gauge": "~1.2.5" } }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" } }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" } }, "tar": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", "dev": true, "requires": { "block-stream": "*", "fstream": "^1.0.12", "inherits": "2" } }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } } } }, "noop-logger": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", "dev": true }, "nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, "requires": { "abbrev": "^1.0.0" } }, "normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, "npm-path": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", "dev": true, "requires": { "which": "^1.2.10" }, "dependencies": { "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } } } }, "npm-which": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", "dev": true, "requires": { "commander": "^2.9.0", "npm-path": "^2.0.2", "which": "^1.2.10" }, "dependencies": { "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } } } }, "npmlog": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.0.tgz", "integrity": "sha512-03ppFRGlsyUaQFbGC2C8QWJN/C/K7PsfyD9aQdhVKAQIH4sQBc8WASqFBP7O+Ut4d2oo5LoeoboB3cGdBZSp6Q==", "dev": true, "requires": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", "gauge": "^4.0.0", "set-blocking": "^2.0.0" } }, "null-check": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", "dev": true }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "nw-gyp": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/nw-gyp/-/nw-gyp-3.6.5.tgz", "integrity": "sha512-vYrOIYJEKpq9CfaHuiqEjV1rBYgr6uaUrPhPRiznb91LujkAUqGhQ5QqDC1bLdd+zo9jf2H0Zkl2M5zQB7+CuQ==", "dev": true, "requires": { "fstream": "^1.0.0", "glob": "^7.0.3", "graceful-fs": "^4.1.2", "minimatch": "^3.0.2", "mkdirp": "^0.5.0", "nopt": "2 || 3", "npmlog": "0 || 1 || 2 || 3 || 4", "osenv": "0", "request": "2", "rimraf": "2", "semver": "~5.3.0", "tar": "^2.0.0", "which": "1" }, "dependencies": { "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" } }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { "minimist": "^1.2.5" } }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { "abbrev": "1" } }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", "gauge": "~2.7.3", "set-blocking": "~2.0.0" } }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" } }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, "tar": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", "dev": true, "requires": { "block-stream": "*", "fstream": "^1.0.12", "inherits": "2" } }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } } } }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, "object-get": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", "dev": true }, "object-to-spawn-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "requires": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.3" } }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { "lcid": "^1.0.0" } }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, "osenv": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" } }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { "yocto-queue": "^0.1.0" } }, "p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { "p-limit": "^3.0.2" } }, "p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "requires": { "aggregate-error": "^3.0.0" } }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { "callsites": "^3.0.0" } }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "path-array": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz", "integrity": "sha1-fi8PNfB6IBUSK4aLfqwOssT+wnE=", "dev": true, "requires": { "array-index": "^1.0.0" } }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "dev": true, "requires": { "isarray": "0.0.1" } }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { "pify": "^3.0.0" }, "dependencies": { "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true } } }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "plur": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", "dev": true, "requires": { "irregular-plurals": "^3.2.0" } }, "prebuild": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/prebuild/-/prebuild-11.0.3.tgz", "integrity": "sha512-0synbTNdYD9nkVFtVl0nbslM6AefnKRcvyvtDwv6qswh4gYCbdWGmir4G7YPPDa3VmKCZADVBYnkqNI3qKJy5Q==", "dev": true, "requires": { "cmake-js": "~5.2.0", "detect-libc": "^2.0.0", "each-series-async": "^1.0.1", "execspawn": "^1.0.1", "ghreleases": "^3.0.2", "github-from-package": "0.0.0", "glob": "^7.1.6", "minimist": "^1.1.2", "mkdirp": "^0.5.1", "napi-build-utils": "^1.0.1", "node-abi": "^3.0.0", "node-gyp": "^6.0.1", "node-ninja": "^1.0.1", "noop-logger": "^0.1.0", "npm-which": "^3.0.1", "npmlog": "^4.0.1", "nw-gyp": "^3.6.3", "rc": "^1.0.3", "run-waterfall": "^1.1.6", "tar-stream": "^2.1.0" }, "dependencies": { "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "requires": { "minipass": "^2.6.0" } }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" } }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "requires": { "minipass": "^2.9.0" } }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { "minimist": "^1.2.5" } }, "node-gyp": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-6.1.0.tgz", "integrity": "sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw==", "dev": true, "requires": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.2", "mkdirp": "^0.5.1", "nopt": "^4.0.1", "npmlog": "^4.1.2", "request": "^2.88.0", "rimraf": "^2.6.3", "semver": "^5.7.1", "tar": "^4.4.12", "which": "^1.3.1" } }, "nopt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dev": true, "requires": { "abbrev": "1", "osenv": "^0.1.4" } }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", "gauge": "~2.7.3", "set-blocking": "~2.0.0" } }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" }, "dependencies": { "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true } } }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" } }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" }, "dependencies": { "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true } } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, "tar": { "version": "4.4.19", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, "requires": { "chownr": "^1.1.4", "fs-minipass": "^1.2.7", "minipass": "^2.9.0", "minizlib": "^1.3.3", "mkdirp": "^0.5.5", "safe-buffer": "^5.2.1", "yallist": "^3.1.1" } }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true } } }, "prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", "requires": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" } }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "prettier": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true }, "prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "requires": { "fast-diff": "^1.1.2" } }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true }, "promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "requires": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, "quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" } }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "dependencies": { "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" } } }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" }, "dependencies": { "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } }, "read-pkg-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { "find-up": "^2.0.0", "read-pkg": "^3.0.0" }, "dependencies": { "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { "locate-path": "^2.0.0" } }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { "p-try": "^1.0.0" } }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { "p-limit": "^1.1.0" } }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } } }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" } }, "redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "requires": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "reduce-extract": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", "dev": true, "requires": { "test-value": "^1.0.1" }, "dependencies": { "array-back": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", "dev": true, "requires": { "typical": "^2.6.0" } }, "test-value": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", "dev": true, "requires": { "array-back": "^1.0.2", "typical": "^2.4.2" } } } }, "reduce-flatten": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", "dev": true }, "reduce-unique": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", "dev": true }, "reduce-without": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", "dev": true, "requires": { "test-value": "^2.0.0" }, "dependencies": { "array-back": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", "dev": true, "requires": { "typical": "^2.6.0" } }, "test-value": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", "dev": true, "requires": { "array-back": "^1.0.3", "typical": "^2.6.0" } } } }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" } }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", "dev": true, "requires": { "lodash": "^4.17.14" } }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "requires": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" } }, "rsvp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", "dev": true }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "requires": { "queue-microtask": "^1.2.2" } }, "run-waterfall": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.7.tgz", "integrity": "sha512-iFPgh7SatHXOG1ClcpdwHI63geV3Hc/iL6crGSyBlH2PY7Rm/za+zoKz6FfY/Qlw5K7JwSol8pseO8fN6CMhhQ==", "dev": true }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "saslprep": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", "dev": true, "optional": true, "requires": { "sparse-bitfield": "^3.0.3" } }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "requires": { "lru-cache": "^6.0.0" } }, "serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" } }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { "shebang-regex": "^3.0.0" } }, "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, "simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "requires": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "simple-mime": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/simple-mime/-/simple-mime-0.1.0.tgz", "integrity": "sha1-lfUXxPRm18/1YacfydqyWW6p7y4=", "dev": true }, "sinon": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz", "integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.3", "@sinonjs/fake-timers": "^9.0.0", "@sinonjs/samsam": "^6.1.1", "diff": "^5.0.0", "nise": "^5.1.1", "supports-color": "^7.2.0" } }, "sinon-chai": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", "dev": true, "requires": {} }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" }, "socks": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", "requires": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" } }, "socks-proxy-agent": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, "requires": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sort-array": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", "integrity": "sha512-GVFN6Y1sHKrWaSYOJTk9093ZnrBMc9sP3nuhANU44S4xg3rE6W5Z5WyamuT8VpMBbssnetx5faKCua0LEmUnSw==", "dev": true, "requires": { "array-back": "^5.0.0", "typical": "^6.0.1" }, "dependencies": { "array-back": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", "dev": true }, "typical": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", "dev": true } } }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-support": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", "dev": true, "requires": { "source-map": "0.1.32" }, "dependencies": { "source-map": { "version": "0.1.32", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", "dev": true, "requires": { "amdefine": ">=0.0.4" } } } }, "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", "dev": true, "optional": true, "requires": { "memory-pager": "^1.0.2" } }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "dev": true }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { "through": "2" } }, "split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "requires": { "readable-stream": "^3.0.0" } }, "splitargs": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", "integrity": "sha1-/p965lc3GzOxDLgNoUPPgknPazs=", "dev": true }, "sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" } }, "ssri": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, "requires": { "minipass": "^3.1.1" } }, "standard-version": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", "dev": true, "requires": { "chalk": "^2.4.2", "conventional-changelog": "3.1.24", "conventional-changelog-config-spec": "2.1.0", "conventional-changelog-conventionalcommits": "4.6.1", "conventional-recommended-bump": "6.1.0", "detect-indent": "^6.0.0", "detect-newline": "^3.1.0", "dotgitignore": "^2.1.0", "figures": "^3.1.0", "find-up": "^5.0.0", "fs-access": "^1.0.1", "git-semver-tags": "^4.0.0", "semver": "^7.1.1", "stringify-package": "^1.0.1", "yargs": "^16.0.0" }, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" } }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" } }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" } } } }, "stream-connect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", "dev": true, "requires": { "array-back": "^1.0.2" }, "dependencies": { "array-back": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", "dev": true, "requires": { "typical": "^2.6.0" } } } }, "stream-via": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", "dev": true }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { "safe-buffer": "~5.2.0" } }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "stringify-package": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", "dev": true }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { "ansi-regex": "^5.0.1" } }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "requires": { "min-indent": "^1.0.0" } }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } }, "supports-hyperlinks": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, "requires": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, "table-layout": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", "dev": true, "requires": { "array-back": "^2.0.0", "deep-extend": "~0.6.0", "lodash.padend": "^4.6.1", "typical": "^2.6.1", "wordwrapjs": "^3.0.0" }, "dependencies": { "array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "requires": { "typical": "^2.6.1" } } } }, "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", "dev": true }, "tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "dev": true, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^3.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" }, "dependencies": { "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" } } }, "tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" }, "dependencies": { "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } } } }, "temp-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", "dev": true }, "test-value": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", "dev": true, "requires": { "array-back": "^2.0.0", "typical": "^2.6.1" }, "dependencies": { "array-back": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", "dev": true, "requires": { "typical": "^2.6.1" } } } }, "text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { "readable-stream": ">=1.0.33-1 <1.1.0-0", "xtend": ">=4.0.0 <4.1.0-0" }, "dependencies": { "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { "is-number": "^7.0.0" } }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "requires": { "psl": "^1.1.28", "punycode": "^2.1.1" } }, "tr46": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "dev": true, "requires": { "punycode": "^2.1.1" } }, "traceur": { "version": "0.0.111", "resolved": "https://registry.npmjs.org/traceur/-/traceur-0.0.111.tgz", "integrity": "sha1-wE3nTRRpbDNzQn3k/Ajsr5E/w6E=", "dev": true, "requires": { "commander": "2.9.x", "glob": "5.0.x", "rsvp": "^3.0.13", "semver": "^4.3.3", "source-map-support": "~0.2.8" }, "dependencies": { "commander": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { "graceful-readlink": ">= 1.0.0" } }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { "inflight": "^1.0.4", "inherits": "2", "minimatch": "2 || 3", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "semver": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", "dev": true } } }, "traverse": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", "dev": true }, "trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, "tsd": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.25.0.tgz", "integrity": "sha512-liUlvKtsdr+70XEZP/kkF6U8+Q9URZi4Pw58ih7a9x3kjJblG8rdVgvG62xcvkgRva1q3yWX5qAxfYZuYiC5CA==", "dev": true, "requires": { "@tsd/typescript": "~4.9.3", "eslint-formatter-pretty": "^4.1.0", "globby": "^11.0.1", "meow": "^9.0.0", "path-exists": "^4.0.0", "read-pkg-up": "^7.0.0" }, "dependencies": { "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { "p-locate": "^4.1.0" } }, "meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", "dev": true, "requires": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", "decamelize": "^1.2.0", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", "normalize-package-data": "^3.0.0", "read-pkg-up": "^7.0.1", "redent": "^3.0.0", "trim-newlines": "^3.0.0", "type-fest": "^0.18.0", "yargs-parser": "^20.2.3" } }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" } }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { "p-limit": "^2.2.0" } }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "requires": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", "parse-json": "^5.0.0", "type-fest": "^0.6.0" }, "dependencies": { "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true } } }, "read-pkg-up": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" }, "dependencies": { "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true } } }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "type-fest": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true } } }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { "safe-buffer": "^5.0.1" } }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", "dev": true }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { "prelude-ls": "^1.2.1" } }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", "dev": true }, "uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, "uglify-js": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.0.tgz", "integrity": "sha512-x+xdeDWq7FiORDvyIJ0q/waWd4PhjBNOm5dQUOq2AKC0IEjxOS66Ha9tctiVDGcRQuh69K7fgU5oRuTK4cysSg==", "dev": true, "optional": true }, "underscore": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz", "integrity": "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==", "dev": true }, "unique-filename": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, "requires": { "unique-slug": "^3.0.0" } }, "unique-slug": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, "requires": { "imurmurhash": "^0.1.4" } }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, "unzipper": { "version": "0.8.14", "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.8.14.tgz", "integrity": "sha512-8rFtE7EP5ssOwGpN2dt1Q4njl0N1hUXJ7sSPz0leU2hRdq6+pra57z4YPBlVqm40vcgv6ooKZEAx48fMTv9x4w==", "dev": true, "requires": { "big-integer": "^1.6.17", "binary": "~0.3.0", "bluebird": "~3.4.1", "buffer-indexof-polyfill": "~1.0.0", "duplexer2": "~0.1.4", "fstream": "~1.0.10", "listenercount": "~1.0.1", "readable-stream": "~2.1.5", "setimmediate": "~1.0.4" }, "dependencies": { "bluebird": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { "readable-stream": "^2.0.2" } }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, "readable-stream": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", "dev": true, "requires": { "buffer-shims": "^1.0.0", "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "~1.0.0", "process-nextick-args": "~1.0.6", "string_decoder": "~0.10.x", "util-deprecate": "~1.0.1" } }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" } }, "url-join": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=", "dev": true }, "url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=", "dev": true }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util-extend": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", "dev": true }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "walk-back": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", "dev": true }, "webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true }, "whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, "requires": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" } }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" } }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, "requires": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", "dev": true }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wordwrapjs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", "dev": true, "requires": { "reduce-flatten": "^1.0.1", "typical": "^2.6.1" }, "dependencies": { "reduce-flatten": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", "dev": true } } }, "workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true }, "yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" }, "dependencies": { "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, "decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true } } }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true } } } libmongocrypt-1.8.4/bindings/node/package.json000066400000000000000000000047331454530651600214440ustar00rootroot00000000000000{ "name": "mongodb-client-encryption", "version": "2.8.0-alpha.1", "description": "Official client encryption module for the MongoDB Node.js driver", "main": "lib/index.js", "types": "index.d.ts", "files": [ "README.md", "CHANGELOG.md", "lib", "src", "index.d.ts", "binding.gyp" ], "directories": { "lib": "lib" }, "scripts": { "install": "prebuild-install --runtime napi --tag-prefix node-v || node-gyp rebuild", "check:lint": "eslint lib test && tsd", "docs": "jsdoc2md --template etc/README.hbs --plugin dmd-clear --files 'lib/**/*.js' > README.md", "test": "mocha test", "rebuild": "prebuild --compile", "release": "standard-version --tag-prefix node-v --path bindings/node", "prebuild": "prebuild --runtime napi --strip --verbose --tag-prefix node-v --all" }, "author": { "name": "The MongoDB NodeJS Team", "email": "dbx-node@mongodb.com" }, "bugs": { "url": "https://jira.mongodb.org/projects/NODE/issues/" }, "license": "Apache-2.0", "gypfile": true, "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^4.3.0", "prebuild-install": "^7.1.1", "socks": "^2.6.1" }, "devDependencies": { "@types/sinon": "^10.0.13", "@types/sinon-chai": "^3.2.9", "chai": "^4.3.6", "chai-subset": "^1.6.0", "chalk": "^4.1.2", "clang-format": "^1.6.0", "dmd-clear": "^0.1.2", "eslint": "^8.8.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "jsdoc-to-markdown": "^7.1.1", "mocha": "^9.2.0", "mongodb": "^4.9.0", "node-gyp": "^9.3.1", "prebuild": "^11.0.2", "prettier": "^2.5.1", "sinon": "^13.0.1", "sinon-chai": "^3.7.0", "standard-version": "^9.3.2", "tar": "^6.1.11", "tsd": "^0.25.0" }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.186.0", "gcp-metadata": "^5.2.0", "mongodb": ">=3.4.0" }, "peerDependenciesMeta": { "@aws-sdk/credential-providers": { "optional": true }, "gcp-metadata": { "optional": true } }, "engines": { "node": ">=12.9.0" }, "binary": { "napi_versions": [ 4 ] }, "repository": { "type": "git", "url": "https://github.com/mongodb/libmongocrypt", "directory": "bindings/node" }, "tsd": { "directory": "test/types", "compilerOptions": { "strict": true, "target": "esnext", "module": "commonjs", "moduleResolution": "node" } } } libmongocrypt-1.8.4/bindings/node/src/000077500000000000000000000000001454530651600177365ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/src/mongocrypt.cc000066400000000000000000001124561454530651600224570ustar00rootroot00000000000000#include "mongocrypt.h" #include #ifdef _MSC_VER #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif namespace node_mongocrypt { using namespace Napi; // anonymous namepace for helpers namespace { struct InstanceData { Reference MongoCryptContextCtor; Reference MongoCryptKMSRequestCtor; }; struct MongoCryptStatusDeleter { void operator()(mongocrypt_status_t* status) { mongocrypt_status_destroy(status); } }; Object ExtractStatus(Env env, mongocrypt_status_t* status) { Object result = Object::New(env); result["type"] = Number::New(env, mongocrypt_status_type(status)); result["code"] = Number::New(env, mongocrypt_status_code(status)); const char* message = mongocrypt_status_message(status, nullptr); if (message != nullptr) { result["message"] = String::New(env, message); } return result; } std::unique_ptr BufferToBinary(Uint8Array node_buffer) { uint8_t* buffer = node_buffer.Data(); size_t buffer_len = node_buffer.ByteLength(); return std::unique_ptr( mongocrypt_binary_new_from_data(buffer, buffer_len)); } Uint8Array BufferFromBinary(Env env, mongocrypt_binary_t* binary) { const uint8_t* data = mongocrypt_binary_data(binary); size_t len = mongocrypt_binary_len(binary); return Buffer::Copy(env, data, len); } Uint8Array BufferWithLengthOf(Env env, mongocrypt_binary_t* binary) { size_t len = mongocrypt_binary_len(binary); return Buffer::New(env, len); } void CopyBufferData(mongocrypt_binary_t* out, Uint8Array buffer, size_t count) { assert(count <= mongocrypt_binary_len(out)); assert(count <= buffer.ByteLength()); memcpy(mongocrypt_binary_data(out), buffer.Data(), count); } void CopyBufferData(mongocrypt_binary_t* out, Uint8Array buffer) { CopyBufferData(out, buffer, mongocrypt_binary_len(out)); } std::string errorStringFromStatus(mongocrypt_t* crypt) { std::unique_ptr status(mongocrypt_status_new()); mongocrypt_status(crypt, status.get()); const char* errorMessage = mongocrypt_status_message(status.get(), nullptr); if (!errorMessage) { return "Operation failed"; } return errorMessage; } std::string errorStringFromStatus(mongocrypt_ctx_t* context) { std::unique_ptr status(mongocrypt_status_new()); mongocrypt_ctx_status(context, status.get()); const char* errorMessage = mongocrypt_status_message(status.get(), nullptr); if (!errorMessage) { return "Operation failed"; } return errorMessage; } template E strToEnumValue( Env env, const std::string& str, const char* option_name, const std::initializer_list>& values) { for (const auto& candidate : values) { if (candidate.first == str) { return candidate.second; } } throw Error::New(env, std::string("invalid enum value: '") + str + "' for " + option_name); } } // anonymous namespace Function MongoCrypt::Init(Napi::Env env) { return DefineClass(env, "MongoCrypt", { InstanceMethod("makeEncryptionContext", &MongoCrypt::MakeEncryptionContext), InstanceMethod("makeExplicitEncryptionContext", &MongoCrypt::MakeExplicitEncryptionContext), InstanceMethod("makeDecryptionContext", &MongoCrypt::MakeDecryptionContext), InstanceMethod("makeExplicitDecryptionContext", &MongoCrypt::MakeExplicitDecryptionContext), InstanceMethod("makeDataKeyContext", &MongoCrypt::MakeDataKeyContext), InstanceMethod("makeRewrapManyDataKeyContext", &MongoCrypt::MakeRewrapManyDataKeyContext), InstanceAccessor("status", &MongoCrypt::Status, nullptr), InstanceAccessor("cryptSharedLibVersionInfo", &MongoCrypt::CryptSharedLibVersionInfo, nullptr), StaticValue("libmongocryptVersion", String::New(env, mongocrypt_version(nullptr))) }); } void MongoCrypt::logHandler(mongocrypt_log_level_t level, const char* message, uint32_t message_len, void* ctx) { MongoCrypt* mongoCrypt = static_cast(ctx); if (!mongoCrypt) { fprintf(stderr, "Log handler called without `MongoCrypt` instance\n"); return; } Napi::Env env = mongoCrypt->Env(); HandleScope scope(env); Function logger = mongoCrypt->GetCallback("logger"); if (logger.IsEmpty()) { fprintf(stderr, "No logger set, but log handler registered\n"); return; } try { logger.Call(std::initializer_list { Number::New(env, level), String::New(env, message, message_len) }); } catch (const std::exception& ex) { fprintf(stderr, "Uncaught exception in logger callback: %s\n", ex.what()); } catch (...) { fprintf(stderr, "Uncaught exception in logger callback\n"); } } static void MaybeSetCryptoHookErrorStatus(Value result, mongocrypt_status_t *status) { if (!result.IsObject()) { return; } Object hookError = result.As(); if (!hookError.Has("message")) { return; } std::string errorMessage = hookError.Get("message").ToString(); mongocrypt_status_set( status, MONGOCRYPT_STATUS_ERROR_CLIENT, 1, errorMessage.c_str(), errorMessage.length() + 1 ); } static bool aes_256_generic_hook (MongoCrypt* mongoCrypt, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status, Function hook) { Env env = mongoCrypt->Env(); HandleScope scope(env); Uint8Array keyBuffer = BufferFromBinary(env, key); Uint8Array ivBuffer = BufferFromBinary(env, iv); Uint8Array inBuffer = BufferFromBinary(env, in); Uint8Array outBuffer = BufferWithLengthOf(env, out); Value result; try { result = hook.Call(std::initializer_list { keyBuffer, ivBuffer, inBuffer, outBuffer }); } catch (...) { return false; } if (!result.IsNumber()) { MaybeSetCryptoHookErrorStatus(result, status); return false; } *bytes_written = result.ToNumber().Uint32Value(); CopyBufferData(out, outBuffer, *bytes_written); return true; } bool MongoCrypt::setupCryptoHooks() { auto aes_256_cbc_encrypt = [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { MongoCrypt* mc = static_cast(ctx); return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CbcEncryptHook")); }; auto aes_256_cbc_decrypt = [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { MongoCrypt* mc = static_cast(ctx); return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CbcDecryptHook")); }; auto aes_256_ctr_encrypt = [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { MongoCrypt* mc = static_cast(ctx); return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CtrEncryptHook")); }; auto aes_256_ctr_decrypt = [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { MongoCrypt* mc = static_cast(ctx); return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CtrDecryptHook")); }; auto random = [](void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_status_t *status) -> bool { MongoCrypt* mongoCrypt = static_cast(ctx); Napi::Env env = mongoCrypt->Env(); HandleScope scope(env); Function hook = mongoCrypt->GetCallback("randomHook"); Uint8Array outBuffer = BufferWithLengthOf(env, out); Napi::Value result; try { result = hook.Call(std::initializer_list { outBuffer, Number::New(env, count) }); } catch (...) { return false; } if (!result.IsNumber()) { MaybeSetCryptoHookErrorStatus(result, status); return false; } CopyBufferData(out, outBuffer); return true; }; auto hmac_sha_512 = [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { MongoCrypt* mongoCrypt = static_cast(ctx); Napi::Env env = mongoCrypt->Env(); HandleScope scope(env); Function hook = mongoCrypt->GetCallback("hmacSha512Hook"); Uint8Array keyBuffer = BufferFromBinary(env, key); Uint8Array inputBuffer = BufferFromBinary(env, in); Uint8Array outputBuffer = BufferWithLengthOf(env, out); Napi::Value result; try { result = hook.Call(std::initializer_list { keyBuffer, inputBuffer, outputBuffer }); } catch (...) { return false; } if (!result.IsNumber()) { MaybeSetCryptoHookErrorStatus(result, status); return false; } CopyBufferData(out, outputBuffer); return true; }; auto hmac_sha_256 = [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { MongoCrypt* mongoCrypt = static_cast(ctx); Napi::Env env = mongoCrypt->Env(); HandleScope scope(env); Function hook = mongoCrypt->GetCallback("hmacSha256Hook"); Uint8Array keyBuffer = BufferFromBinary(env, key); Uint8Array inputBuffer = BufferFromBinary(env, in); Uint8Array outputBuffer = BufferWithLengthOf(env, out); Napi::Value result; try { result = hook.Call(std::initializer_list { keyBuffer, inputBuffer, outputBuffer }); } catch (...) { return false; } if (!result.IsNumber()) { MaybeSetCryptoHookErrorStatus(result, status); return false; } CopyBufferData(out, outputBuffer); return true; }; auto sha_256 = [](void *ctx, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { MongoCrypt* mongoCrypt = static_cast(ctx); Napi::Env env = mongoCrypt->Env(); HandleScope scope(env); Function hook = mongoCrypt->GetCallback("sha256Hook"); Uint8Array inputBuffer = BufferFromBinary(env, in); Uint8Array outputBuffer = BufferWithLengthOf(env, out); Napi::Value result; try { result = hook.Call(std::initializer_list { inputBuffer, outputBuffer }); } catch (...) { return false; } if (!result.IsNumber()) { MaybeSetCryptoHookErrorStatus(result, status); return false; } CopyBufferData(out, outputBuffer); return true; }; auto sign_rsa_sha256 = [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { MongoCrypt* mongoCrypt = static_cast(ctx); Napi::Env env = mongoCrypt->Env(); HandleScope scope(env); Function hook = mongoCrypt->GetCallback("signRsaSha256Hook"); Uint8Array keyBuffer = BufferFromBinary(env, key); Uint8Array inputBuffer = BufferFromBinary(env, in); Uint8Array outputBuffer = BufferWithLengthOf(env, out); Napi::Value result; try { result = hook.Call(std::initializer_list { keyBuffer, inputBuffer, outputBuffer }); } catch (...) { return false; } if (!result.IsNumber()) { MaybeSetCryptoHookErrorStatus(result, status); return false; } CopyBufferData(out, outputBuffer); return true; }; if (!mongocrypt_setopt_crypto_hooks(_mongo_crypt.get(), aes_256_cbc_encrypt, aes_256_cbc_decrypt, random, hmac_sha_512, hmac_sha_256, sha_256, this)) { return false; } // Added after `mongocrypt_setopt_crypto_hooks`, they should be treated as the same during configuration if (!mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(_mongo_crypt.get(), sign_rsa_sha256, this)) { return false; } if (!mongocrypt_setopt_aes_256_ctr(_mongo_crypt.get(), aes_256_ctr_encrypt, aes_256_ctr_decrypt, this)) { return false; } return true; } MongoCrypt::MongoCrypt(const CallbackInfo& info) : ObjectWrap(info), _mongo_crypt(mongocrypt_new()) { if (info.Length() < 1 || !info[0].IsObject()) { throw TypeError::New(Env(), "First parameter must be an object"); } Object options = info[0].ToObject(); if (options.Has("kmsProviders")) { Napi::Value kmsProvidersOptions = options["kmsProviders"]; if (!kmsProvidersOptions.IsBuffer()) { throw TypeError::New(Env(), "Option `kmsProviders` must be a Buffer"); } std::unique_ptr kmsProvidersBinary( BufferToBinary(kmsProvidersOptions.As())); if (!mongocrypt_setopt_kms_providers(_mongo_crypt.get(), kmsProvidersBinary.get())) { throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); } } if (options.Has("schemaMap")) { Napi::Value schemaMapBuffer = options["schemaMap"]; if (!schemaMapBuffer.IsBuffer()) { throw TypeError::New(Env(), "Option `schemaMap` must be a Buffer"); } std::unique_ptr schemaMapBinary( BufferToBinary(schemaMapBuffer.As())); if (!mongocrypt_setopt_schema_map(_mongo_crypt.get(), schemaMapBinary.get())) { throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); } } if (options.Has("encryptedFieldsMap")) { Napi::Value encryptedFieldsMapBuffer = options["encryptedFieldsMap"]; if (!encryptedFieldsMapBuffer.IsBuffer()) { throw TypeError::New(Env(), "Option `encryptedFieldsMap` must be a Buffer"); } std::unique_ptr encryptedFieldsMapBinary( BufferToBinary(encryptedFieldsMapBuffer.As())); if (!mongocrypt_setopt_encrypted_field_config_map(_mongo_crypt.get(), encryptedFieldsMapBinary.get())) { throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); } } if (options.Has("logger")) { SetCallback("logger", options["logger"]); if (!mongocrypt_setopt_log_handler( _mongo_crypt.get(), MongoCrypt::logHandler, this)) { throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); } } if (options.Has("cryptoCallbacks")) { Object cryptoCallbacks = options.Get("cryptoCallbacks").ToObject(); SetCallback("aes256CbcEncryptHook", cryptoCallbacks["aes256CbcEncryptHook"]); SetCallback("aes256CbcDecryptHook", cryptoCallbacks["aes256CbcDecryptHook"]); SetCallback("aes256CtrEncryptHook", cryptoCallbacks["aes256CtrEncryptHook"]); SetCallback("aes256CtrDecryptHook", cryptoCallbacks["aes256CtrDecryptHook"]); SetCallback("randomHook", cryptoCallbacks["randomHook"]); SetCallback("hmacSha512Hook", cryptoCallbacks["hmacSha512Hook"]); SetCallback("hmacSha256Hook", cryptoCallbacks["hmacSha256Hook"]); SetCallback("sha256Hook", cryptoCallbacks["sha256Hook"]); SetCallback("signRsaSha256Hook", cryptoCallbacks["signRsaSha256Hook"]); if (!setupCryptoHooks()) { throw Error::New(Env(), "unable to configure crypto hooks"); } } if (options.Has("cryptSharedLibSearchPaths")) { Napi::Value search_paths_v = options["cryptSharedLibSearchPaths"]; if (!search_paths_v.IsArray()) { throw TypeError::New(Env(), "Option `cryptSharedLibSearchPaths` must be an array"); } Array search_paths = search_paths_v.As(); for (uint32_t i = 0; i < search_paths.Length(); i++) { mongocrypt_setopt_append_crypt_shared_lib_search_path( _mongo_crypt.get(), search_paths.Get(i).ToString().Utf8Value().c_str()); } } if (options.Has("cryptSharedLibPath")) { mongocrypt_setopt_set_crypt_shared_lib_path_override( _mongo_crypt.get(), options.Get("cryptSharedLibPath").ToString().Utf8Value().c_str()); } if (options.Get("bypassQueryAnalysis").ToBoolean()) { mongocrypt_setopt_bypass_query_analysis(_mongo_crypt.get()); } mongocrypt_setopt_use_need_kms_credentials_state(_mongo_crypt.get()); // Initialize after all options are set. if (!mongocrypt_init(_mongo_crypt.get())) { throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); } } Value MongoCrypt::CryptSharedLibVersionInfo(const CallbackInfo& info) { uint64_t version_numeric = mongocrypt_crypt_shared_lib_version(_mongo_crypt.get()); const char* version_string = mongocrypt_crypt_shared_lib_version_string(_mongo_crypt.get(), nullptr); if (version_string == nullptr) { return Env().Null(); } Object ret = Object::New(Env()); ret["version"] = BigInt::New(Env(), version_numeric); ret["versionStr"] = String::New(Env(), version_string); return ret; } Value MongoCrypt::Status(const CallbackInfo& info) { std::unique_ptr status(mongocrypt_status_new()); mongocrypt_status(_mongo_crypt.get(), status.get()); return ExtractStatus(Env(), status.get()); } Value MongoCrypt::MakeEncryptionContext(const CallbackInfo& info) { std::string ns = info[0].ToString(); std::unique_ptr context( mongocrypt_ctx_new(_mongo_crypt.get())); Napi::Value commandBuffer = info[1]; if (!commandBuffer.IsBuffer()) { throw TypeError::New(Env(), "Parameter `command` must be a Buffer"); } std::unique_ptr binaryCommand(BufferToBinary(commandBuffer.As())); if (!mongocrypt_ctx_encrypt_init( context.get(), ns.c_str(), ns.size(), binaryCommand.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } return MongoCryptContext::NewInstance(Env(), std::move(context)); } Value MongoCrypt::MakeExplicitEncryptionContext(const CallbackInfo& info) { std::unique_ptr context( mongocrypt_ctx_new(_mongo_crypt.get())); Napi::Value valueBuffer = info[0]; if (!valueBuffer.IsBuffer()) { throw TypeError::New(Env(), "Parameter `value` must be a Buffer"); } Object options = info.Length() > 1 ? info[1].ToObject() : Object::New(info.Env()); if (options.Has("keyId")) { Napi::Value keyId = options["keyId"]; if (!keyId.IsBuffer()) { throw TypeError::New(Env(), "`keyId` must be a Buffer"); } std::unique_ptr binary(BufferToBinary(keyId.As())); if (!mongocrypt_ctx_setopt_key_id(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } if (options.Has("keyAltName")) { Napi::Value keyAltName = options["keyAltName"]; if (!keyAltName.IsBuffer()) { throw TypeError::New(Env(), "`keyAltName` must be a Buffer"); } std::unique_ptr binary( BufferToBinary(keyAltName.As())); if (!mongocrypt_ctx_setopt_key_alt_name(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } if (options.Has("algorithm")) { std::string algorithm = options.Get("algorithm").ToString(); if (!mongocrypt_ctx_setopt_algorithm( context.get(), algorithm.c_str(), algorithm.size())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } if (strcasecmp(algorithm.c_str(), "rangepreview") == 0) { if (!options.Has("rangeOptions")) { throw TypeError::New(Env(), "`rangeOptions` must be provided if `algorithm` is set to RangePreview"); } Napi::Value rangeOptions = options["rangeOptions"]; if (!rangeOptions.IsBuffer()) { throw TypeError::New(Env(), "`rangeOptions` must be a Buffer"); } std::unique_ptr binary(BufferToBinary(rangeOptions.As())); if (!mongocrypt_ctx_setopt_algorithm_range(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } } if (options.Has("contentionFactor")) { Napi::Value contention_factor_value = options["contentionFactor"]; int64_t contention_factor = contention_factor_value.IsBigInt() ? contention_factor_value.As().Int64Value(nullptr) : contention_factor_value.ToNumber().Int64Value(); if (!mongocrypt_ctx_setopt_contention_factor(context.get(), contention_factor)) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } if (options.Has("queryType")) { std::string query_type_str = options.Get("queryType").ToString(); if (!mongocrypt_ctx_setopt_query_type(context.get(), query_type_str.data(), -1)) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } std::unique_ptr binaryValue(BufferToBinary(valueBuffer.As())); const bool isExpressionMode = options.Get("expressionMode").ToBoolean(); const bool status = isExpressionMode ? mongocrypt_ctx_explicit_encrypt_expression_init(context.get(), binaryValue.get()) : mongocrypt_ctx_explicit_encrypt_init(context.get(), binaryValue.get()); if (!status) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } return MongoCryptContext::NewInstance(Env(), std::move(context)); } Value MongoCrypt::MakeDecryptionContext(const CallbackInfo& info) { if (!info[0].IsBuffer()) { throw TypeError::New(Env(), "First parameter must be a Buffer"); } std::unique_ptr binary( BufferToBinary(info[0].As())); std::unique_ptr context( mongocrypt_ctx_new(_mongo_crypt.get())); if (!mongocrypt_ctx_decrypt_init(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } return MongoCryptContext::NewInstance(Env(), std::move(context)); } Value MongoCrypt::MakeExplicitDecryptionContext(const CallbackInfo& info) { if (!info[0].IsBuffer()) { throw TypeError::New(Env(), "First parameter must be a Buffer"); } std::unique_ptr binary( BufferToBinary(info[0].As())); std::unique_ptr context( mongocrypt_ctx_new(_mongo_crypt.get())); if (!mongocrypt_ctx_explicit_decrypt_init(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } return MongoCryptContext::NewInstance(Env(), std::move(context)); } Value MongoCrypt::MakeDataKeyContext(const CallbackInfo& info) { Napi::Value optionsBuffer = info[0]; if (!optionsBuffer.IsBuffer()) { throw TypeError::New(Env(), "Parameter `options` must be a Buffer"); } std::unique_ptr context( mongocrypt_ctx_new(_mongo_crypt.get())); std::unique_ptr binary( BufferToBinary(optionsBuffer.As())); if (!mongocrypt_ctx_setopt_key_encryption_key(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } Object options = info[1].ToObject(); if (options.Has("keyAltNames")) { Napi::Value keyAltNames = options["keyAltNames"]; if (keyAltNames.IsArray()) { Array keyAltNamesArray = keyAltNames.As(); uint32_t keyAltNamesLength = keyAltNamesArray.Length(); for (uint32_t i = 0; i < keyAltNamesLength; i += 1) { if (keyAltNamesArray.Has(i)) { Napi::Value keyAltName = keyAltNamesArray[i]; if (!keyAltName.IsBuffer()) { // We should never get here throw TypeError::New(Env(), "Serialized keyAltName must be a Buffer"); } std::unique_ptr binary( BufferToBinary(keyAltName.As())); if (!mongocrypt_ctx_setopt_key_alt_name(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } } } } if (options.Has("keyMaterial")) { Napi::Value keyMaterial = options["keyMaterial"]; if (!keyMaterial.IsUndefined()) { if (!keyMaterial.IsBuffer()) { // We should never get here throw TypeError::New(Env(), "Serialized keyMaterial must be a Buffer"); } std::unique_ptr binary( BufferToBinary(keyMaterial.As())); if (!mongocrypt_ctx_setopt_key_material(context.get(), binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } } if (!mongocrypt_ctx_datakey_init(context.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } return MongoCryptContext::NewInstance(Env(), std::move(context)); } Value MongoCrypt::MakeRewrapManyDataKeyContext(const CallbackInfo& info) { Napi::Value filter_buffer = info[0]; if (!filter_buffer.IsBuffer()) { throw TypeError::New(Env(), "Parameter `options` must be a Buffer"); } std::unique_ptr context( mongocrypt_ctx_new(_mongo_crypt.get())); Napi::Value key_encryption_key = info[1]; if (key_encryption_key.IsBuffer()) { std::unique_ptr key_binary( BufferToBinary(key_encryption_key.As())); if (!mongocrypt_ctx_setopt_key_encryption_key(context.get(), key_binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } } std::unique_ptr filter_binary( BufferToBinary(filter_buffer.As())); if (!mongocrypt_ctx_rewrap_many_datakey_init(context.get(), filter_binary.get())) { throw TypeError::New(Env(), errorStringFromStatus(context.get())); } return MongoCryptContext::NewInstance(Env(), std::move(context)); } // Store callbacks as nested properties on the MongoCrypt binding object // itself, and use these helpers to do so. Storing them as JS engine // References is a big memory leak footgun. Function MongoCrypt::GetCallback(const char* name) { Napi::Value storage = Value().Get("__callbackStorage"); if (!storage.IsObject()) { throw Error::New(Env(), "Cannot get callbacks becauses none were registered"); } Napi::Value entry = storage.As().Get(name); if (!entry.IsFunction()) { throw Error::New(Env(), std::string("Trying to look up unknown callback ") + name); } return entry.As(); } void MongoCrypt::SetCallback(const char* name, Napi::Value fn) { if (!fn.IsFunction()) { throw Error::New(Env(), std::string("Storing non-function as callback ") + name); } Napi::Value storage = Value().Get("__callbackStorage"); if (!storage.IsObject()) { storage = Object::New(Env()); Value().Set("__callbackStorage", storage); } storage.As().Set(name, fn); } Function MongoCryptContext::Init(Napi::Env env) { return DefineClass(env, "MongoCryptContext", { InstanceMethod("nextMongoOperation", &MongoCryptContext::NextMongoOperation), InstanceMethod("addMongoOperationResponse", &MongoCryptContext::AddMongoOperationResponse), InstanceMethod("finishMongoOperation", &MongoCryptContext::FinishMongoOperation), InstanceMethod("nextKMSRequest", &MongoCryptContext::NextKMSRequest), InstanceMethod("provideKMSProviders", &MongoCryptContext::ProvideKMSProviders), InstanceMethod("finishKMSRequests", &MongoCryptContext::FinishKMSRequests), InstanceMethod("finalize", &MongoCryptContext::FinalizeContext), InstanceAccessor("status", &MongoCryptContext::Status, nullptr), InstanceAccessor("state", &MongoCryptContext::State, nullptr) }); } Object MongoCryptContext::NewInstance(Napi::Env env, std::unique_ptr context) { InstanceData* instance_data = env.GetInstanceData(); Object obj = instance_data->MongoCryptContextCtor.Value().New({}); MongoCryptContext* instance = MongoCryptContext::Unwrap(obj); instance->_context = std::move(context); return obj; } MongoCryptContext::MongoCryptContext(const CallbackInfo& info) : ObjectWrap(info) {} Value MongoCryptContext::Status(const CallbackInfo& info) { std::unique_ptr status(mongocrypt_status_new()); mongocrypt_ctx_status(_context.get(), status.get()); return ExtractStatus(Env(), status.get()); } Value MongoCryptContext::State(const CallbackInfo& info) { return Number::New(Env(), mongocrypt_ctx_state(_context.get())); } Value MongoCryptContext::NextMongoOperation(const CallbackInfo& info) { std::unique_ptr op_bson(mongocrypt_binary_new()); mongocrypt_ctx_mongo_op(_context.get(), op_bson.get()); return BufferFromBinary(Env(), op_bson.get()); } void MongoCryptContext::AddMongoOperationResponse(const CallbackInfo& info) { if (info.Length() != 1 || !info[0].IsObject()) { throw TypeError::New(Env(), "Missing required parameter `buffer`"); } if (!info[0].IsBuffer()) { throw TypeError::New(Env(), "First parameter must be a Buffer"); } std::unique_ptr reply_bson( BufferToBinary(info[0].As())); mongocrypt_ctx_mongo_feed(_context.get(), reply_bson.get()); // return value } void MongoCryptContext::FinishMongoOperation(const CallbackInfo& info) { mongocrypt_ctx_mongo_done(_context.get()); } void MongoCryptContext::ProvideKMSProviders(const CallbackInfo& info) { if (info.Length() != 1 || !info[0].IsObject()) { throw TypeError::New(Env(), "Missing required parameter `buffer`"); } if (!info[0].IsBuffer()) { throw TypeError::New(Env(), "First parameter must be a Buffer"); } std::unique_ptr kms_bson( BufferToBinary(info[0].As())); mongocrypt_ctx_provide_kms_providers(_context.get(), kms_bson.get()); } Value MongoCryptContext::NextKMSRequest(const CallbackInfo& info) { mongocrypt_kms_ctx_t* kms_context = mongocrypt_ctx_next_kms_ctx(_context.get()); if (kms_context == nullptr) { return Env().Null(); } else { Object result = MongoCryptKMSRequest::NewInstance(Env(), kms_context); // The lifetime of the `kms_context` pointer is not specified // anywhere, so it seems reasonable to assume that it is at // least the lifetime of this context object. // Use a symbol to enforce that lifetime dependency. result.Set("__kmsRequestContext", Value()); return result; } } void MongoCryptContext::FinishKMSRequests(const CallbackInfo& info) { mongocrypt_ctx_kms_done(_context.get()); } Value MongoCryptContext::FinalizeContext(const CallbackInfo& info) { std::unique_ptr output(mongocrypt_binary_new()); mongocrypt_ctx_finalize(_context.get(), output.get()); return BufferFromBinary(Env(), output.get()); } Function MongoCryptKMSRequest::Init(Napi::Env env) { return DefineClass(env, "MongoCryptKMSRequest", { InstanceMethod("addResponse", &MongoCryptKMSRequest::AddResponse), InstanceAccessor("status", &MongoCryptKMSRequest::Status, nullptr), InstanceAccessor("bytesNeeded", &MongoCryptKMSRequest::BytesNeeded, nullptr), InstanceAccessor("kmsProvider", &MongoCryptKMSRequest::KMSProvider, nullptr), InstanceAccessor("endpoint", &MongoCryptKMSRequest::Endpoint, nullptr), InstanceAccessor("message", &MongoCryptKMSRequest::Message, nullptr) }); } Object MongoCryptKMSRequest::NewInstance(Napi::Env env, mongocrypt_kms_ctx_t* kms_context) { InstanceData* instance_data = env.GetInstanceData(); Object obj = instance_data->MongoCryptKMSRequestCtor.Value().New({}); MongoCryptKMSRequest* instance = MongoCryptKMSRequest::Unwrap(obj); instance->_kms_context = kms_context; return obj; } MongoCryptKMSRequest::MongoCryptKMSRequest(const CallbackInfo& info) : ObjectWrap(info), _kms_context(nullptr) {} Value MongoCryptKMSRequest::Status(const CallbackInfo& info) { std::unique_ptr status(mongocrypt_status_new()); mongocrypt_kms_ctx_status(_kms_context, status.get()); return ExtractStatus(Env(), status.get()); } Value MongoCryptKMSRequest::BytesNeeded(const CallbackInfo& info) { return Number::New(Env(), mongocrypt_kms_ctx_bytes_needed(_kms_context)); } Value MongoCryptKMSRequest::KMSProvider(const CallbackInfo& info) { return String::New(Env(), mongocrypt_kms_ctx_get_kms_provider(_kms_context, nullptr)); } Value MongoCryptKMSRequest::Message(const CallbackInfo& info) { std::unique_ptr message(mongocrypt_binary_new()); mongocrypt_kms_ctx_message(_kms_context, message.get()); return BufferFromBinary(Env(), message.get()); } Value MongoCryptKMSRequest::Endpoint(const CallbackInfo& info) { std::unique_ptr message(mongocrypt_binary_new()); const char* endpoint; mongocrypt_kms_ctx_endpoint(_kms_context, &endpoint); return String::New(Env(), endpoint); } void MongoCryptKMSRequest::AddResponse(const CallbackInfo& info) { if (!info[0].IsBuffer()) { throw TypeError::New(Env(), "First parameter must be of type Buffer"); } std::unique_ptr reply_bytes( BufferToBinary(info[0].As())); mongocrypt_kms_ctx_feed(_kms_context, reply_bytes.get()); } static Object Init(Env env, Object exports) { Function MongoCryptCtor = MongoCrypt::Init(env); Function MongoCryptContextCtor = MongoCryptContext::Init(env); Function MongoCryptKMSRequestCtor = MongoCryptKMSRequest::Init(env); exports["MongoCrypt"] = MongoCryptCtor; exports["MongoCryptContextCtor"] = MongoCryptContextCtor; exports["MongoCryptKMSRequestCtor"] = MongoCryptKMSRequestCtor; env.SetInstanceData(new InstanceData { Reference::New(MongoCryptContextCtor, 1), Reference::New(MongoCryptKMSRequestCtor, 1) }); return exports; } NODE_API_MODULE(mongocrypt, Init) } // namespace node_mongocrypt libmongocrypt-1.8.4/bindings/node/src/mongocrypt.h000066400000000000000000000075741454530651600223250ustar00rootroot00000000000000#ifndef NODE_MONGOCRYPT_H #define NODE_MONGOCRYPT_H // We generally only target N-API version 4, but the instance data // feature is only available in N-API version 6. However, it is // available in all Node.js versions that have N-API version 4 // as an experimental feature (that has not been changed since then). #define NAPI_VERSION 6 #define NAPI_EXPERIMENTAL #include #include extern "C" { #include } namespace node_mongocrypt { struct MongoCryptBinaryDeleter { void operator()(mongocrypt_binary_t* binary) { mongocrypt_binary_destroy(binary); } }; struct MongoCryptDeleter { void operator()(mongocrypt_t* mongo_crypt) { mongocrypt_destroy(mongo_crypt); } }; struct MongoCryptContextDeleter { void operator()(mongocrypt_ctx_t* context) { mongocrypt_ctx_destroy(context); } }; class MongoCrypt : public Napi::ObjectWrap { public: static Napi::Function Init(Napi::Env env); private: Napi::Value MakeEncryptionContext(const Napi::CallbackInfo& info); Napi::Value MakeExplicitEncryptionContext(const Napi::CallbackInfo& info); Napi::Value MakeDecryptionContext(const Napi::CallbackInfo& info); Napi::Value MakeExplicitDecryptionContext(const Napi::CallbackInfo& info); Napi::Value MakeDataKeyContext(const Napi::CallbackInfo& info); Napi::Value MakeRewrapManyDataKeyContext(const Napi::CallbackInfo& info); Napi::Value Status(const Napi::CallbackInfo& info); Napi::Value CryptSharedLibVersionInfo(const Napi::CallbackInfo& info); private: friend class Napi::ObjectWrap; Napi::Function GetCallback(const char* name); void SetCallback(const char* name, Napi::Value fn); explicit MongoCrypt(const Napi::CallbackInfo& info); bool setupCryptoHooks(); static void logHandler(mongocrypt_log_level_t level, const char* message, uint32_t message_len, void* ctx); std::unique_ptr _mongo_crypt; }; class MongoCryptContext : public Napi::ObjectWrap { public: static Napi::Function Init(Napi::Env env); static Napi::Object NewInstance(Napi::Env env, std::unique_ptr context); private: Napi::Value NextMongoOperation(const Napi::CallbackInfo& info); void AddMongoOperationResponse(const Napi::CallbackInfo& info); void FinishMongoOperation(const Napi::CallbackInfo& info); Napi::Value NextKMSRequest(const Napi::CallbackInfo& info); void ProvideKMSProviders(const Napi::CallbackInfo& info); void FinishKMSRequests(const Napi::CallbackInfo& info); Napi::Value FinalizeContext(const Napi::CallbackInfo& info); Napi::Value Status(const Napi::CallbackInfo& info); Napi::Value State(const Napi::CallbackInfo& info); private: friend class Napi::ObjectWrap; explicit MongoCryptContext(const Napi::CallbackInfo& info); std::unique_ptr _context; }; class MongoCryptKMSRequest : public Napi::ObjectWrap { public: static Napi::Function Init(Napi::Env env); static Napi::Object NewInstance(Napi::Env env, mongocrypt_kms_ctx_t* kms_context); private: void AddResponse(const Napi::CallbackInfo& info); Napi::Value Status(const Napi::CallbackInfo& info); Napi::Value Message(const Napi::CallbackInfo& info); Napi::Value BytesNeeded(const Napi::CallbackInfo& info); Napi::Value KMSProvider(const Napi::CallbackInfo& info); Napi::Value Endpoint(const Napi::CallbackInfo& info); private: friend class Napi::ObjectWrap; explicit MongoCryptKMSRequest(const Napi::CallbackInfo& info); mongocrypt_kms_ctx_t* _kms_context; }; } // namespace node_mongocrypt #endif // NODE_MONGOCRYPT_H libmongocrypt-1.8.4/bindings/node/test/000077500000000000000000000000001454530651600201265ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/test/autoEncrypter.test.js000066400000000000000000000762121454530651600243160ustar00rootroot00000000000000'use strict'; const fs = require('fs'); const path = require('path'); const sinon = require('sinon'); const mongodb = require('mongodb'); const BSON = mongodb.BSON; const EJSON = BSON.EJSON; const requirements = require('./requirements.helper'); const MongoNetworkTimeoutError = mongodb.MongoNetworkTimeoutError || mongodb.MongoTimeoutError; const MongoError = mongodb.MongoError; const stateMachine = require('../lib/stateMachine')({ mongodb }); const StateMachine = stateMachine.StateMachine; const MongocryptdManager = require('../lib/mongocryptdManager').MongocryptdManager; const { expect } = require('chai'); const sharedLibrarySuffix = process.platform === 'win32' ? 'dll' : process.platform === 'darwin' ? 'dylib' : 'so'; let sharedLibraryStub = path.resolve( __dirname, '..', '..', '..', `mongo_crypt_v1.${sharedLibrarySuffix}` ); if (!fs.existsSync(sharedLibraryStub)) { sharedLibraryStub = path.resolve( __dirname, '..', 'deps', 'tmp', 'libmongocrypt-build', ...(process.platform === 'win32' ? ['RelWithDebInfo'] : []), `mongo_crypt_v1.${sharedLibrarySuffix}` ); } function readExtendedJsonToBuffer(path) { const ejson = EJSON.parse(fs.readFileSync(path, 'utf8')); return BSON.serialize(ejson); } function readHttpResponse(path) { let data = fs.readFileSync(path, 'utf8'); data = data.split('\n').join('\r\n'); return Buffer.from(data, 'utf8'); } const TEST_COMMAND = JSON.parse(fs.readFileSync(`${__dirname}/data/cmd.json`)); const MOCK_COLLINFO_RESPONSE = readExtendedJsonToBuffer(`${__dirname}/data/collection-info.json`); const MOCK_MONGOCRYPTD_RESPONSE = readExtendedJsonToBuffer( `${__dirname}/data/mongocryptd-reply.json` ); const MOCK_KEYDOCUMENT_RESPONSE = readExtendedJsonToBuffer(`${__dirname}/data/key-document.json`); const MOCK_KMS_DECRYPT_REPLY = readHttpResponse(`${__dirname}/data/kms-decrypt-reply.txt`); class MockClient { constructor() { this.topology = { bson: BSON }; } } const originalAccessKeyId = process.env.AWS_ACCESS_KEY_ID; const originalSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; const AutoEncrypter = require('../lib/autoEncrypter')({ mongodb, stateMachine }).AutoEncrypter; describe('AutoEncrypter', function () { this.timeout(12000); let ENABLE_LOG_TEST = false; let sandbox = sinon.createSandbox(); beforeEach(() => { sandbox.restore(); sandbox.stub(StateMachine.prototype, 'kmsRequest').callsFake(request => { request.addResponse(MOCK_KMS_DECRYPT_REPLY); return Promise.resolve(); }); sandbox .stub(StateMachine.prototype, 'fetchCollectionInfo') .callsFake((client, ns, filter, callback) => { callback(null, MOCK_COLLINFO_RESPONSE); }); sandbox .stub(StateMachine.prototype, 'markCommand') .callsFake((client, ns, command, callback) => { if (ENABLE_LOG_TEST) { const response = BSON.deserialize(MOCK_MONGOCRYPTD_RESPONSE); response.schemaRequiresEncryption = false; ENABLE_LOG_TEST = false; // disable test after run callback(null, BSON.serialize(response)); return; } callback(null, MOCK_MONGOCRYPTD_RESPONSE); }); sandbox.stub(StateMachine.prototype, 'fetchKeys').callsFake((client, ns, filter, callback) => { // mock data is already serialized, our action deals with the result of a cursor const deserializedKey = BSON.deserialize(MOCK_KEYDOCUMENT_RESPONSE); callback(null, [deserializedKey]); }); }); afterEach(() => { sandbox.restore(); }); describe('#constructor', function () { context('when mongodb exports BSON (driver >= 4.9.0)', function () { context('when a bson option is provided', function () { const bson = Object.assign({}, BSON); const encrypter = new AutoEncrypter( {}, { bson: bson, kmsProviders: { local: { key: Buffer.alloc(96) } } } ); it('uses the bson option', function () { expect(encrypter._bson).to.equal(bson); }); }); context('when a bson option is not provided', function () { const encrypter = new AutoEncrypter( {}, { kmsProviders: { local: { key: Buffer.alloc(96) } } } ); it('uses the mongodb exported BSON', function () { expect(encrypter._bson).to.equal(BSON); }); }); it('never uses bson from the topology', function () { expect(() => { new AutoEncrypter( {}, { kmsProviders: { local: { key: Buffer.alloc(96) } } } ); }).not.to.throw(); }); }); context('when mongodb does not export BSON (driver < 4.9.0)', function () { context('when a bson option is provided', function () { const bson = Object.assign({}, BSON); const encrypter = new AutoEncrypter( {}, { bson: bson, kmsProviders: { local: { key: Buffer.alloc(96) } } } ); it('uses the bson option', function () { expect(encrypter._bson).to.equal(bson); }); }); context('when a bson option is not provided', function () { const mongoNoBson = { ...mongodb, BSON: undefined }; const AutoEncrypterNoBson = require('../lib/autoEncrypter')({ mongodb: mongoNoBson, stateMachine }).AutoEncrypter; context('when the client has a topology', function () { const client = new MockClient(); const encrypter = new AutoEncrypterNoBson(client, { kmsProviders: { local: { key: Buffer.alloc(96) } } }); it('uses the bson on the topology', function () { expect(encrypter._bson).to.equal(client.topology.bson); }); }); context('when the client does not have a topology', function () { it('raises an error', function () { expect(() => { new AutoEncrypterNoBson({}, {}); }).to.throw(/bson/); }); }); }); }); context('when using mongocryptd', function () { const client = new MockClient(); const autoEncrypterOptions = { mongocryptdBypassSpawn: true, keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }; const autoEncrypter = new AutoEncrypter(client, autoEncrypterOptions); it('instantiates a mongo client on the auto encrypter', function () { expect(autoEncrypter) .to.have.property('_mongocryptdClient') .to.be.instanceOf(mongodb.MongoClient); }); it('sets the 3x legacy client options on the mongo client', function () { expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); const options = autoEncrypter._mongocryptdClient.s.options; expect(options).to.have.property('useUnifiedTopology', true); expect(options).to.have.property('useNewUrlParser', true); }); it('sets serverSelectionTimeoutMS to 10000ms', function () { expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); const options = autoEncrypter._mongocryptdClient.s.options; expect(options).to.have.property('serverSelectionTimeoutMS', 10000); }); context('when mongocryptdURI is not specified', () => { it('sets the ip address family to ipv4', function () { expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); const options = autoEncrypter._mongocryptdClient.s.options; expect(options).to.have.property('family', 4); }); }); context('when mongocryptdURI is specified', () => { it('does not set the ip address family to ipv4', function () { const autoEncrypter = new AutoEncrypter(client, { ...autoEncrypterOptions, extraOptions: { mongocryptdURI: MongocryptdManager.DEFAULT_MONGOCRYPTD_URI } }); expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); const options = autoEncrypter._mongocryptdClient.s.options; expect(options).not.to.have.property('family', 4); }); }); }); }); it('should support `bypassAutoEncryption`', function (done) { const client = new MockClient(); const autoEncrypter = new AutoEncrypter(client, { bypassAutoEncryption: true, mongocryptdBypassSpawn: true, keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); autoEncrypter.encrypt('test.test', { test: 'command' }, (err, encrypted) => { expect(err).to.not.exist; expect(encrypted).to.eql({ test: 'command' }); done(); }); }); describe('state machine', function () { it('should decrypt mock data', function (done) { const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); mc.decrypt(input, (err, decrypted) => { if (err) return done(err); expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); expect(decrypted).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); expect(decrypted.filter).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); done(); }); }); it('should decrypt mock data and mark decrypted items if enabled for testing', function (done) { const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); const nestedInput = readExtendedJsonToBuffer( `${__dirname}/data/encrypted-document-nested.json` ); const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); mc[Symbol.for('@@mdb.decorateDecryptionResult')] = true; mc.decrypt(input, (err, decrypted) => { if (err) return done(err); expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); expect(decrypted).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); expect(decrypted.filter[Symbol.for('@@mdb.decryptedKeys')]).to.eql(['ssn']); // The same, but with an object containing different data types as the input mc.decrypt({ a: [null, 1, { c: new BSON.Binary('foo', 1) }] }, (err, decrypted) => { if (err) return done(err); expect(decrypted).to.eql({ a: [null, 1, { c: new BSON.Binary('foo', 1) }] }); expect(decrypted).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); // The same, but with nested data inside the decrypted input mc.decrypt(nestedInput, (err, decrypted) => { if (err) return done(err); expect(decrypted).to.eql({ nested: { x: { y: 1234 } } }); expect(decrypted[Symbol.for('@@mdb.decryptedKeys')]).to.eql(['nested']); expect(decrypted.nested).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); expect(decrypted.nested.x).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); expect(decrypted.nested.x.y).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); done(); }); }); }); }); it('should decrypt mock data with per-context KMS credentials', function (done) { const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: {} }, async onKmsProviderRefresh() { return { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }; } }); mc.decrypt(input, (err, decrypted) => { if (err) return done(err); expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); done(); }); }); context('when no refresh function is provided', function () { const accessKey = 'example'; const secretKey = 'example'; before(function () { if (!requirements.credentialProvidersInstalled.aws) { this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; this.currentTest.skip(); return; } // After the entire suite runs, set the env back for the rest of the test run. process.env.AWS_ACCESS_KEY_ID = accessKey; process.env.AWS_SECRET_ACCESS_KEY = secretKey; }); after(function () { // After the entire suite runs, set the env back for the rest of the test run. process.env.AWS_ACCESS_KEY_ID = originalAccessKeyId; process.env.AWS_SECRET_ACCESS_KEY = originalSecretAccessKey; }); it('should decrypt mock data with KMS credentials from the environment', function (done) { const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: {} } }); mc.decrypt(input, (err, decrypted) => { if (err) return done(err); expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); done(); }); }); }); context('when no refresh function is provided and no optional sdk', function () { const accessKey = 'example'; const secretKey = 'example'; before(function () { if (requirements.credentialProvidersInstalled.aws) { this.currentTest.skipReason = 'With optional sdk installed credentials would be loaded.'; this.currentTest.skip(); return; } // After the entire suite runs, set the env back for the rest of the test run. process.env.AWS_ACCESS_KEY_ID = accessKey; process.env.AWS_SECRET_ACCESS_KEY = secretKey; }); after(function () { // After the entire suite runs, set the env back for the rest of the test run. process.env.AWS_ACCESS_KEY_ID = originalAccessKeyId; process.env.AWS_SECRET_ACCESS_KEY = originalSecretAccessKey; }); it('errors without the optional sdk credential provider', function (done) { const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: {} } }); mc.decrypt(input, err => { expect(err.message).to.equal( 'client not configured with KMS provider necessary to decrypt' ); done(); }); }); }); it('should encrypt mock data', function (done) { const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { if (err) return done(err); const expected = EJSON.parse( JSON.stringify({ find: 'test', filter: { ssn: { $binary: { base64: 'AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=', subType: '6' } } } }) ); expect(encrypted).to.containSubset(expected); done(); }); }); it('should encrypt mock data with per-context KMS credentials', function (done) { const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: {} }, async onKmsProviderRefresh() { return { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }; } }); mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { if (err) return done(err); const expected = EJSON.parse( JSON.stringify({ find: 'test', filter: { ssn: { $binary: { base64: 'AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=', subType: '6' } } } }) ); expect(encrypted).to.containSubset(expected); done(); }); }); // TODO(NODE-4089): Enable test once https://github.com/mongodb/libmongocrypt/pull/263 is done it.skip('should encrypt mock data when using the crypt_shared library', function (done) { const client = new MockClient(); const mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: {} }, async onKmsProviderRefresh() { return { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }; }, extraOptions: { cryptSharedLibPath: sharedLibraryStub } }); expect(mc).to.not.have.property('_mongocryptdManager'); expect(mc).to.not.have.property('_mongocryptdClient'); mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { if (err) return done(err); const expected = EJSON.parse( JSON.stringify({ find: 'test', filter: { ssn: { $binary: { base64: 'AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=', subType: '6' } } } }) ); expect(encrypted).to.containSubset(expected); done(); }); }); }); describe('logging', function () { it('should allow registration of a log handler', function (done) { ENABLE_LOG_TEST = true; let loggerCalled = false; const logger = (level, message) => { if (loggerCalled) return; loggerCalled = true; expect(level).to.be.oneOf([2, 3]); expect(message).to.not.be.empty; }; const client = new MockClient(); const mc = new AutoEncrypter(client, { logger, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { if (err) return done(err); const expected = EJSON.parse( JSON.stringify({ find: 'test', filter: { ssn: '457-55-5462' } }) ); expect(encrypted).to.containSubset(expected); done(); }); }); }); describe('autoSpawn', function () { beforeEach(function () { if (requirements.SKIP_LIVE_TESTS) { this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; this.currentTest.skip(); return; } }); afterEach(function (done) { if (this.mc) { this.mc.teardown(false, err => { this.mc = undefined; done(err); }); } else { done(); } }); it('should autoSpawn a mongocryptd on init by default', function (done) { const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); const localMcdm = this.mc._mongocryptdManager; sandbox.spy(localMcdm, 'spawn'); this.mc.init(err => { if (err) return done(err); expect(localMcdm.spawn).to.have.been.calledOnce; done(); }); }); it('should not attempt to kick off mongocryptd on a normal error', function (done) { let called = false; StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { if (!called) { called = true; callback(new Error('msg')); return; } callback(null, MOCK_MONGOCRYPTD_RESPONSE); }); const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); const localMcdm = this.mc._mongocryptdManager; this.mc.init(err => { if (err) return done(err); sandbox.spy(localMcdm, 'spawn'); this.mc.encrypt('test.test', TEST_COMMAND, err => { expect(localMcdm.spawn).to.not.have.been.called; expect(err).to.be.an.instanceOf(Error); done(); }); }); }); it('should restore the mongocryptd and retry once if a MongoNetworkTimeoutError is experienced', function (done) { let called = false; StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { if (!called) { called = true; callback(new MongoNetworkTimeoutError('msg')); return; } callback(null, MOCK_MONGOCRYPTD_RESPONSE); }); const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); const localMcdm = this.mc._mongocryptdManager; this.mc.init(err => { if (err) return done(err); sandbox.spy(localMcdm, 'spawn'); this.mc.encrypt('test.test', TEST_COMMAND, err => { expect(localMcdm.spawn).to.have.been.calledOnce; expect(err).to.not.exist; done(); }); }); }); it('should propagate error if MongoNetworkTimeoutError is experienced twice in a row', function (done) { let counter = 2; StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { if (counter) { counter -= 1; callback(new MongoNetworkTimeoutError('msg')); return; } callback(null, MOCK_MONGOCRYPTD_RESPONSE); }); const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } } }); expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); const localMcdm = this.mc._mongocryptdManager; this.mc.init(err => { if (err) return done(err); sandbox.spy(localMcdm, 'spawn'); this.mc.encrypt('test.test', TEST_COMMAND, err => { expect(localMcdm.spawn).to.have.been.calledOnce; expect(err).to.be.an.instanceof(MongoNetworkTimeoutError); done(); }); }); }); it('should return a useful message if mongocryptd fails to autospawn', function (done) { const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } }, extraOptions: { mongocryptdURI: 'mongodb://something.invalid:27020/' } }); expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); sandbox.stub(MongocryptdManager.prototype, 'spawn').callsFake(callback => { callback(); }); this.mc.init(err => { expect(err).to.exist; expect(err).to.be.instanceOf(MongoError); done(); }); }); }); describe('noAutoSpawn', function () { beforeEach('start MongocryptdManager', function (done) { if (requirements.SKIP_LIVE_TESTS) { this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; this.skip(); } this.mcdm = new MongocryptdManager({}); this.mcdm.spawn(done); }); afterEach(function (done) { if (this.mc) { this.mc.teardown(false, err => { this.mc = undefined; done(err); }); } else { done(); } }); ['mongocryptdBypassSpawn', 'bypassAutoEncryption', 'bypassQueryAnalysis'].forEach(opt => { const encryptionOptions = { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } }, extraOptions: { mongocryptdBypassSpawn: opt === 'mongocryptdBypassSpawn' }, bypassAutoEncryption: opt === 'bypassAutoEncryption', bypassQueryAnalysis: opt === 'bypassQueryAnalysis' }; it(`should not spawn mongocryptd on startup if ${opt} is true`, function (done) { const client = new MockClient(); this.mc = new AutoEncrypter(client, encryptionOptions); const localMcdm = this.mc._mongocryptdManager || { spawn: () => {} }; sandbox.spy(localMcdm, 'spawn'); this.mc.init(err => { expect(err).to.not.exist; expect(localMcdm.spawn).to.have.a.callCount(0); done(); }); }); }); it('should not spawn a mongocryptd or retry on a server selection error if mongocryptdBypassSpawn: true', function (done) { let called = false; const timeoutError = new MongoNetworkTimeoutError('msg'); StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { if (!called) { called = true; callback(timeoutError); return; } callback(null, MOCK_MONGOCRYPTD_RESPONSE); }); const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } }, extraOptions: { mongocryptdBypassSpawn: true } }); const localMcdm = this.mc._mongocryptdManager; sandbox.spy(localMcdm, 'spawn'); this.mc.init(err => { expect(err).to.not.exist; expect(localMcdm.spawn).to.not.have.been.called; this.mc.encrypt('test.test', TEST_COMMAND, (err, response) => { expect(localMcdm.spawn).to.not.have.been.called; expect(response).to.not.exist; expect(err).to.equal(timeoutError); done(); }); }); }); }); describe('crypt_shared library', function () { it('should fail if no library can be found in the search path and cryptSharedLibRequired is set', function () { // NB: This test has to be run before the tests/without having previously // loaded a CSFLE shared library below to get the right error path. const client = new MockClient(); try { new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } }, extraOptions: { cryptSharedLibSearchPaths: ['/nonexistent'], cryptSharedLibRequired: true } }); expect.fail('missed exception'); } catch (err) { expect(err.message).to.include( '`cryptSharedLibRequired` set but no crypt_shared library loaded' ); } }); it('should load a shared library by specifying its path', function (done) { const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } }, extraOptions: { cryptSharedLibPath: sharedLibraryStub } }); expect(this.mc).to.not.have.property('_mongocryptdManager'); expect(this.mc).to.not.have.property('_mongocryptdClient'); expect(this.mc).to.have.deep.property('cryptSharedLibVersionInfo', { // eslint-disable-next-line no-undef version: BigInt(0x000600020001000), versionStr: 'stubbed-crypt_shared' }); this.mc.teardown(true, done); }); it('should load a shared library by specifying a search path', function (done) { const client = new MockClient(); this.mc = new AutoEncrypter(client, { keyVaultNamespace: 'admin.datakeys', logger: () => {}, kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' }, local: { key: Buffer.alloc(96) } }, extraOptions: { cryptSharedLibSearchPaths: [path.dirname(sharedLibraryStub)] } }); expect(this.mc).to.not.have.property('_mongocryptdManager'); expect(this.mc).to.not.have.property('_mongocryptdClient'); expect(this.mc).to.have.deep.property('cryptSharedLibVersionInfo', { // eslint-disable-next-line no-undef version: BigInt(0x000600020001000), versionStr: 'stubbed-crypt_shared' }); this.mc.teardown(true, done); }); }); it('should provide the libmongocrypt version', function () { expect(AutoEncrypter.libmongocryptVersion).to.be.a('string'); }); }); libmongocrypt-1.8.4/bindings/node/test/buffer_pool.test.js000066400000000000000000000061751454530651600237550ustar00rootroot00000000000000'use strict'; const { BufferPool } = require('../lib/buffer_pool'); const { expect } = require('chai'); describe('new BufferPool()', function () { it('should report the correct length', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1])); buffer.append(Buffer.from([2, 3])); buffer.append(Buffer.from([2, 3])); expect(buffer).property('length').to.equal(6); }); it('return an empty buffer if too many bytes requested', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1, 2, 3])); const data = buffer.read(6); expect(data).to.have.length(0); expect(buffer).property('length').to.equal(4); }); context('peek', function () { it('exact size', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1])); const data = buffer.peek(2); expect(data).to.eql(Buffer.from([0, 1])); expect(buffer).property('length').to.equal(2); }); it('within first buffer', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1, 2, 3])); const data = buffer.peek(2); expect(data).to.eql(Buffer.from([0, 1])); expect(buffer).property('length').to.equal(4); }); it('across multiple buffers', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1])); buffer.append(Buffer.from([2, 3])); buffer.append(Buffer.from([4, 5])); expect(buffer).property('length').to.equal(6); const data = buffer.peek(5); expect(data).to.eql(Buffer.from([0, 1, 2, 3, 4])); expect(buffer).property('length').to.equal(6); }); }); context('read', function () { it('should throw an error if a negative size is requested', function () { const buffer = new BufferPool(); expect(() => buffer.read(-1)).to.throw(/Argument "size" must be a non-negative number/); }); it('should throw an error if a non-number size is requested', function () { const buffer = new BufferPool(); expect(() => buffer.read('256')).to.throw(/Argument "size" must be a non-negative number/); }); it('exact size', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1])); const data = buffer.read(2); expect(data).to.eql(Buffer.from([0, 1])); expect(buffer).property('length').to.equal(0); }); it('within first buffer', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1, 2, 3])); const data = buffer.read(2); expect(data).to.eql(Buffer.from([0, 1])); expect(buffer).property('length').to.equal(2); }); it('across multiple buffers', function () { const buffer = new BufferPool(); buffer.append(Buffer.from([0, 1])); buffer.append(Buffer.from([2, 3])); buffer.append(Buffer.from([4, 5])); expect(buffer).property('length').to.equal(6); const data = buffer.read(5); expect(data).to.eql(Buffer.from([0, 1, 2, 3, 4])); expect(buffer).property('length').to.equal(1); expect(buffer.read(1)).to.eql(Buffer.from([5])); }); }); }); libmongocrypt-1.8.4/bindings/node/test/clientEncryption.test.js000066400000000000000000001134621454530651600250020ustar00rootroot00000000000000'use strict'; const fs = require('fs'); const { expect } = require('chai'); const sinon = require('sinon'); const mongodb = require('mongodb'); const BSON = mongodb.BSON; const MongoClient = mongodb.MongoClient; const cryptoCallbacks = require('../lib/cryptoCallbacks'); const stateMachine = require('../lib/stateMachine')({ mongodb }); const StateMachine = stateMachine.StateMachine; const { Binary, EJSON, deserialize } = BSON; const { MongoCryptCreateEncryptedCollectionError, MongoCryptCreateDataKeyError } = require('../lib/errors'); function readHttpResponse(path) { let data = fs.readFileSync(path, 'utf8').toString(); data = data.split('\n').join('\r\n'); return Buffer.from(data, 'utf8'); } const ClientEncryption = require('../lib/clientEncryption')({ mongodb, stateMachine }).ClientEncryption; class MockClient { constructor() { this.topology = { bson: BSON }; } db(dbName) { return { async createCollection(name, options) { return { namespace: `${dbName}.${name}`, options }; } }; } } const requirements = require('./requirements.helper'); describe('ClientEncryption', function () { this.timeout(12000); /** @type {MongoClient} */ let client; function throwIfNotNsNotFoundError(err) { if (!err.message.match(/ns not found/)) { throw err; } } async function setup() { client = new MongoClient(process.env.MONGODB_URI || 'mongodb://localhost:27017/test'); await client.connect(); try { await client.db('client').collection('encryption').drop(); } catch (err) { throwIfNotNsNotFoundError(err); } } function teardown() { if (requirements.SKIP_LIVE_TESTS) { return Promise.resolve(); } return client.close(); } describe('#constructor', function () { context('when mongodb exports BSON (driver >= 4.9.0)', function () { context('when a bson option is provided', function () { const bson = Object.assign({}, BSON); const encrypter = new ClientEncryption( {}, { bson: bson, keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } } ); it('uses the bson option', function () { expect(encrypter._bson).to.equal(bson); }); }); context('when a bson option is not provided', function () { const encrypter = new ClientEncryption( {}, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } } ); it('uses the mongodb exported BSON', function () { expect(encrypter._bson).to.equal(BSON); }); }); it('never uses bson from the topology', function () { expect(() => { new ClientEncryption( {}, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } } ); }).not.to.throw(); }); }); context('when mongodb does not export BSON (driver < 4.9.0)', function () { context('when a bson option is provided', function () { const bson = Object.assign({}, BSON); const encrypter = new ClientEncryption( {}, { bson: bson, keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } } ); it('uses the bson option', function () { expect(encrypter._bson).to.equal(bson); }); }); context('when a bson option is not provided', function () { const mongoNoBson = { ...mongodb, BSON: undefined }; const ClientEncryptionNoBson = require('../lib/clientEncryption')({ mongodb: mongoNoBson, stateMachine }).ClientEncryption; context('when the client has a topology', function () { const client = new MockClient(); const encrypter = new ClientEncryptionNoBson(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } }); it('uses the bson on the topology', function () { expect(encrypter._bson).to.equal(client.topology.bson); }); }); context('when the client does not have a topology', function () { it('raises an error', function () { expect(() => { new ClientEncryptionNoBson({}, {}); }).to.throw(/bson/); }); }); }); }); }); describe('stubbed stateMachine', function () { let sandbox = sinon.createSandbox(); after(() => sandbox.restore()); before(() => { // stubbed out for AWS unit testing below const MOCK_KMS_ENCRYPT_REPLY = readHttpResponse(`${__dirname}/data/kms-encrypt-reply.txt`); sandbox.stub(StateMachine.prototype, 'kmsRequest').callsFake(request => { request.addResponse(MOCK_KMS_ENCRYPT_REPLY); return Promise.resolve(); }); }); beforeEach(function () { if (requirements.SKIP_LIVE_TESTS) { this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; this.test.skip(); return; } return setup(); }); afterEach(function () { return teardown(); }); [ { name: 'local', kmsProviders: { local: { key: Buffer.alloc(96) } } }, { name: 'aws', kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }, options: { masterKey: { region: 'region', key: 'cmk' } } } ].forEach(providerTest => { it(`should create a data key with the "${providerTest.name}" KMS provider`, async function () { const providerName = providerTest.name; const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: providerTest.kmsProviders }); const dataKeyOptions = providerTest.options || {}; const dataKey = await encryption.createDataKey(providerName, dataKeyOptions); expect(dataKey).property('_bsontype', 'Binary'); const doc = await client.db('client').collection('encryption').findOne({ _id: dataKey }); expect(doc).to.have.property('masterKey'); expect(doc.masterKey).property('provider', providerName); }); it(`should create a data key with the "${providerTest.name}" KMS provider (fixed key material)`, async function () { const providerName = providerTest.name; const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: providerTest.kmsProviders }); const dataKeyOptions = { ...providerTest.options, keyMaterial: new BSON.Binary(Buffer.alloc(96)) }; const dataKey = await encryption.createDataKey(providerName, dataKeyOptions); expect(dataKey).property('_bsontype', 'Binary'); const doc = await client.db('client').collection('encryption').findOne({ _id: dataKey }); expect(doc).to.have.property('masterKey'); expect(doc.masterKey).property('provider', providerName); }); }); it(`should create a data key with the local KMS provider (fixed key material, fixed key UUID)`, async function () { // 'Custom Key Material Test' prose spec test: const keyVaultColl = client.db('client').collection('encryption'); const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: 'A'.repeat(128) // the value here is not actually relevant } } }); const dataKeyOptions = { keyMaterial: new BSON.Binary( Buffer.from( 'xPTAjBRG5JiPm+d3fj6XLi2q5DMXUS/f1f+SMAlhhwkhDRL0kr8r9GDLIGTAGlvC+HVjSIgdL+RKwZCvpXSyxTICWSXTUYsWYPyu3IoHbuBZdmw2faM3WhcRIgbMReU5', 'base64' ) ) }; const dataKey = await encryption.createDataKey('local', dataKeyOptions); expect(dataKey._bsontype).to.equal('Binary'); // Remove and re-insert with a fixed UUID to guarantee consistent output const doc = ( await keyVaultColl.findOneAndDelete({ _id: dataKey }, { writeConcern: { w: 'majority' } }) ).value; doc._id = new BSON.Binary(Buffer.alloc(16), 4); await keyVaultColl.insertOne(doc, { writeConcern: { w: 'majority' } }); const encrypted = await encryption.encrypt('test', { keyId: doc._id, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); expect(encrypted._bsontype).to.equal('Binary'); expect(encrypted.toString('base64')).to.equal( 'AQAAAAAAAAAAAAAAAAAAAAACz0ZOLuuhEYi807ZXTdhbqhLaS2/t9wLifJnnNYwiw79d75QYIZ6M/aYC1h9nCzCjZ7pGUpAuNnkUhnIXM3PjrA==' ); }); it('should fail to create a data key if keyMaterial is wrong', function (done) { const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: 'A'.repeat(128) } } }); const dataKeyOptions = { keyMaterial: new BSON.Binary(Buffer.alloc(97)) }; try { encryption.createDataKey('local', dataKeyOptions); expect.fail('missed exception'); } catch (err) { expect(err.message).to.equal('keyMaterial should have length 96, but has length 97'); done(); } }); it('should explicitly encrypt and decrypt with the "local" KMS provider', function (done) { const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } }); encryption.createDataKey('local', (err, dataKey) => { expect(err).to.not.exist; const encryptOptions = { keyId: dataKey, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }; encryption.encrypt('hello', encryptOptions, (err, encrypted) => { expect(err).to.not.exist; expect(encrypted._bsontype).to.equal('Binary'); expect(encrypted.sub_type).to.equal(6); encryption.decrypt(encrypted, (err, decrypted) => { expect(err).to.not.exist; expect(decrypted).to.equal('hello'); done(); }); }); }); }); it('should explicitly encrypt and decrypt with the "local" KMS provider (promise)', function () { const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } }); return encryption .createDataKey('local') .then(dataKey => { const encryptOptions = { keyId: dataKey, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }; return encryption.encrypt('hello', encryptOptions); }) .then(encrypted => { expect(encrypted._bsontype).to.equal('Binary'); expect(encrypted.sub_type).to.equal(6); return encryption.decrypt(encrypted); }) .then(decrypted => { expect(decrypted).to.equal('hello'); }); }); it('should explicitly encrypt and decrypt with a re-wrapped local key', function () { // Create new ClientEncryption instances to make sure // that we are actually using the rewrapped keys and not // something that has been cached. const newClientEncryption = () => new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: 'A'.repeat(128) } } }); let encrypted; return newClientEncryption() .createDataKey('local') .then(dataKey => { const encryptOptions = { keyId: dataKey, algorithm: 'Indexed', contentionFactor: 0 }; return newClientEncryption().encrypt('hello', encryptOptions); }) .then(_encrypted => { encrypted = _encrypted; expect(encrypted._bsontype).to.equal('Binary'); expect(encrypted.sub_type).to.equal(6); }) .then(() => { return newClientEncryption().rewrapManyDataKey({}); }) .then(rewrapManyDataKeyResult => { expect(rewrapManyDataKeyResult.bulkWriteResult.result.nModified).to.equal(1); return newClientEncryption().decrypt(encrypted); }) .then(decrypted => { expect(decrypted).to.equal('hello'); }); }); it('should not perform updates if no keys match', function () { const clientEncryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: 'A'.repeat(128) } } }); return clientEncryption.rewrapManyDataKey({ _id: 12345 }).then(rewrapManyDataKeyResult => { expect(rewrapManyDataKeyResult.bulkWriteResult).to.equal(undefined); }); }); it.skip('should explicitly encrypt and decrypt with a re-wrapped local key (explicit session/transaction)', function () { const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: 'A'.repeat(128) } } }); let encrypted; let rewrapManyDataKeyResult; return encryption .createDataKey('local') .then(dataKey => { const encryptOptions = { keyId: dataKey, algorithm: 'Indexed', contentionFactor: 0 }; return encryption.encrypt('hello', encryptOptions); }) .then(_encrypted => { encrypted = _encrypted; }) .then(() => { // withSession does not forward the callback's return value, hence // the slightly awkward 'rewrapManyDataKeyResult' passing here return client.withSession(session => { return session.withTransaction(() => { expect(session.transaction.isStarting).to.equal(true); expect(session.transaction.isActive).to.equal(true); rewrapManyDataKeyResult = encryption.rewrapManyDataKey( {}, { provider: 'local', session } ); return rewrapManyDataKeyResult.then(() => { // Verify that the 'session' argument was actually used expect(session.transaction.isStarting).to.equal(false); expect(session.transaction.isActive).to.equal(true); }); }); }); }) .then(() => { return rewrapManyDataKeyResult; }) .then(rewrapManyDataKeyResult => { expect(rewrapManyDataKeyResult.bulkWriteResult.result.nModified).to.equal(1); return encryption.decrypt(encrypted); }) .then(decrypted => { expect(decrypted).to.equal('hello'); }); }).skipReason = 'TODO(DRIVERS-2389): add explicit session support to key management API'; // TODO(NODE-3371): resolve KMS JSON response does not include string 'Plaintext'. HTTP status=200 error it.skip('should explicitly encrypt and decrypt with the "aws" KMS provider', function (done) { const encryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' } } }); const dataKeyOptions = { masterKey: { region: 'region', key: 'cmk' } }; encryption.createDataKey('aws', dataKeyOptions, (err, dataKey) => { expect(err).to.not.exist; const encryptOptions = { keyId: dataKey, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }; encryption.encrypt('hello', encryptOptions, (err, encrypted) => { expect(err).to.not.exist; expect(encrypted).to.have.property('v'); expect(encrypted.v._bsontype).to.equal('Binary'); expect(encrypted.v.sub_type).to.equal(6); encryption.decrypt(encrypted, (err, decrypted) => { expect(err).to.not.exist; expect(decrypted).to.equal('hello'); done(); }); }); }); }).skipReason = "TODO(NODE-3371): resolve KMS JSON response does not include string 'Plaintext'. HTTP status=200 error"; }); describe('ClientEncryptionKeyAltNames', function () { const kmsProviders = requirements.awsKmsProviders; const dataKeyOptions = requirements.awsDataKeyOptions; beforeEach(function () { if (requirements.SKIP_AWS_TESTS) { this.currentTest.skipReason = `requirements.SKIP_AWS_TESTS=${requirements.SKIP_AWS_TESTS}`; this.currentTest.skip(); return; } return setup().then(() => { this.client = client; this.collection = client.db('client').collection('encryption'); this.encryption = new ClientEncryption(this.client, { keyVaultNamespace: 'client.encryption', kmsProviders }); }); }); afterEach(function () { return teardown().then(() => { this.encryption = undefined; this.collection = undefined; this.client = undefined; }); }); function makeOptions(keyAltNames) { expect(dataKeyOptions.masterKey).to.be.an('object'); expect(dataKeyOptions.masterKey.key).to.be.a('string'); expect(dataKeyOptions.masterKey.region).to.be.a('string'); return { masterKey: { key: dataKeyOptions.masterKey.key, region: dataKeyOptions.masterKey.region }, keyAltNames }; } describe('errors', function () { [42, 'hello', { keyAltNames: 'foobar' }, /foobar/].forEach(val => { it(`should fail if typeof keyAltNames = ${typeof val}`, function () { const options = makeOptions(val); expect(() => this.encryption.createDataKey('aws', options, () => undefined)).to.throw( TypeError ); }); }); [undefined, null, 42, { keyAltNames: 'foobar' }, ['foobar'], /foobar/].forEach(val => { it(`should fail if typeof keyAltNames[x] = ${typeof val}`, function () { const options = makeOptions([val]); expect(() => this.encryption.createDataKey('aws', options, () => undefined)).to.throw( TypeError ); }); }); }); it('should create a key with keyAltNames', function () { let dataKey; const options = makeOptions(['foobar']); return this.encryption .createDataKey('aws', options) .then(_dataKey => (dataKey = _dataKey)) .then(() => this.collection.findOne({ keyAltNames: 'foobar' })) .then(document => { expect(document).to.be.an('object'); expect(document).to.have.property('keyAltNames').that.includes.members(['foobar']); expect(document).to.have.property('_id').that.deep.equals(dataKey); }); }); it('should create a key with multiple keyAltNames', function () { let dataKey; return this.encryption .createDataKey('aws', makeOptions(['foobar', 'fizzbuzz'])) .then(_dataKey => (dataKey = _dataKey)) .then(() => Promise.all([ this.collection.findOne({ keyAltNames: 'foobar' }), this.collection.findOne({ keyAltNames: 'fizzbuzz' }) ]) ) .then(docs => { expect(docs).to.have.lengthOf(2); const doc1 = docs[0]; const doc2 = docs[1]; expect(doc1).to.be.an('object'); expect(doc2).to.be.an('object'); expect(doc1) .to.have.property('keyAltNames') .that.includes.members(['foobar', 'fizzbuzz']); expect(doc1).to.have.property('_id').that.deep.equals(dataKey); expect(doc2) .to.have.property('keyAltNames') .that.includes.members(['foobar', 'fizzbuzz']); expect(doc2).to.have.property('_id').that.deep.equals(dataKey); }); }); it('should be able to reference a key with `keyAltName` during encryption', function () { let keyId; const keyAltName = 'mySpecialKey'; const algorithm = 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'; const valueToEncrypt = 'foobar'; return this.encryption .createDataKey('aws', makeOptions([keyAltName])) .then(_dataKey => (keyId = _dataKey)) .then(() => this.encryption.encrypt(valueToEncrypt, { keyId, algorithm })) .then(encryptedValue => { return this.encryption .encrypt(valueToEncrypt, { keyAltName, algorithm }) .then(encryptedValue2 => { expect(encryptedValue).to.deep.equal(encryptedValue2); }); }); }); }); context('with stubbed key material and fixed random source', function () { let sandbox = sinon.createSandbox(); afterEach(() => { sandbox.restore(); }); beforeEach(() => { const rndData = Buffer.from( '\x4d\x06\x95\x64\xf5\xa0\x5e\x9e\x35\x23\xb9\x8f\x57\x5a\xcb\x15', 'latin1' ); let rndPos = 0; sandbox.stub(cryptoCallbacks, 'randomHook').callsFake((buffer, count) => { if (rndPos + count > rndData) { return new Error('Out of fake random data'); } buffer.set(rndData.subarray(rndPos, rndPos + count)); rndPos += count; return count; }); // stubbed out for AWS unit testing below sandbox.stub(StateMachine.prototype, 'fetchKeys').callsFake((client, ns, filter, cb) => { filter = deserialize(filter); const keyIds = filter.$or[0]._id.$in.map(key => key.toString('hex')); const fileNames = keyIds.map( keyId => `${__dirname}/../../../test/data/keys/${keyId.toUpperCase()}-local-document.json` ); const contents = fileNames.map(filename => EJSON.parse(fs.readFileSync(filename))); cb(null, contents); }); }); // This exactly matches _test_encrypt_fle2_explicit from the C tests it('should explicitly encrypt and decrypt with the "local" KMS provider (FLE2, exact result)', function () { const encryption = new ClientEncryption(new MockClient(), { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } }); const encryptOptions = { keyId: new Binary(Buffer.from('ABCDEFAB123498761234123456789012', 'hex'), 4), algorithm: 'Unindexed' }; return encryption .encrypt('value123', encryptOptions) .then(encrypted => { expect(encrypted._bsontype).to.equal('Binary'); expect(encrypted.sub_type).to.equal(6); return encryption.decrypt(encrypted); }) .then(decrypted => { expect(decrypted).to.equal('value123'); }); }); }); describe('encrypt()', function () { let clientEncryption; let completeOptions; let dataKey; beforeEach(async function () { if (requirements.SKIP_LIVE_TESTS) { this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; this.test.skip(); return; } await setup(); clientEncryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } }); dataKey = await clientEncryption.createDataKey('local', { name: 'local', kmsProviders: { local: { key: Buffer.alloc(96) } } }); completeOptions = { algorithm: 'RangePreview', contentionFactor: 0, rangeOptions: { min: new BSON.Long(0), max: new BSON.Long(10), sparsity: new BSON.Long(1) }, keyId: dataKey }; }); afterEach(() => teardown()); context('when expressionMode is incorrectly provided as an argument', function () { it('overrides the provided option with the correct value for expression mode', async function () { const optionsWithExpressionMode = { ...completeOptions, expressionMode: true }; const result = await clientEncryption.encrypt( new mongodb.Long(0), optionsWithExpressionMode ); expect(result).to.be.instanceof(Binary); }); }); }); describe('encryptExpression()', function () { let clientEncryption; let completeOptions; let dataKey; const expression = { $and: [{ someField: { $gt: 1 } }] }; beforeEach(async function () { if (requirements.SKIP_LIVE_TESTS) { this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; this.test.skip(); return; } await setup(); clientEncryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96) } } }); dataKey = await clientEncryption.createDataKey('local', { name: 'local', kmsProviders: { local: { key: Buffer.alloc(96) } } }); completeOptions = { algorithm: 'RangePreview', queryType: 'rangePreview', contentionFactor: 0, rangeOptions: { min: new BSON.Int32(0), max: new BSON.Int32(10), sparsity: new BSON.Long(1) }, keyId: dataKey }; }); afterEach(() => teardown()); it('throws if rangeOptions is not provided', async function () { expect(delete completeOptions.rangeOptions).to.be.true; const errorOrResult = await clientEncryption .encryptExpression(expression, completeOptions) .catch(e => e); expect(errorOrResult).to.be.instanceof(TypeError); }); it('throws if algorithm is not provided', async function () { expect(delete completeOptions.algorithm).to.be.true; const errorOrResult = await clientEncryption .encryptExpression(expression, completeOptions) .catch(e => e); expect(errorOrResult).to.be.instanceof(TypeError); }); it(`throws if algorithm does not equal 'rangePreview'`, async function () { completeOptions['algorithm'] = 'equality'; const errorOrResult = await clientEncryption .encryptExpression(expression, completeOptions) .catch(e => e); expect(errorOrResult).to.be.instanceof(TypeError); }); it(`does not throw if algorithm has different casing than 'rangePreview'`, async function () { completeOptions['algorithm'] = 'rAnGePrEvIeW'; const errorOrResult = await clientEncryption .encryptExpression(expression, completeOptions) .catch(e => e); expect(errorOrResult).not.to.be.instanceof(Error); }); context('when expressionMode is incorrectly provided as an argument', function () { it('overrides the provided option with the correct value for expression mode', async function () { const optionsWithExpressionMode = { ...completeOptions, expressionMode: false }; const result = await clientEncryption.encryptExpression( expression, optionsWithExpressionMode ); expect(result).not.to.be.instanceof(Binary); }); }); }); it('should provide the libmongocrypt version', function () { expect(ClientEncryption.libmongocryptVersion).to.be.a('string'); }); describe('createEncryptedCollection()', () => { /** @type {InstanceType} */ let clientEncryption; const client = new MockClient(); let db; const collectionName = 'secure'; beforeEach(async function () { clientEncryption = new ClientEncryption(client, { keyVaultNamespace: 'client.encryption', kmsProviders: { local: { key: Buffer.alloc(96, 0) } } }); db = client.db('createEncryptedCollectionDb'); }); afterEach(async () => { sinon.restore(); }); context('validates input', () => { it('throws TypeError if options are omitted', async () => { const error = await clientEncryption .createEncryptedCollection(db, collectionName) .catch(error => error); expect(error).to.be.instanceOf(TypeError, /provider/); }); it('throws TypeError if options.createCollectionOptions are omitted', async () => { const error = await clientEncryption .createEncryptedCollection(db, collectionName, {}) .catch(error => error); expect(error).to.be.instanceOf(TypeError, /encryptedFields/); }); it('throws TypeError if options.createCollectionOptions.encryptedFields are omitted', async () => { const error = await clientEncryption .createEncryptedCollection(db, collectionName, { createCollectionOptions: {} }) .catch(error => error); expect(error).to.be.instanceOf(TypeError, /Cannot read properties/); }); }); context('when options.encryptedFields.fields is not an array', () => { it('does not generate any encryption keys', async () => { const createCollectionSpy = sinon.spy(db, 'createCollection'); const createDataKeySpy = sinon.spy(clientEncryption, 'createDataKey'); await clientEncryption.createEncryptedCollection(db, collectionName, { createCollectionOptions: { encryptedFields: { fields: 'not an array' } } }); expect(createDataKeySpy.callCount).to.equal(0); const options = createCollectionSpy.getCall(0).args[1]; expect(options).to.deep.equal({ encryptedFields: { fields: 'not an array' } }); }); }); context('when options.encryptedFields.fields elements are not objects', () => { it('they are passed along to createCollection', async () => { const createCollectionSpy = sinon.spy(db, 'createCollection'); const keyId = new Binary(Buffer.alloc(16, 0)); const createDataKeyStub = sinon.stub(clientEncryption, 'createDataKey').resolves(keyId); await clientEncryption.createEncryptedCollection(db, collectionName, { createCollectionOptions: { encryptedFields: { fields: ['not an array', { keyId: null }, { keyId: {} }] } } }); expect(createDataKeyStub.callCount).to.equal(1); const options = createCollectionSpy.getCall(0).args[1]; expect(options).to.deep.equal({ encryptedFields: { fields: ['not an array', { keyId: keyId }, { keyId: {} }] } }); }); }); it('only passes options.masterKey to createDataKey', async () => { const masterKey = Symbol('key'); const createDataKey = sinon .stub(clientEncryption, 'createDataKey') .resolves(new Binary(Buffer.alloc(16, 0))); const result = await clientEncryption.createEncryptedCollection(db, collectionName, { provider: 'aws', createCollectionOptions: { encryptedFields: { fields: [{}] } }, masterKey }); expect(result).to.have.property('collection'); expect(createDataKey).to.have.been.calledOnceWithExactly('aws', { masterKey }); }); context('when createDataKey rejects', () => { const customErrorEvil = new Error('evil!'); const customErrorGood = new Error('good!'); const keyId = new Binary(Buffer.alloc(16, 0), 4); const createCollectionOptions = { encryptedFields: { fields: [{}, {}, { keyId: 'cool id!' }, {}] } }; const createDataKeyRejection = async () => { const stub = sinon.stub(clientEncryption, 'createDataKey'); stub.onCall(0).resolves(keyId); stub.onCall(1).rejects(customErrorEvil); stub.onCall(2).rejects(customErrorGood); stub.onCall(4).resolves(keyId); const error = await clientEncryption .createEncryptedCollection(db, collectionName, { provider: 'local', createCollectionOptions }) .catch(error => error); // At least make sure the function did not succeed expect(error).to.be.instanceOf(Error); return error; }; it('throws MongoCryptCreateDataKeyError', async () => { const error = await createDataKeyRejection(); expect(error).to.be.instanceOf(MongoCryptCreateDataKeyError); }); it('thrown error has a cause set to the first error that was thrown from createDataKey', async () => { const error = await createDataKeyRejection(); expect(error.cause).to.equal(customErrorEvil); expect(error.message).to.include(customErrorEvil.message); }); it('thrown error contains partially filled encryptedFields.fields', async () => { const error = await createDataKeyRejection(); expect(error.encryptedFields).property('fields').that.is.an('array'); expect(error.encryptedFields.fields).to.have.lengthOf( createCollectionOptions.encryptedFields.fields.length ); expect(error.encryptedFields.fields).to.have.nested.property('[0].keyId', keyId); expect(error.encryptedFields.fields).to.not.have.nested.property('[1].keyId'); expect(error.encryptedFields.fields).to.have.nested.property('[2].keyId', 'cool id!'); }); }); context('when createCollection rejects', () => { const customError = new Error('evil!'); const keyId = new Binary(Buffer.alloc(16, 0), 4); const createCollectionRejection = async () => { const stubCreateDataKey = sinon.stub(clientEncryption, 'createDataKey'); stubCreateDataKey.onCall(0).resolves(keyId); stubCreateDataKey.onCall(1).resolves(keyId); stubCreateDataKey.onCall(2).resolves(keyId); sinon.stub(db, 'createCollection').rejects(customError); const createCollectionOptions = { encryptedFields: { fields: [{}, {}, { keyId: 'cool id!' }] } }; const error = await clientEncryption .createEncryptedCollection(db, collectionName, { provider: 'local', createCollectionOptions }) .catch(error => error); // At least make sure the function did not succeed expect(error).to.be.instanceOf(Error); return error; }; it('throws MongoCryptCreateEncryptedCollectionError', async () => { const error = await createCollectionRejection(); expect(error).to.be.instanceOf(MongoCryptCreateEncryptedCollectionError); }); it('thrown error has a cause set to the error that was thrown from createCollection', async () => { const error = await createCollectionRejection(); expect(error.cause).to.equal(customError); expect(error.message).to.include(customError.message); }); it('thrown error contains filled encryptedFields.fields', async () => { const error = await createCollectionRejection(); expect(error.encryptedFields).property('fields').that.is.an('array'); expect(error.encryptedFields.fields).to.have.nested.property('[0].keyId', keyId); expect(error.encryptedFields.fields).to.have.nested.property('[1].keyId', keyId); expect(error.encryptedFields.fields).to.have.nested.property('[2].keyId', 'cool id!'); }); }); context('when there are nullish keyIds in the encryptedFields.fields array', function () { it('does not mutate the input fields array when generating data keys', async () => { const encryptedFields = Object.freeze({ escCollection: 'esc', eccCollection: 'ecc', ecocCollection: 'ecoc', fields: Object.freeze([ Object.freeze({ keyId: false }), Object.freeze({ keyId: null, path: 'name', bsonType: 'int', queries: Object.freeze({ contentionFactor: 0 }) }), null ]) }); const keyId = new Binary(Buffer.alloc(16, 0), 4); sinon.stub(clientEncryption, 'createDataKey').resolves(keyId); const { collection, encryptedFields: resultEncryptedFields } = await clientEncryption.createEncryptedCollection(db, collectionName, { provider: 'local', createCollectionOptions: { encryptedFields } }); expect(collection).to.have.property('namespace', 'createEncryptedCollectionDb.secure'); expect(encryptedFields, 'original encryptedFields should be unmodified').nested.property( 'fields[0].keyId', false ); expect( resultEncryptedFields, 'encryptedFields created by helper should have replaced nullish keyId' ).nested.property('fields[1].keyId', keyId); expect(encryptedFields, 'original encryptedFields should be unmodified').nested.property( 'fields[2]', null ); }); it('generates dataKeys for all null keyIds in the fields array', async () => { const encryptedFields = Object.freeze({ escCollection: 'esc', eccCollection: 'ecc', ecocCollection: 'ecoc', fields: Object.freeze([ Object.freeze({ keyId: null }), Object.freeze({ keyId: null }), Object.freeze({ keyId: null }) ]) }); const keyId = new Binary(Buffer.alloc(16, 0), 4); sinon.stub(clientEncryption, 'createDataKey').resolves(keyId); const { collection, encryptedFields: resultEncryptedFields } = await clientEncryption.createEncryptedCollection(db, collectionName, { provider: 'local', createCollectionOptions: { encryptedFields } }); expect(collection).to.have.property('namespace', 'createEncryptedCollectionDb.secure'); expect(resultEncryptedFields.fields).to.have.lengthOf(3); expect(resultEncryptedFields.fields.filter(({ keyId }) => keyId === null)).to.have.lengthOf( 0 ); }); }); }); }); libmongocrypt-1.8.4/bindings/node/test/common.test.js000066400000000000000000000066171454530651600227440ustar00rootroot00000000000000'use strict'; const { expect } = require('chai'); const maybeCallback = require('../lib/common').maybeCallback; describe('maybeCallback()', () => { it('should accept two arguments', () => { expect(maybeCallback).to.have.lengthOf(2); }); describe('when handling an error case', () => { it('should pass the error to the callback provided', done => { const superPromiseRejection = Promise.reject(new Error('fail')); const result = maybeCallback( () => superPromiseRejection, (error, result) => { try { expect(result).to.not.exist; expect(error).to.be.instanceOf(Error); return done(); } catch (assertionError) { return done(assertionError); } } ); expect(result).to.be.undefined; }); it('should return the rejected promise to the caller when no callback is provided', async () => { const superPromiseRejection = Promise.reject(new Error('fail')); const returnedPromise = maybeCallback(() => superPromiseRejection, undefined); expect(returnedPromise).to.equal(superPromiseRejection); // @ts-expect-error: There is no overload to change the return type not be nullish, // and we do not want to add one in fear of making it too easy to neglect adding the callback argument const thrownError = await returnedPromise.catch(error => error); expect(thrownError).to.be.instanceOf(Error); }); it('should not modify a rejection error promise', async () => { class MyError extends Error {} const driverError = Object.freeze(new MyError()); const rejection = Promise.reject(driverError); // @ts-expect-error: There is no overload to change the return type not be nullish, // and we do not want to add one in fear of making it too easy to neglect adding the callback argument const thrownError = await maybeCallback(() => rejection, undefined).catch(error => error); expect(thrownError).to.be.equal(driverError); }); it('should not modify a rejection error when passed to callback', done => { class MyError extends Error {} const driverError = Object.freeze(new MyError()); const rejection = Promise.reject(driverError); maybeCallback( () => rejection, error => { try { expect(error).to.exist; expect(error).to.equal(driverError); done(); } catch (assertionError) { done(assertionError); } } ); }); }); describe('when handling a success case', () => { it('should pass the result and undefined error to the callback provided', done => { const superPromiseSuccess = Promise.resolve(2); const result = maybeCallback( () => superPromiseSuccess, (error, result) => { try { expect(error).to.be.undefined; expect(result).to.equal(2); done(); } catch (assertionError) { done(assertionError); } } ); expect(result).to.be.undefined; }); it('should return the resolved promise to the caller when no callback is provided', async () => { const superPromiseSuccess = Promise.resolve(2); const result = maybeCallback(() => superPromiseSuccess); expect(result).to.equal(superPromiseSuccess); expect(await result).to.equal(2); }); }); }); libmongocrypt-1.8.4/bindings/node/test/cryptoCallbacks.test.js000066400000000000000000000216721454530651600245720ustar00rootroot00000000000000'use strict'; const sinon = require('sinon'); const { expect } = require('chai'); const mongodb = require('mongodb'); const MongoClient = mongodb.MongoClient; const stateMachine = require('../lib/stateMachine')({ mongodb }); const cryptoCallbacks = require('../lib/cryptoCallbacks'); const ClientEncryption = require('../lib/clientEncryption')({ mongodb, stateMachine }).ClientEncryption; const requirements = require('./requirements.helper'); // Data Key Stuff const kmsProviders = Object.assign({}, requirements.awsKmsProviders); const dataKeyOptions = Object.assign({}, requirements.awsDataKeyOptions); describe('cryptoCallbacks', function () { before(function () { if (requirements.SKIP_AWS_TESTS) { console.error('Skipping crypto callback tests'); return; } this.sinon = sinon.createSandbox(); }); beforeEach(function () { if (requirements.SKIP_AWS_TESTS) { this.currentTest.skipReason = `requirements.SKIP_AWS_TESTS=${requirements.SKIP_AWS_TESTS}`; this.test.skip(); return; } this.sinon.restore(); this.client = new MongoClient('mongodb://localhost:27017/', { useUnifiedTopology: true, useNewUrlParser: true }); return this.client.connect(); }); afterEach(function () { if (requirements.SKIP_AWS_TESTS) { return; } this.sinon.restore(); let p = Promise.resolve(); if (this.client) { p = p.then(() => this.client.close()).then(() => (this.client = undefined)); } return p; }); after(function () { this.sinon = undefined; }); // TODO(NODE-3370): fix key formatting error "asn1_check_tlen:wrong tag" it.skip('should support support crypto callback for signing RSA-SHA256', function () { const input = Buffer.from('data to sign'); const pemFileData = '-----BEGIN PRIVATE KEY-----\n' + 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJxCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xYuXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CMprqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrShXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqImRYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlxdc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4umxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAxbLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4VnrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a\n' + '-----END PRIVATE KEY-----'; const key = Buffer.from(pemFileData); const output = Buffer.alloc(256); const expectedOutput = Buffer.from( 'VocBRhpMmQ2XCzVehWSqheQLnU889gf3dhU4AnVnQTJjsKx/CM23qKDPkZDd2A/BnQsp99SN7ksIX5Raj0TPwyN5OCN/YrNFNGoOFlTsGhgP/hyE8X3Duiq6sNO0SMvRYNPFFGlJFsp1Fw3Z94eYMg4/Wpw5s4+Jo5Zm/qY7aTJIqDKDQ3CNHLeJgcMUOc9sz01/GzoUYKDVODHSxrYEk5ireFJFz9vP8P7Ha+VDUZuQIQdXer9NBbGFtYmWprY3nn4D3Dw93Sn0V0dIqYeIo91oKyslvMebmUM95S2PyIJdEpPb2DJDxjvX/0LLwSWlSXRWy9gapWoBkb4ynqZBsg==', 'base64' ); const { signRsaSha256Hook } = cryptoCallbacks; const err = signRsaSha256Hook(key, input, output); if (err instanceof Error) { expect(err).to.not.exist; } expect(output).to.deep.equal(expectedOutput); }).skipReason = 'TODO(NODE-3370): fix key formatting error "asn1_check_tlen:wrong tag"'; const hookNames = new Set([ 'aes256CbcEncryptHook', 'aes256CbcDecryptHook', 'randomHook', 'hmacSha512Hook', 'hmacSha256Hook', 'sha256Hook' ]); it('should invoke crypto callbacks when doing encryption', function (done) { for (const name of hookNames) { this.sinon.spy(cryptoCallbacks, name); } function assertCertainHooksCalled(expectedSet) { expectedSet = expectedSet || new Set([]); for (const name of hookNames) { const hook = cryptoCallbacks[name]; if (expectedSet.has(name)) { expect(hook).to.have.been.called; } else { expect(hook).to.not.have.been.called; } hook.resetHistory(); } } const encryption = new ClientEncryption(this.client, { keyVaultNamespace: 'test.encryption', kmsProviders }); try { assertCertainHooksCalled(); } catch (e) { return done(e); } encryption.createDataKey('aws', dataKeyOptions, (err, dataKey) => { try { expect(err).to.not.exist; assertCertainHooksCalled(new Set(['hmacSha256Hook', 'sha256Hook', 'randomHook'])); } catch (e) { return done(e); } const encryptOptions = { keyId: dataKey, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }; encryption.encrypt('hello', encryptOptions, (err, encryptedValue) => { try { expect(err).to.not.exist; assertCertainHooksCalled( new Set(['aes256CbcEncryptHook', 'hmacSha512Hook', 'hmacSha256Hook', 'sha256Hook']) ); } catch (e) { return done(e); } encryption.decrypt(encryptedValue, err => { try { expect(err).to.not.exist; assertCertainHooksCalled(new Set(['aes256CbcDecryptHook', 'hmacSha512Hook'])); } catch (e) { return done(e); } done(); }); }); }); }); describe('error testing', function () { ['aes256CbcEncryptHook', 'aes256CbcDecryptHook', 'hmacSha512Hook'].forEach(hookName => { it(`should properly propagate an error when ${hookName} fails`, function (done) { const error = new Error('some random error text'); this.sinon.stub(cryptoCallbacks, hookName).returns(error); const encryption = new ClientEncryption(this.client, { keyVaultNamespace: 'test.encryption', kmsProviders }); function finish(err) { try { expect(err, 'Expected an error to exist').to.exist; expect(err).to.have.property('message', error.message); done(); } catch (e) { done(e); } } try { encryption.createDataKey('aws', dataKeyOptions, (err, dataKey) => { if (err) return finish(err); const encryptOptions = { keyId: dataKey, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }; encryption.encrypt('hello', encryptOptions, (err, encryptedValue) => { if (err) return finish(err); encryption.decrypt(encryptedValue, err => finish(err)); }); }); } catch (e) { done(new Error('We should not be here')); } }); }); // These ones will fail with an error, but that error will get overridden // with "failed to create KMS message" in mongocrypt-kms-ctx.c ['hmacSha256Hook', 'sha256Hook'].forEach(hookName => { it(`should error with a specific kms error when ${hookName} fails`, function () { const error = new Error('some random error text'); this.sinon.stub(cryptoCallbacks, hookName).returns(error); const encryption = new ClientEncryption(this.client, { keyVaultNamespace: 'test.encryption', kmsProviders }); expect(() => encryption.createDataKey('aws', dataKeyOptions, () => undefined)).to.throw( 'failed to create KMS message' ); }); }); it('should error synchronously with error when randomHook fails', function (done) { const error = new Error('some random error text'); this.sinon.stub(cryptoCallbacks, 'randomHook').returns(error); const encryption = new ClientEncryption(this.client, { keyVaultNamespace: 'test.encryption', kmsProviders }); try { encryption.createDataKey('aws', dataKeyOptions, () => { done(new Error('We should not be here')); }); } catch (err) { try { expect(err).to.have.property('message', 'some random error text'); done(); } catch (e) { done(e); } } }); }); }); libmongocrypt-1.8.4/bindings/node/test/data/000077500000000000000000000000001454530651600210375ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/test/data/README.md000066400000000000000000000005401454530651600223150ustar00rootroot00000000000000# libmongocrypt example data # This directory contains a simple example of mocked responses to test libmongocrypt and driver wrappers. Data for other scenarios and edge cases is in the `data` directory. The HTTP reply file, kms-decrypt-reply.txt, has regular newline endings \n that MUST be replaced by \r\n endings when reading the file for testing.libmongocrypt-1.8.4/bindings/node/test/data/cmd.json000066400000000000000000000001131454530651600224700ustar00rootroot00000000000000{ "find": "test", "filter": { "ssn": "457-55-5462" } } libmongocrypt-1.8.4/bindings/node/test/data/collection-info.json000066400000000000000000000017321454530651600250210ustar00rootroot00000000000000{ "type": "collection", "name": "test", "idIndex": { "ns": "test.test", "name": "_id_", "key": { "_id": { "$numberInt": "1" } }, "v": { "$numberInt": "2" } }, "options": { "validator": { "$jsonSchema": { "properties": { "ssn": { "encrypt": { "keyId": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "type": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } } libmongocrypt-1.8.4/bindings/node/test/data/encrypted-document-nested.json000066400000000000000000000003371454530651600270260ustar00rootroot00000000000000{ "nested": { "$binary": { "base64": "AmFhYWFhYWFhYWFhYWFhYWEDW89+etsVGIufAfsiEwR62ce6+lry79sJJBUyJ6hH89wBkhpRkzFLz26Nu6jXQRe8ESYAF5cAa5wg9rsq95IBHuaIaLEQLW2jLjGo1fp69jg=", "subType": "06" } } } libmongocrypt-1.8.4/bindings/node/test/data/encrypted-document.json000066400000000000000000000004261454530651600255450ustar00rootroot00000000000000{ "filter": { "find": "test", "ssn": { "$binary": { "base64": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", "subType": "06" } } } } libmongocrypt-1.8.4/bindings/node/test/data/encryptedFields.json000066400000000000000000000010551454530651600250570ustar00rootroot00000000000000{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } libmongocrypt-1.8.4/bindings/node/test/data/key-document.json000066400000000000000000000017571454530651600243500ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "masterKey": { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "provider": "aws" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } } } libmongocrypt-1.8.4/bindings/node/test/data/key1-document.json000066400000000000000000000013741454530651600244240ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "sHe0kz57YW7v8g9VP9sf/+K1ex4JqKc5rf/URX3n3p8XdZ6+15uXPaSayC6adWbNxkFskuMCOifDoTT+rkqMtFkDclOy884RuGGtUysq3X7zkAWYTKi8QAfKkajvVbZl2y23UqgVasdQu3OVBQCrH/xY00nNAs/52e958nVjBuzQkSb1T8pKJAyjZsHJ60+FtnfafDZSTAIBJYn7UWBCwQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648914851981" } }, "updateDate": { "$date": { "$numberLong": "1648914851981" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } libmongocrypt-1.8.4/bindings/node/test/data/kms-decrypt-reply.txt000066400000000000000000000005561454530651600252010ustar00rootroot00000000000000HTTP/1.1 200 OK x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e Content-Type: application/x-amz-json-1.1 Content-Length: 233 {"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "Plaintext": "TqhXy3tKckECjy4/ZNykMWG8amBF46isVPzeOgeusKrwheBmYaU8TMG5AHR/NeUDKukqo8hBGgogiQOVpLPkqBQHD8YkLsNbDmHoGOill5QAHnniF/Lz405bGucB5TfR"}libmongocrypt-1.8.4/bindings/node/test/data/kms-encrypt-reply.txt000066400000000000000000000011251454530651600252040ustar00rootroot00000000000000HTTP/1.1 200 OK x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e Content-Type: application/x-amz-json-1.1 Content-Length: 446 Connection: close {"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "CiphertextBlob": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gHCPOT4UQIpMTvAVABLqnXlAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLxAm0nO3rccdoWA6AIBEIB7HUe6+aPvgNu/4sLEXBQVDIJVBueI3q7zdOMBSkRKkgZWqEuQgA6iDuEZbhHhOVCUXPBaLX6QWRwyMmjvIy/2Bg5q+TmwnfRo6QKdw2vee1W32/FdPWIoQy1yKOoIhNy6XMWldS3JuWK8ffQOYkssEqx0V4LW6PKuFv7D"}libmongocrypt-1.8.4/bindings/node/test/data/mongocryptd-reply.json000066400000000000000000000006551454530651600254360ustar00rootroot00000000000000{ "schemaRequiresEncryption": true, "ok": { "$numberInt": "1" }, "result": { "filter": { "ssn": { "$binary": { "base64": "ADgAAAAQYQABAAAABWtpABAAAAAEYWFhYWFhYWFhYWFhYWFhYQJ2AAwAAAA0NTctNTUtNTQ2MgAA", "subType": "06" } } }, "find": "test" }, "hasEncryptedPlaceholders": true } libmongocrypt-1.8.4/bindings/node/test/index.test.js000066400000000000000000000034471454530651600225610ustar00rootroot00000000000000'use strict'; const { expect } = require('chai'); const mongodbClientEncryption = require('../lib/index'); const { fetchAzureKMSToken } = require('../lib/providers'); // Update this as you add exports, helps double check we don't accidentally remove something // since not all tests import from the root public export const EXPECTED_EXPORTS = [ 'extension', 'MongoCryptError', 'MongoCryptCreateEncryptedCollectionError', 'MongoCryptCreateDataKeyError', 'MongoCryptAzureKMSRequestError', 'MongoCryptKMSRequestNetworkTimeoutError', 'AutoEncrypter', 'ClientEncryption' ]; describe('mongodb-client-encryption entrypoint', () => { it('should export all and only the expected keys in expected_exports', () => { expect(mongodbClientEncryption).to.have.all.keys(EXPECTED_EXPORTS); }); it('extension returns an object equal in shape to the default except for extension', () => { const extensionResult = mongodbClientEncryption.extension(require('mongodb')); const expectedExports = EXPECTED_EXPORTS.filter(exp => exp !== 'extension'); const exportsDefault = Object.keys(mongodbClientEncryption).filter(exp => exp !== 'extension'); expect(extensionResult).to.have.all.keys(expectedExports); expect(extensionResult).to.have.all.keys(exportsDefault); }); context('exports for driver testing', () => { it('exports `fetchAzureKMSToken` in a symbol property', () => { expect(mongodbClientEncryption).to.have.property( '___azureKMSProseTestExports', fetchAzureKMSToken ); }); it('extension exports `fetchAzureKMSToken` in a symbol property', () => { const extensionResult = mongodbClientEncryption.extension(require('mongodb')); expect(extensionResult).to.have.property('___azureKMSProseTestExports', fetchAzureKMSToken); }); }); }); libmongocrypt-1.8.4/bindings/node/test/mongocryptdManager.test.js000066400000000000000000000033121454530651600253010ustar00rootroot00000000000000'use strict'; const MongocryptdManager = require('../lib/mongocryptdManager').MongocryptdManager; const { expect } = require('chai'); describe('MongocryptdManager', function () { it('should default to having spawnArgs of --idleShutdownTimeoutSecs=60', function () { const mcdm = new MongocryptdManager(); expect(mcdm.spawnArgs).to.deep.equal(['--idleShutdownTimeoutSecs', 60]); }); it('should concat --idleShutdownTimeoutSecs=60 to provided args', function () { const mcdm = new MongocryptdManager({ mongocryptdSpawnArgs: ['foo', 12] }); expect(mcdm.spawnArgs).to.deep.equal(['foo', 12, '--idleShutdownTimeoutSecs', 60]); }); it('should not override `idleShutdownTimeoutSecs` if the user sets it using `key value` form', function () { const mcdm = new MongocryptdManager({ mongocryptdSpawnArgs: ['--idleShutdownTimeoutSecs', 12] }); expect(mcdm.spawnArgs).to.deep.equal(['--idleShutdownTimeoutSecs', 12]); }); it('should not override `idleShutdownTimeoutSecs` if the user sets it using `key=value` form', function () { const mcdm = new MongocryptdManager({ mongocryptdSpawnArgs: ['--idleShutdownTimeoutSecs=12'] }); expect(mcdm.spawnArgs).to.deep.equal(['--idleShutdownTimeoutSecs=12']); }); it('should support construction with options', function () { const mcdm = new MongocryptdManager({ mongocryptdURI: 'some-uri', mongocryptdBypassSpawn: true, mongocryptdSpawnPath: 'some-spawn-path', mongocryptdSpawnArgs: ['--idleShutdownTimeoutSecs=12'] }); expect(mcdm).to.eql({ uri: 'some-uri', bypassSpawn: true, spawnPath: 'some-spawn-path', spawnArgs: ['--idleShutdownTimeoutSecs=12'] }); }); }); libmongocrypt-1.8.4/bindings/node/test/providers/000077500000000000000000000000001454530651600221435ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/test/providers/credentialsProvider.test.js000066400000000000000000000456051454530651600275010ustar00rootroot00000000000000'use strict'; const { expect } = require('chai'); const http = require('http'); const requirements = require('../requirements.helper'); const { loadCredentials, isEmptyCredentials } = require('../../lib/providers'); const { tokenCache, fetchAzureKMSToken } = require('../../lib/providers/azure'); const sinon = require('sinon'); const utils = require('../../lib/providers/utils'); const { MongoCryptKMSRequestNetworkTimeoutError, MongoCryptAzureKMSRequestError } = require('../../lib/errors'); const originalAccessKeyId = process.env.AWS_ACCESS_KEY_ID; const originalSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; const originalSessionToken = process.env.AWS_SESSION_TOKEN; describe('#loadCredentials', function () { context('isEmptyCredentials()', () => { it('returns true for an empty object', () => { expect(isEmptyCredentials('rainyCloud', { rainyCloud: {} })).to.be.true; }); it('returns false for an object with keys', () => { expect(isEmptyCredentials('rainyCloud', { rainyCloud: { password: 'secret' } })).to.be.false; }); it('returns false for an nullish credentials', () => { expect(isEmptyCredentials('rainyCloud', { rainyCloud: null })).to.be.false; expect(isEmptyCredentials('rainyCloud', { rainyCloud: undefined })).to.be.false; expect(isEmptyCredentials('rainyCloud', {})).to.be.false; }); it('returns false for non object credentials', () => { expect(isEmptyCredentials('rainyCloud', { rainyCloud: 0 })).to.be.false; expect(isEmptyCredentials('rainyCloud', { rainyCloud: false })).to.be.false; expect(isEmptyCredentials('rainyCloud', { rainyCloud: Symbol('secret') })).to.be.false; }); }); context('when using aws', () => { const accessKey = 'example'; const secretKey = 'example'; const sessionToken = 'example'; after(function () { // After the entire suite runs, set the env back for the rest of the test run. process.env.AWS_ACCESS_KEY_ID = originalAccessKeyId; process.env.AWS_SECRET_ACCESS_KEY = originalSecretAccessKey; process.env.AWS_SESSION_TOKEN = originalSessionToken; }); context('when the credential provider finds credentials', function () { before(function () { process.env.AWS_ACCESS_KEY_ID = accessKey; process.env.AWS_SECRET_ACCESS_KEY = secretKey; process.env.AWS_SESSION_TOKEN = sessionToken; }); context('when the credentials are empty', function () { const kmsProviders = { aws: {} }; before(function () { if (!requirements.credentialProvidersInstalled.aws) { this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; this.currentTest.skip(); return; } }); it('refreshes the aws credentials', async function () { const providers = await loadCredentials(kmsProviders); expect(providers).to.deep.equal({ aws: { accessKeyId: accessKey, secretAccessKey: secretKey, sessionToken: sessionToken } }); }); }); context('when the credentials are not empty', function () { context('when aws is empty', function () { const kmsProviders = { local: { key: Buffer.alloc(96) }, aws: {} }; before(function () { if (!requirements.credentialProvidersInstalled.aws) { this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; this.currentTest.skip(); return; } }); it('refreshes only the aws credentials', async function () { const providers = await loadCredentials(kmsProviders); expect(providers).to.deep.equal({ local: { key: Buffer.alloc(96) }, aws: { accessKeyId: accessKey, secretAccessKey: secretKey, sessionToken: sessionToken } }); }); }); context('when aws is not empty', function () { const kmsProviders = { local: { key: Buffer.alloc(96) }, aws: { accessKeyId: 'example' } }; before(function () { if (!requirements.credentialProvidersInstalled.aws) { this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; this.currentTest.skip(); return; } }); it('does not refresh credentials', async function () { const providers = await loadCredentials(kmsProviders); expect(providers).to.deep.equal(kmsProviders); }); }); }); }); context('when the sdk is not installed', function () { const kmsProviders = { local: { key: Buffer.alloc(96) }, aws: {} }; before(function () { if (requirements.credentialProvidersInstalled.aws) { this.currentTest.skipReason = 'Credentials will be loaded when sdk present'; this.currentTest.skip(); return; } }); it('does not refresh credentials', async function () { const providers = await loadCredentials(kmsProviders); expect(providers).to.deep.equal(kmsProviders); }); }); }); context('when using gcp', () => { const setupHttpServer = status => { let httpServer; before(() => { httpServer = http .createServer((_, res) => { if (status === 200) { res.writeHead(200, { 'Content-Type': 'application/json' }); res.writeHead(200, { 'Metadata-Flavor': 'Google' }); res.end(JSON.stringify({ access_token: 'abc' })); } else { res.writeHead(401, { 'Content-Type': 'application/json' }); res.writeHead(401, { 'Metadata-Flavor': 'Google' }); res.end('{}'); } }) .listen(5001); process.env.GCE_METADATA_HOST = 'http://127.0.0.1:5001'; }); after(() => { httpServer.close(); delete process.env.GCE_METADATA_HOST; }); }; context('and gcp-metadata is installed', () => { beforeEach(function () { if (!requirements.credentialProvidersInstalled.gcp) { this.currentTest.skipReason = 'Tests require gcp-metadata to be installed'; this.currentTest.skip(); return; } }); context('when metadata http response is 200 ok', () => { setupHttpServer(200); context('when the credentials are empty', function () { const kmsProviders = { gcp: {} }; it('refreshes the gcp credentials', async function () { const providers = await loadCredentials(kmsProviders); expect(providers).to.deep.equal({ gcp: { accessToken: 'abc' } }); }); }); }); context('when metadata http response is 401 bad', () => { setupHttpServer(401); context('when the credentials are empty', function () { const kmsProviders = { gcp: {} }; it('surfaces error from server', async function () { const error = await loadCredentials(kmsProviders).catch(error => error); expect(error).to.be.instanceOf(Error); }); }); }); }); context('and gcp-metadata is not installed', () => { beforeEach(function () { if (requirements.credentialProvidersInstalled.gcp) { this.currentTest.skipReason = 'Tests require gcp-metadata to be installed'; this.currentTest.skip(); return; } }); context('when the credentials are empty', function () { const kmsProviders = { gcp: {} }; it('does not modify the gcp credentials', async function () { const providers = await loadCredentials(kmsProviders); expect(providers).to.deep.equal({ gcp: {} }); }); }); }); }); context('when using azure', () => { afterEach(() => tokenCache.resetCache()); afterEach(() => sinon.restore()); context('credential caching', () => { const cache = tokenCache; beforeEach(() => { cache.resetCache(); }); context('when there is no cached token', () => { let mockToken = { accessToken: 'mock token', expiresOnTimestamp: Date.now() }; let token; beforeEach(async () => { sinon.stub(cache, '_getToken').returns(mockToken); token = await cache.getToken(); }); it('fetches a token', async () => { expect(token).to.have.property('accessToken', mockToken.accessToken); }); it('caches the token on the class', async () => { expect(cache.cachedToken).to.equal(mockToken); }); }); context('when there is a cached token', () => { context('when the cached token expires <= 1 minute from the current time', () => { let mockToken = { accessToken: 'mock token', expiresOnTimestamp: Date.now() }; let token; beforeEach(async () => { cache.cachedToken = { accessToken: 'a new key', expiresOnTimestamp: Date.now() + 3000 }; sinon.stub(cache, '_getToken').returns(mockToken); token = await cache.getToken(); }); it('fetches a token', () => { expect(token).to.have.property('accessToken', mockToken.accessToken); }); it('caches the token on the class', () => { expect(cache.cachedToken).to.equal(mockToken); }); }); context('when the cached token expires > 1 minute from the current time', () => { let expiredToken = { token: 'mock token', expiresOnTimestamp: Date.now() }; let expectedMockToken = { accessToken: 'a new key', expiresOnTimestamp: Date.now() + 10000 }; let token; beforeEach(async () => { cache.cachedToken = expiredToken; sinon.stub(cache, '_getToken').returns(expectedMockToken); token = await cache.getToken(); }); it('returns the cached token', () => { expect(token).to.have.property('accessToken', expectedMockToken.accessToken); }); }); }); }); context('request configuration', () => { const mockResponse = { status: 200, body: '{ "access_token": "token", "expires_in": "10000" }' }; let httpSpy; beforeEach(async () => { httpSpy = sinon.stub(utils, 'get'); httpSpy.resolves(mockResponse); await loadCredentials({ azure: {} }); }); it('sets the `api-version` param to 2012-02-01', () => { const url = httpSpy.args[0][0]; expect(url).to.be.instanceof(URL); expect(url.searchParams.get('api-version'), '2018-02-01'); }); it('sets the `resource` param to `https://vault.azure.net`', () => { const url = httpSpy.args[0][0]; expect(url).to.be.instanceof(URL); expect(url.searchParams.get('resource'), 'https://vault.azure.net'); }); it('sends the request to `http://169.254.169.254/metadata/identity/oauth2/token`', () => { const url = httpSpy.args[0][0]; expect(url).to.be.instanceof(URL); expect(url.toString()).to.include('http://169.254.169.254/metadata/identity/oauth2/token'); }); it('sets the Metadata header to true', () => { const options = httpSpy.args[0][1]; expect(options).to.have.property('headers').to.have.property('Metadata', true); }); it('sets the Content-Type header to application/json', () => { const options = httpSpy.args[0][1]; expect(options) .to.have.property('headers') .to.have.property('Content-Type', 'application/json'); }); context('prose test specific requirements', () => { /** * the driver prose tests require the ability to set custom URL endpoints * for the IMDS call and set custom headers */ const url = new URL('http://customentpoint.com'); beforeEach(async () => { sinon.restore(); httpSpy = sinon.stub(utils, 'get'); httpSpy.resolves(mockResponse); await fetchAzureKMSToken({ url, headers: { customHeader1: 'value1', customHeader2: 'value2' } }); }); it('allows a custom URL to be specified', () => { const url = httpSpy.args[0][0]; expect(url).to.be.instanceof(URL); expect(url.toString()).to.include('http://customentpoint.com'); }); it('deep copies the provided url', () => { const spiedUrl = httpSpy.args[0][0]; expect(spiedUrl).to.be.instanceof(URL); expect(spiedUrl).to.not.equal(url); }); it('allows custom headers to be specified', () => { const options = httpSpy.args[0][1]; expect(options).to.have.property('headers').to.have.property('customHeader1', 'value1'); expect(options).to.have.property('headers').to.have.property('customHeader2', 'value2'); }); }); }); context('error handling', () => { afterEach(() => sinon.restore()); context('when the request times out', () => { before(() => { sinon.stub(utils, 'get').rejects(new MongoCryptKMSRequestNetworkTimeoutError()); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); }); }); context('when the request returns a non-200 error', () => { context('when the request has no body', () => { before(() => { sinon.stub(utils, 'get').resolves({ status: 400 }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); expect(error).to.match(/Malformed JSON body in GET request/); }); }); context('when the request has a non-json body', () => { before(() => { sinon.stub(utils, 'get').resolves({ status: 400, body: 'non-json body' }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); expect(error).to.match(/Malformed JSON body in GET request/); }); }); context('when the request has a json body', () => { beforeEach(() => { sinon .stub(utils, 'get') .resolves({ status: 400, body: '{ "error": "something went wrong" }' }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); }); it('attaches the body to the error', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.have.property('body').to.deep.equal({ error: 'something went wrong' }); }); }); }); context('when the request returns a 200 response', () => { context('when the request has no body', () => { before(() => { sinon.stub(utils, 'get').resolves({ status: 200 }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); expect(error).to.match(/Malformed JSON body in GET request/); }); }); context('when the request has a non-json body', () => { before(() => { sinon.stub(utils, 'get').resolves({ status: 200, body: 'non-json body' }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); expect(error).to.match(/Malformed JSON body in GET request/); }); }); context('when the body has no access_token', () => { beforeEach(() => { sinon.stub(utils, 'get').resolves({ status: 200, body: '{ "expires_in": "10000" }' }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); expect(error).to.match(/missing field `access_token/); }); }); context('when the body has no expires_in', () => { beforeEach(() => { sinon.stub(utils, 'get').resolves({ status: 200, body: '{ "access_token": "token" }' }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); expect(error).to.match(/missing field `expires_in/); }); }); context('when expires_in cannot be parsed into a number', () => { beforeEach(() => { sinon.stub(utils, 'get').resolves({ status: 200, body: '{ "access_token": "token", "expires_in": "foo" }' }); }); it('throws a MongoCryptKMSRequestError', async () => { const error = await loadCredentials({ azure: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); expect(error).to.match(/unable to parse int from `expires_in` field/); }); }); }); context('when a valid token was returned', () => { beforeEach(() => { sinon .stub(utils, 'get') .resolves({ status: 200, body: '{ "access_token": "token", "expires_in": "10000" }' }); }); it('returns the token in the `azure` field of the kms providers', async () => { const kmsProviders = await loadCredentials({ azure: {} }); expect(kmsProviders).to.have.property('azure').to.deep.equal({ accessToken: 'token' }); }); }); }); }); }); libmongocrypt-1.8.4/bindings/node/test/release.test.js000066400000000000000000000033701454530651600230650ustar00rootroot00000000000000'use strict'; const { expect } = require('chai'); const tar = require('tar'); const cp = require('child_process'); const fs = require('fs'); const pkg = require('../package.json'); const packFile = `mongodb-client-encryption-${pkg.version}.tgz`; const REQUIRED_FILES = [ 'package/binding.gyp', 'package/CHANGELOG.md', 'package/index.d.ts', 'package/lib/index.js', 'package/lib/autoEncrypter.js', 'package/lib/buffer_pool.js', 'package/lib/clientEncryption.js', 'package/lib/common.js', 'package/lib/providers/index.js', 'package/lib/providers/gcp.js', 'package/lib/providers/aws.js', 'package/lib/providers/azure.js', 'package/lib/providers/utils.js', 'package/lib/cryptoCallbacks.js', 'package/lib/errors.js', 'package/lib/mongocryptdManager.js', 'package/lib/stateMachine.js', 'package/LICENSE', 'package/package.json', 'package/README.md', 'package/src/mongocrypt.cc', 'package/src/mongocrypt.h' ]; describe(`Release ${packFile}`, function () { this.timeout(5000); let tarFileList; before(() => { expect(fs.existsSync(packFile)).to.equal(false); cp.execSync('npm pack', { stdio: 'ignore' }); tarFileList = []; tar.list({ file: packFile, sync: true, onentry(entry) { tarFileList.push(entry.path); } }); }); after(() => { fs.unlinkSync(packFile); }); for (const requiredFile of REQUIRED_FILES) { it(`should contain ${requiredFile}`, () => { expect(tarFileList).to.includes(requiredFile); }); } it('should not have extraneous files', () => { const unexpectedFileList = tarFileList.filter(f => !REQUIRED_FILES.some(r => r === f)); expect(unexpectedFileList).to.have.lengthOf(0, `Extra files: ${unexpectedFileList.join(', ')}`); }); }); libmongocrypt-1.8.4/bindings/node/test/requirements.helper.js000066400000000000000000000023461454530651600244720ustar00rootroot00000000000000'use strict'; // Data Key Stuff const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID; const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY; const AWS_REGION = process.env.AWS_REGION; const AWS_CMK_ID = process.env.AWS_CMK_ID; const awsKmsProviders = { aws: { accessKeyId: AWS_ACCESS_KEY_ID, secretAccessKey: AWS_SECRET_ACCESS_KEY } }; const awsDataKeyOptions = { masterKey: { key: AWS_CMK_ID, region: AWS_REGION } }; const SKIP_LIVE_TESTS = !!process.env.MONGODB_NODE_SKIP_LIVE_TESTS; const SKIP_AWS_TESTS = SKIP_LIVE_TESTS || !AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY || !AWS_REGION || !AWS_CMK_ID; function isAWSCredentialProviderInstalled() { try { require.resolve('@aws-sdk/credential-providers'); return true; } catch { return false; } } function isGCPCredentialProviderInstalled() { try { require.resolve('gcp-metadata'); return true; } catch { return false; } } module.exports = { SKIP_LIVE_TESTS, SKIP_AWS_TESTS, KEYS: { AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_CMK_ID }, awsKmsProviders, awsDataKeyOptions, credentialProvidersInstalled: { aws: isAWSCredentialProviderInstalled(), gcp: isGCPCredentialProviderInstalled() } }; libmongocrypt-1.8.4/bindings/node/test/stateMachine.test.js000066400000000000000000000254651454530651600240630ustar00rootroot00000000000000'use strict'; const { EventEmitter, once } = require('events'); const net = require('net'); const tls = require('tls'); const fs = require('fs'); const { expect } = require('chai'); const sinon = require('sinon'); const mongodb = require('mongodb'); const BSON = mongodb.BSON; const StateMachine = require('../lib/stateMachine')({ mongodb }).StateMachine; describe('StateMachine', function () { class MockRequest { constructor(message, bytesNeeded) { this._bytesNeeded = typeof bytesNeeded === 'number' ? bytesNeeded : 1024; this._message = message; this.endpoint = 'some.fake.host.com'; this._kmsProvider = 'aws'; } get message() { return this._message; } get bytesNeeded() { return this._bytesNeeded; } get kmsProvider() { return this._kmsProvider; } addResponse(buffer) { this._bytesNeeded -= buffer.length; } } describe('#markCommand', function () { let runCommandStub; let dbStub; let clientStub; beforeEach(function () { this.sinon = sinon.createSandbox(); runCommandStub = this.sinon.stub().resolves({}); dbStub = this.sinon.createStubInstance(mongodb.Db, { command: runCommandStub }); clientStub = this.sinon.createStubInstance(mongodb.MongoClient, { db: dbStub }); }); const command = { encryptedFields: {}, a: new BSON.Long('0'), b: new BSON.Int32(0) }; const options = { promoteLongs: false, promoteValues: false }; const serializedCommand = BSON.serialize(command); const stateMachine = new StateMachine({ bson: BSON }); const callback = () => {}; context('when executing the command', function () { it('does not promote values', function () { stateMachine.markCommand(clientStub, 'test.coll', serializedCommand, callback); expect(runCommandStub.calledWith(command, options)).to.be.true; }); }); }); describe('kmsRequest', function () { class MockSocket extends EventEmitter { constructor(callback) { super(); this.on('connect', callback); } write() {} destroy() {} end(callback) { Promise.resolve().then(callback); } } before(function () { this.sinon = sinon.createSandbox(); }); context('when handling standard kms requests', function () { beforeEach(function () { this.fakeSocket = undefined; this.sinon.stub(tls, 'connect').callsFake((options, callback) => { this.fakeSocket = new MockSocket(callback); return this.fakeSocket; }); }); it('should only resolve once bytesNeeded drops to zero', function (done) { const stateMachine = new StateMachine({ bson: BSON }); const request = new MockRequest(Buffer.from('foobar'), 500); let status = 'pending'; stateMachine .kmsRequest(request) .then( () => (status = 'resolved'), () => (status = 'rejected') ) .catch(() => {}); this.fakeSocket.emit('connect'); setTimeout(() => { expect(status).to.equal('pending'); expect(request.bytesNeeded).to.equal(500); expect(request.kmsProvider).to.equal('aws'); this.fakeSocket.emit('data', Buffer.alloc(300)); setTimeout(() => { expect(status).to.equal('pending'); expect(request.bytesNeeded).to.equal(200); this.fakeSocket.emit('data', Buffer.alloc(200)); setTimeout(() => { expect(status).to.equal('resolved'); expect(request.bytesNeeded).to.equal(0); done(); }); }); }); }); }); context('when tls options are provided', function () { context('when the options are insecure', function () { [ 'tlsInsecure', 'tlsAllowInvalidCertificates', 'tlsAllowInvalidHostnames', 'tlsDisableOCSPEndpointCheck', 'tlsDisableCertificateRevocationCheck' ].forEach(function (option) { context(`when the option is ${option}`, function () { const stateMachine = new StateMachine({ bson: BSON, tlsOptions: { aws: { [option]: true } } }); const request = new MockRequest(Buffer.from('foobar'), 500); it('rejects with the validation error', function (done) { stateMachine.kmsRequest(request).catch(err => { expect(err.message).to.equal(`Insecure TLS options prohibited for aws: ${option}`); done(); }); }); }); }); }); context('when the options are secure', function () { context('when providing tlsCertificateKeyFile', function () { const stateMachine = new StateMachine({ bson: BSON, tlsOptions: { aws: { tlsCertificateKeyFile: 'test.pem' } } }); const request = new MockRequest(Buffer.from('foobar'), -1); const buffer = Buffer.from('foobar'); let connectOptions; it('sets the cert and key options in the tls connect options', function (done) { this.sinon.stub(fs, 'readFileSync').callsFake(fileName => { expect(fileName).to.equal('test.pem'); return buffer; }); this.sinon.stub(tls, 'connect').callsFake((options, callback) => { connectOptions = options; this.fakeSocket = new MockSocket(callback); return this.fakeSocket; }); stateMachine.kmsRequest(request).then(function () { expect(connectOptions.cert).to.equal(buffer); expect(connectOptions.key).to.equal(buffer); done(); }); this.fakeSocket.emit('data', Buffer.alloc(0)); }); }); context('when providing tlsCAFile', function () { const stateMachine = new StateMachine({ bson: BSON, tlsOptions: { aws: { tlsCAFile: 'test.pem' } } }); const request = new MockRequest(Buffer.from('foobar'), -1); const buffer = Buffer.from('foobar'); let connectOptions; it('sets the ca options in the tls connect options', function (done) { this.sinon.stub(fs, 'readFileSync').callsFake(fileName => { expect(fileName).to.equal('test.pem'); return buffer; }); this.sinon.stub(tls, 'connect').callsFake((options, callback) => { connectOptions = options; this.fakeSocket = new MockSocket(callback); return this.fakeSocket; }); stateMachine.kmsRequest(request).then(function () { expect(connectOptions.ca).to.equal(buffer); done(); }); this.fakeSocket.emit('data', Buffer.alloc(0)); }); }); context('when providing tlsCertificateKeyFilePassword', function () { const stateMachine = new StateMachine({ bson: BSON, tlsOptions: { aws: { tlsCertificateKeyFilePassword: 'test' } } }); const request = new MockRequest(Buffer.from('foobar'), -1); let connectOptions; it('sets the passphrase option in the tls connect options', function (done) { this.sinon.stub(tls, 'connect').callsFake((options, callback) => { connectOptions = options; this.fakeSocket = new MockSocket(callback); return this.fakeSocket; }); stateMachine.kmsRequest(request).then(function () { expect(connectOptions.passphrase).to.equal('test'); done(); }); this.fakeSocket.emit('data', Buffer.alloc(0)); }); }); }); }); afterEach(function () { this.sinon.restore(); }); }); describe('Socks5 support', function () { let socks5srv; let hasTlsConnection; let withUsernamePassword; beforeEach(async () => { hasTlsConnection = false; socks5srv = net.createServer(async socket => { if (withUsernamePassword) { expect(await once(socket, 'data')).to.deep.equal([Buffer.from('05020002', 'hex')]); socket.write(Buffer.from('0502', 'hex')); expect(await once(socket, 'data')).to.deep.equal([ Buffer.concat([ Buffer.from('0103', 'hex'), Buffer.from('foo'), Buffer.from('03', 'hex'), Buffer.from('bar') ]) ]); socket.write(Buffer.from('0100', 'hex')); } else { expect(await once(socket, 'data')).to.deep.equal([Buffer.from('050100', 'hex')]); socket.write(Buffer.from('0500', 'hex')); } expect(await once(socket, 'data')).to.deep.equal([ Buffer.concat([ Buffer.from('0501000312', 'hex'), Buffer.from('some.fake.host.com'), Buffer.from('01bb', 'hex') ]) ]); socket.write(Buffer.from('0500007f0000010100', 'hex')); expect((await once(socket, 'data'))[0][1]).to.equal(3); // TLS handshake version byte hasTlsConnection = true; socket.end(); }); socks5srv.listen(0); await once(socks5srv, 'listening'); }); afterEach(() => { socks5srv.close(); }); it('should create HTTPS connections through a Socks5 proxy (no proxy auth)', async function () { const stateMachine = new StateMachine({ bson: BSON, proxyOptions: { proxyHost: 'localhost', proxyPort: socks5srv.address().port } }); const request = new MockRequest(Buffer.from('foobar'), 500); try { await stateMachine.kmsRequest(request); } catch (err) { expect(err.name).to.equal('MongoCryptError'); expect(err.originalError.code).to.equal('ECONNRESET'); expect(hasTlsConnection).to.equal(true); return; } expect.fail('missed exception'); }); it('should create HTTPS connections through a Socks5 proxy (username/password auth)', async function () { withUsernamePassword = true; const stateMachine = new StateMachine({ bson: BSON, proxyOptions: { proxyHost: 'localhost', proxyPort: socks5srv.address().port, proxyUsername: 'foo', proxyPassword: 'bar' } }); const request = new MockRequest(Buffer.from('foobar'), 500); try { await stateMachine.kmsRequest(request); } catch (err) { expect(err.name).to.equal('MongoCryptError'); expect(err.originalError.code).to.equal('ECONNRESET'); expect(hasTlsConnection).to.equal(true); return; } expect.fail('missed exception'); }); }); }); libmongocrypt-1.8.4/bindings/node/test/tools/000077500000000000000000000000001454530651600212665ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/test/tools/chai-addons.js000066400000000000000000000002461454530651600240000ustar00rootroot00000000000000'use strict'; // configure chai const chai = require('chai'); chai.use(require('sinon-chai')); chai.use(require('chai-subset')); chai.config.truncateThreshold = 0; libmongocrypt-1.8.4/bindings/node/test/tools/mongodb_reporter.js000066400000000000000000000217461454530651600252050ustar00rootroot00000000000000//@ts-check 'use strict'; const mocha = require('mocha'); const chalk = require('chalk'); chalk.level = 3; const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_SUITE_BEGIN, EVENT_SUITE_END, EVENT_TEST_PENDING, EVENT_TEST_BEGIN, EVENT_TEST_END } = mocha.Runner.constants; const fs = require('fs'); const os = require('os'); /** * @typedef {object} MongoMochaSuiteExtension * @property {Date} timestamp - suite start date * @property {string} stdout - capture of stdout * @property {string} stderr - capture of stderr * @property {MongoMochaTest} test - capture of stderr * @typedef {object} MongoMochaTestExtension * @property {Date} startTime - test start date * @property {Date} endTime - test end date * @property {number} elapsedTime - difference between end and start * @property {Error} [error] - The possible error from a test * @property {true} [skipped] - Set if test was skipped * @typedef {MongoMochaSuiteExtension & Mocha.Suite} MongoMochaSuite * @typedef {MongoMochaTestExtension & Mocha.Test} MongoMochaTest */ // Turn this on if you have to debug this custom reporter! let REPORT_TO_STDIO = false; function captureStream(stream) { var oldWrite = stream.write; var buf = ''; stream.write = function (chunk) { buf += chunk.toString(); // chunk is a String or Buffer oldWrite.apply(stream, arguments); }; return { unhook: function unhook() { stream.write = oldWrite; return buf; }, captured: function () { return buf; } }; } /** * @param {Mocha.Runner} runner * @this {any} */ class MongoDBMochaReporter extends mocha.reporters.Spec { constructor(runner) { super(runner); /** @type {Map} */ this.suites = new Map(); this.xunitWritten = false; runner.on(EVENT_RUN_BEGIN, () => this.start()); runner.on(EVENT_RUN_END, () => this.end()); runner.on(EVENT_SUITE_BEGIN, suite => this.onSuite(suite)); runner.on(EVENT_TEST_BEGIN, test => this.onTest(test)); runner.on(EVENT_TEST_PASS, test => this.pass(test)); runner.on(EVENT_TEST_FAIL, (test, error) => this.fail(test, error)); runner.on(EVENT_TEST_PENDING, test => this.pending(test)); runner.on(EVENT_SUITE_END, suite => this.suiteEnd(suite)); runner.on(EVENT_TEST_END, test => this.testEnd(test)); process.on('SIGINT', () => this.end(true)); } start() {} end(ctrlC) { try { if (ctrlC) console.log('emergency exit!'); const output = { testSuites: [] }; for (const [id, [className, { suite }]] of [...this.suites.entries()].entries()) { let totalSuiteTime = 0; let testCases = []; let failureCount = 0; const tests = /** @type {MongoMochaTest[]}*/ (suite.tests); for (const test of tests) { let time = test.elapsedTime / 1000; time = Number.isNaN(time) ? 0 : time; totalSuiteTime += time; failureCount += test.state === 'failed' ? 1 : 0; /** @type {string | Date | number} */ let startTime = test.startTime; startTime = startTime ? startTime.toISOString() : 0; /** @type {string | Date | number} */ let endTime = test.endTime; endTime = endTime ? endTime.toISOString() : 0; let error = test.error; let failure = error ? { type: error.constructor.name, message: error.message, stack: error.stack } : undefined; let skipped = !!test.skipped; testCases.push({ name: test.title, className, time, startTime, endTime, skipped, failure }); } /** @type {string | Date | number} */ let timestamp = suite.timestamp; timestamp = timestamp ? timestamp.toISOString().split('.')[0] : ''; output.testSuites.push({ package: suite.file.includes('integration') ? 'Integration' : 'Unit', id, name: className, timestamp, hostname: os.hostname(), tests: suite.tests.length, failures: failureCount, errors: '0', time: totalSuiteTime, testCases, stdout: suite.stdout, stderr: suite.stderr }); } if (!this.xunitWritten) { fs.writeFileSync('xunit.xml', outputToXML(output), { encoding: 'utf8' }); } this.xunitWritten = true; console.log(chalk.bold('wrote xunit.xml')); } catch (error) { console.error(chalk.red(`Failed to output xunit report! ${error}`)); } finally { if (ctrlC) process.exit(1); } } /** * @param {MongoMochaSuite} suite */ onSuite(suite) { if (suite.root) return; if (!this.suites.has(suite.fullTitle())) { suite.timestamp = new Date(); this.suites.set(suite.fullTitle(), { suite, stdout: captureStream(process.stdout), stderr: captureStream(process.stderr) }); } else { console.warn(`${chalk.yellow('WARNING:')} ${suite.fullTitle()} started twice`); } } /** * @param {MongoMochaSuite} suite */ suiteEnd(suite) { if (suite.root) return; const currentSuite = this.suites.get(suite.fullTitle()); if (!currentSuite) { console.error('Suite never started >:('); process.exit(1); } if (currentSuite.stdout || currentSuite.stderr) { suite.stdout = currentSuite.stdout.unhook(); suite.stderr = currentSuite.stderr.unhook(); delete currentSuite.stdout; delete currentSuite.stderr; } } /** * @param {MongoMochaTest} test */ onTest(test) { test.startTime = new Date(); } /** * @param {MongoMochaTest} test */ testEnd(test) { test.endTime = new Date(); test.elapsedTime = Number(test.endTime) - Number(test.startTime); } /** * @param {MongoMochaTest} test */ pass(test) { if (REPORT_TO_STDIO) console.log(chalk.green(`✔ ${test.fullTitle()}`)); } /** * @param {MongoMochaTest} test * @param {Error} error */ fail(test, error) { if (REPORT_TO_STDIO) console.log(chalk.red(`⨯ ${test.fullTitle()} -- ${error.message}`)); test.error = error; } /** * @param {MongoMochaTest & {skipReason?: string}} test */ pending(test) { if (REPORT_TO_STDIO) console.log(chalk.cyan(`↬ ${test.fullTitle()}`)); if (typeof test.skipReason === 'string') { console.log(chalk.cyan(`${' '.repeat(test.titlePath().length + 1)}↬ ${test.skipReason}`)); } test.skipped = true; } } module.exports = MongoDBMochaReporter; function replaceIllegalXMLCharacters(string) { // prettier-ignore return String(string) .split('"').join('"') .split('<').join('﹤') .split('>').join('﹥') .split('&').join('﹠'); } const ANSI_ESCAPE_REGEX = // eslint-disable-next-line no-control-regex /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; function outputToXML(output) { function cdata(str) { return `') .join('\\]\\]\\>')}]]>`; } function makeTag(name, attributes, selfClose, content) { const attributesString = Object.entries(attributes || {}) .map(([k, v]) => `${k}="${replaceIllegalXMLCharacters(v)}"`) .join(' '); let tag = `<${name}${attributesString ? ' ' + attributesString : ''}`; if (selfClose) return tag + '/>\n'; else tag += '>'; if (content) return tag + content + ``; return tag; } let s = '\n\n\n'; for (const suite of output.testSuites) { s += makeTag('testsuite', { package: suite.package, id: suite.id, name: suite.name, timestamp: suite.timestamp, hostname: suite.hostname, tests: suite.tests, failures: suite.failures, errors: suite.errors, time: suite.time }); s += '\n\t' + makeTag('properties') + '\n'; // can put metadata here? for (const test of suite.testCases) { s += '\t' + makeTag( 'testcase', { name: test.name, classname: test.className, time: test.time, start: test.startTime, end: test.endTime }, !test.failure && !test.skipped ); if (test.failure) { s += '\n\t\t' + makeTag('failure', { type: test.failure.type }, false, cdata(test.failure.stack)) + '\n'; s += `\t\n`; } if (test.skipped) { s += makeTag('skipped', {}, true); s += `\t\n`; } } s += '\t' + makeTag('system-out', {}, false, cdata(suite.stdout)) + '\n'; s += '\t' + makeTag('system-err', {}, false, cdata(suite.stderr)) + '\n'; s += `\n`; } return s + '\n'; } libmongocrypt-1.8.4/bindings/node/test/types/000077500000000000000000000000001454530651600212725ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/node/test/types/index.test-d.ts000066400000000000000000000053011454530651600241470ustar00rootroot00000000000000import { expectAssignable, expectError, expectType, expectNotType, expectNotAssignable } from 'tsd'; import { RangeOptions, AWSEncryptionKeyOptions, AzureEncryptionKeyOptions, ClientEncryption, GCPEncryptionKeyOptions, ClientEncryptionEncryptOptions, KMSProviders } from '../..'; type RequiredCreateEncryptedCollectionSettings = Parameters< ClientEncryption['createEncryptedCollection'] >[2]; expectError({}); expectError({ provider: 'blah!', createCollectionOptions: { encryptedFields: {} } }); expectError({ provider: 'aws', createCollectionOptions: {} }); expectError({ provider: 'aws', createCollectionOptions: { encryptedFields: null } }); expectAssignable({ provider: 'aws', createCollectionOptions: { encryptedFields: {} } }); expectAssignable({ provider: 'aws', createCollectionOptions: { encryptedFields: {} }, masterKey: { } as AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions }); { // NODE-5041 - incorrect spelling of rangeOpts in typescript definitions const options = {} as ClientEncryptionEncryptOptions; expectType(options.rangeOptions) } { // KMSProviders // aws expectAssignable({ accessKeyId: '', secretAccessKey: '' }); expectAssignable({ accessKeyId: '', secretAccessKey: '', sessionToken: undefined }); expectAssignable({ accessKeyId: '', secretAccessKey: '', sessionToken: '' }); // automatic expectAssignable({}); // azure expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a' }); expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a' }); expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a', identityPlatformEndpoint: undefined }); expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a', identityPlatformEndpoint: '' }); expectAssignable({ accessToken: 'a' }); expectAssignable({}); // gcp expectAssignable({ email: 'a', privateKey: 'a' }); expectAssignable({ email: 'a', privateKey: 'a', endpoint: undefined }); expectAssignable({ email: 'a', privateKey: 'a', endpoint: 'a' }); expectAssignable({ accessToken: 'a' }); // automatic expectAssignable({}); } libmongocrypt-1.8.4/bindings/python/000077500000000000000000000000001454530651600175435ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/.evergreen/000077500000000000000000000000001454530651600216035ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/.evergreen/test.sh000077500000000000000000000056321454530651600231270ustar00rootroot00000000000000#!/bin/bash # Test the Python bindings for libmongocrypt set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail # For createvirtualenv. . .evergreen/utils.sh # MONGOCRYPT_DIR is set by libmongocrypt/.evergreen/config.yml MONGOCRYPT_DIR="$MONGOCRYPT_DIR" git clone https://github.com/mongodb-labs/drivers-evergreen-tools.git if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/bin/mongocrypt.dll export PYMONGOCRYPT_LIB=$(cygpath -m $PYMONGOCRYPT_LIB) PYTHONS=("C:/python/Python37/python.exe" "C:/python/Python38/python.exe" "C:/python/Python39/python.exe" "C:/python/Python310/python.exe" "C:/python/Python311/python.exe") export CRYPT_SHARED_PATH=../crypt_shared/bin/mongo_crypt_v1.dll C:/python/Python310/python.exe drivers-evergreen-tools/.evergreen/mongodl.py --component crypt_shared \ --version latest --out ../crypt_shared/ elif [ "Darwin" = "$(uname -s)" ]; then export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.dylib if [[ $(uname -m) == 'arm64' ]]; then PYTHONS=("/Library/Frameworks/Python.framework/Versions/3.10/bin/python3" ) else PYTHONS=("python3" # Python 3 from brew "/Library/Frameworks/Python.framework/Versions/3.7/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.8/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.9/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.10/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3") fi export CRYPT_SHARED_PATH="../crypt_shared/lib/mongo_crypt_v1.dylib" python3 drivers-evergreen-tools/.evergreen/mongodl.py --component crypt_shared \ --version latest --out ../crypt_shared/ else export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib64/libmongocrypt.so PYTHONS=("/opt/mongodbtoolchain/v3/bin/python3" ) export CRYPT_SHARED_PATH="../crypt_shared/lib/mongo_crypt_v1.so" /opt/mongodbtoolchain/v3/bin/python3 drivers-evergreen-tools/.evergreen/mongodl.py --component \ crypt_shared --version latest --out ../crypt_shared/ --target rhel70 fi for PYTHON_BINARY in "${PYTHONS[@]}"; do echo "Running test with python: $PYTHON_BINARY" $PYTHON_BINARY -c 'import sys; print(sys.version)' createvirtualenv $PYTHON_BINARY .venv python -m pip install --prefer-binary -r test-requirements.txt python setup.py test echo "Running tests with CSFLE on dynamic library path..." TEST_CRYPT_SHARED=1 DYLD_FALLBACK_LIBRARY_PATH=../crypt_shared/lib/:$DYLD_FALLBACK_LIBRARY_PATH \ LD_LIBRARY_PATH=../crypt_shared/lib:$LD_LIBRARY_PATH \ PATH=../crypt_shared/bin:$PATH \ python setup.py test deactivate rm -rf .venv done libmongocrypt-1.8.4/bindings/python/.evergreen/utils.sh000077500000000000000000000020441454530651600233020ustar00rootroot00000000000000#!/bin/bash -ex # Usage: # createvirtualenv /path/to/python /output/path/for/venv # * param1: Python binary to use for the virtualenv # * param2: Path to the virtualenv to create createvirtualenv () { PYTHON=$1 VENVPATH=$2 if $PYTHON -m virtualenv --version; then VIRTUALENV="$PYTHON -m virtualenv --system-site-packages --never-download" elif $PYTHON -m venv -h>/dev/null; then VIRTUALENV="$PYTHON -m venv --system-site-packages" elif command -v virtualenv; then VIRTUALENV="$(command -v virtualenv) -p $PYTHON --system-site-packages --never-download" else echo "Cannot test without virtualenv" exit 1 fi $VIRTUALENV $VENVPATH if [ "Windows_NT" = "$OS" ]; then . $VENVPATH/Scripts/activate else . $VENVPATH/bin/activate fi # Upgrade to the latest versions of pip setuptools wheel so that # pip can always download the latest cryptography+cffi wheels. python -m pip install --upgrade pip python -m pip install --upgrade pip setuptools wheel } libmongocrypt-1.8.4/bindings/python/.gitignore000066400000000000000000000001501454530651600215270ustar00rootroot00000000000000*~ *#* .DS* *.cm *.class *.pyc *.pyd build/ doc/_build/ dist/ *.so *.egg .tox .eggs/ .idea/ *.egg-info/ libmongocrypt-1.8.4/bindings/python/CHANGELOG.rst000066400000000000000000000115541454530651600215720ustar00rootroot00000000000000Changelog ========= Changes in Version 1.6.0 ------------------------ - Drop support for Python 2 and Python <3.7. Python >=3.7 is now required. Changes in Version 1.5.2 ------------------------ - Bundle libmongocrypt 1.7.3 in release wheels. Changes in Version 1.5.1 ------------------------ - Bundle libmongocrypt 1.7.1 in release wheels. Changes in Version 1.5.0 ------------------------ - Add support for range-based Queryable Encryption with the new "rangePreview" algorithm. NOTE: The "rangePreview" algorithm is experimental only. It is not intended for public use. - Bundle libmongocrypt 1.7.0 in release wheels. - **Remove support for libmongocrypt <=1.7.0, libmongocrypt >=1.7.0 is now required.** Note this is only relevant for users that install from source or use the ``PYMONGOCRYPT_LIB`` environment variable. Changes in Version 1.4.1 ------------------------ - Fixed spurious exception traceback at interpreter shutdown: ``AttributeError: 'NoneType' object has no attribute 'mongocrypt_destroy'`` Changes in Version 1.4.0 ------------------------ - Bundle libmongocrypt 1.6.1 in release wheels. - Support GCP attached service accounts when using GCP KMS. - Support Azure VM-assigned Managed Identity for Automatic KMS Credentials. - Support obtaining AWS credentials for CSFLE in the same way as for MONGODB-AWS. Changes in Version 1.3.1 ------------------------ 1.3.1 is a recommended upgrade for all users of 1.3.0. - Fix a potential data corruption bug in RewrapManyDataKey (ClientEncryption.rewrap_many_data_key) when rotating encrypted data encryption keys backed by GCP or Azure key services. The following conditions will trigger this bug: - A GCP-backed or Azure-backed data encryption key being rewrapped requires fetching an access token for decryption of the data encryption key. The result of this bug is that the key material for all data encryption keys being rewrapped is replaced by new randomly generated material, destroying the original key material. To mitigate potential data corruption, upgrade to this version or higher before using RewrapManyDataKey to rotate Azure-backed or GCP-backed data encryption keys. A backup of the key vault collection should always be taken before key rotation. - Bundle libmongocrypt 1.5.2 in release wheels. - **Remove support for libmongocrypt <=1.5.1, libmongocrypt >=1.5.2 is now required.** Note this is only relevant for users that install from source or use the ``PYMONGOCRYPT_LIB`` environment variable. Changes in Version 1.3.0 ------------------------ - Bundle libmongocrypt 1.5.0 in release wheels. - Add support for Queryable Encryption with MongoDB 6.0. - Add support for the crypt_shared library which can be used instead of mongocryptd. - **Remove support for libmongocrypt 1.3, libmongocrypt >=1.5 is now required.** Note this is only relevant for users that install from source or use the ``PYMONGOCRYPT_LIB`` environment variable. Changes in Version 1.2.0 ------------------------ - Add support for the "kmip" KMS provider. - Add MongoCryptKmsContext.kms_provider property. - Bundle libmongocrypt 1.3.0 in release wheels. - **Remove support for libmongocrypt 1.2, libmongocrypt >=1.3 is now required.** Note this is only relevant for users that install from source or use the ``PYMONGOCRYPT_LIB`` environment variable. Changes in Version 1.1.2 ------------------------ - Fix a bug where decrypting from a memoryview was not supported. - Bundle libmongocrypt 1.2.2 in release wheels. Changes in Version 1.1.1 ------------------------ - Bundle libmongocrypt 1.2.1 in release wheels. Changes in Version 1.1.0 ------------------------ - Add support for Azure and GCP KMS providers. - Add support for temporary AWS credentials via the "sessionToken" option. - Bundle libmongocrypt 1.2.0 in release wheels. - **Remove support for libmongocrypt 1.0 and 1.1, libmongocrypt >=1.2 is now required.** Note this is only relevant for users that install from source or use the ``PYMONGOCRYPT_LIB`` environment variable. Changes in Version 1.0.1 ------------------------ - Bundle libmongocrypt 1.0.4 in release wheels. Changes in Version 1.0.0 ------------------------ - The first stable version. - Bundle libmongocrypt 1.0.0 in release wheels. Changes in Version 0.1b3 ------------------------ - Add support for custom KMS endpoints with the AWS masterkey provider. - Bundle libmongocrypt 1.0.0 in release wheels. Changes in Version 0.1b2 ------------------------ - Document that pip 19 is required for manylinux2010 wheel installation. - Bundle libmongocrypt 1.0.0-beta5 in release wheels. Changes in Version 0.1b1 ------------------------ - Make pymongocrypt compatible with manylinux2010 releases. - Bundle libmongocrypt 1.0.0-beta4 in release wheels. Changes in Version 0.1b0 ------------------------ - Initial Python binding for libmongocrypt. - Bundle libmongocrypt 1.0.0-beta4 in release wheels. libmongocrypt-1.8.4/bindings/python/LICENSE000066400000000000000000000261351454530651600205570ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. libmongocrypt-1.8.4/bindings/python/README.rst000066400000000000000000000163021454530651600212340ustar00rootroot00000000000000============ PyMongoCrypt ============ :Info: Python bindings for libmongocrypt. See `GitHub `_ for the latest source. :Author: Shane Harvey About ===== Python wrapper library for libmongocrypt that supports client side encryption in drivers. PyMongoCrypt uses `cffi `_ and `cryptography `_. PyMongoCrypt supports Python 3.7+ and PyPy3.7+. Support / Feedback ================== For issues with, questions about, or feedback for PyMongoCrypt, please look into our `support channels `_. Please do not email any of the PyMongoCrypt developers directly with issues or questions - you're more likely to get an answer on the `mongodb-user `_ list on Google Groups. Bugs / Feature Requests ======================= Think you’ve found a bug? Want to see a new feature in PyMongoCrypt? Please open a case in our issue management tool, JIRA: - `Create an account and login `_. - Navigate to `the PYTHON project `_. - Click **Create Issue** - Please provide as much information as possible about the issue type and how to reproduce it. Bug reports in JIRA for all driver projects (i.e. PYTHON, CSHARP, JAVA) and the Core Server (i.e. SERVER) project are **public**. How To Ask For Help ------------------- Please include all of the following information when opening an issue: - Detailed steps to reproduce the problem, including full traceback, if possible. - The exact python version used, with patch level:: $ python -c "import sys; print(sys.version)" - The exact version of PyMongoCrypt used:: $ python -c "import pymongocrypt; print(pymongocrypt.__version__)" - The exact version of libbmongocrypt used by PyMongoCrypt:: $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" - The exact version of PyMongo used (if applicable), with patch level:: $ python -c "import pymongo; print(pymongo.version); print(pymongo.has_c())" - The operating system and version (e.g. Windows 7, OSX 10.8, ...) - Web framework or asynchronous network library used, if any, with version (e.g. Django 1.7, mod_wsgi 4.3.0, gevent 1.0.1, Tornado 4.0.2, ...) Security Vulnerabilities ------------------------ If you've identified a security vulnerability in a driver or any other MongoDB project, please report it according to the `instructions here `_. Installation ============ PyMongoCrypt can be installed with `pip `_:: $ python -m pip install pymongocrypt $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" 1.2.1 PyMongoCrypt ships wheels for macOS, Windows, and manylinux2010 that include an embedded libmongocrypt build. Installing from wheels on Linux requires pip 19 or later because it adds `support for manylinux2010 wheels `_. Older versions of pip will attempt installation using the pymongocrypt-X.Y.tar.gz source distribution which requires the extra step of downloading and installing libmongocrypt as described below. Users can upgrade to pip 19 by running:: $ python -m pip install --upgrade 'pip>=19' Installing from source ---------------------- Installing from source (or the pymongocrypt-X.Y.tar.gz source distribution, or pip < 19 on Linux) requires an extra step of installing libmongocrypt. First, install PyMongoCrypt from source:: $ git clone git@github.com:mongodb/libmongocrypt.git $ python -m pip install ./libmongocrypt/bindings/python Next, install libmongocrypt. libmongocrypt is continuously built and published on evergreen. The latest tarball containing libmongocrypt built on all supported variants is `published here `_. Download and extract ``libmongocrypt-all.tar.gz`` and set ``PYMONGOCRYPT_LIB`` to the path to your operating system's libmongocrypt.so file. For example:: $ curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt/all/master/latest/libmongocrypt-all.tar.gz $ mkdir libmongocrypt-all && tar xzf libmongocrypt-all.tar.gz -C libmongocrypt-all $ ls libmongocrypt-all amazon2 rhel-62-64-bit rhel72-zseries-test ubuntu1604-arm64 debian10 rhel-67-s390x suse12-64 ubuntu1804-64 debian92 rhel-70-64-bit suse12-s390x ubuntu1804-arm64 linux-64-amazon-ami rhel-71-ppc64el suse15-64 windows-test macos rhel-80-64-bit ubuntu1604 macOS:: $ # Set PYMONGOCRYPT_LIB for macOS: $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/macos/nocrypto/lib/libmongocrypt.dylib $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" 1.2.1 Windows:: $ # Set PYMONGOCRYPT_LIB for Windows: $ chmod +x $(pwd)/libmongocrypt-all/windows-test/nocrypto/bin/mongocrypt.dll $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/windows-test/nocrypto/bin/mongocrypt.dll $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" 1.2.1 Linux:: $ # Set PYMONGOCRYPT_LIB for RHEL 6.2 x86_64: $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/rhel-62-64-bit/nocrypto/lib64/libmongocrypt.so $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" 1.2.1 Dependencies ============ PyMongoCrypt supports Python 3.7+ and PyPy3.7+. PyMongoCrypt requires `cffi `_ and `cryptography `_. If not installed using one of the official wheels, PyMongoCrypt also requires libmongocrypt to be installed on your system. If libmongocrypt is not installed you will see an error like this: .. code-block:: python >>> import pymongocrypt Traceback (most recent call last): File "", line 1, in File "pymongocrypt/__init__.py", line 15, in from pymongocrypt.binding import libmongocrypt_version, lib File "pymongocrypt/binding.py", line 803, in lib = ffi.dlopen(os.environ.get('PYMONGOCRYPT_LIB', 'mongocrypt')) File "/.../lib/python3.7/site-packages/cffi/api.py", line 146, in dlopen lib, function_cache = _make_ffi_library(self, name, flags) File "/.../lib/python3.7/site-packages/cffi/api.py", line 828, in _make_ffi_library backendlib = _load_backend_lib(backend, libname, flags) File "/.../lib/python3.7/site-packages/cffi/api.py", line 823, in _load_backend_lib raise OSError(msg) OSError: ctypes.util.find_library() did not manage to locate a library called 'mongocrypt' Use the ``PYMONGOCRYPT_LIB`` environment variable to load a locally installed libmongocrypt build without relying on platform specific library path environment variables, like ``LD_LIBRARY_PATH``. For example:: $ export PYMONGOCRYPT_LIB='/path/to/libmongocrypt.so' $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" 1.2.1 Testing ======= The easiest way to run the tests is to run **python setup.py test** in the root of the distribution. libmongocrypt-1.8.4/bindings/python/RELEASE.rst000066400000000000000000000077741454530651600213740ustar00rootroot00000000000000===================== PyMongoCrypt Releases ===================== Versioning ---------- PyMongoCrypt's version numbers follow `semantic versioning`_: each version number is structured "major.minor.patch". Patch releases fix bugs, minor releases add features (and may fix bugs), and major releases include API changes that break backwards compatibility (and may add features and fix bugs). In between releases we add .devN to the version number to denote the version under development. So if we just released 1.0.0, then the current dev version might be 1.0.1.dev0 or 1.1.0.dev0. PyMongoCrypt's version numbers do not necessarily correspond to the embedded libmongocrypt library's version number. For example, assume the current PyMongoCrypt version is 1.0 and libmongocrypt is 1.0. Let's say that libmongocrypt 2.0.0 is released which has breaking changes to its API. If those 2.0.0 changes do not require any breaking changes to PyMongoCrypt, then the next version can be 1.1. .. _semantic versioning: http://semver.org/ Release Process --------------- PyMongoCrypt ships wheels for macOS, Windows, and manylinux2010 that include an embedded libmongocrypt build. Releasing a new version requires macOS with Docker and a Windows machine. #. Create a ticket for the release and create a PR. The PR needs to include the next steps including the version change because the branch is protected from directly pushing commits. #. Edit the release.sh script to embed the most recent libmongocrypt tag into our wheels, for example:: # The libmongocrypt git revision release to embed in our wheels. -REVISION=$(git rev-list -n 1 1.0.0) +REVISION=$(git rev-list -n 1 1.0.1) #. Add a changlog entry for this release in CHANGELOG.rst. #. Bump "__version__" in ``pymongocrypt/version.py``. #. After merging the PR, clone the repository and check out the commit with the version change. #. Create and push tag:: $ git tag -a "pymongocrypt-" -m "pymongocrypt-.tar.gz pymongocrypt--py2.py3-none-manylinux2010_x86_64.whl pymongocrypt--py2.py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl pymongocrypt--py2.py3-none-macosx_10_14_x86_64.whl pymongocrypt--py2.py3-none-macosx_11_0_universal2.whl pymongocrypt--py2.py3-none-win_amd64.whl #. Upload all the release packages to PyPI with twine:: $ python3 -m twine upload dist/* #. Create a new PR against the same ticket to update version to a ``.dev0`` version. Manually Creating Wheels ------------------------ #. Build the release packages for macOS and manylinux by running the release.sh script on macOS. Note that Docker must be running:: $ git clone git@github.com:mongodb/libmongocrypt.git $ cd libmongocrypt/bindings/python $ git checkout "pymongocrypt " $ MACOS_TARGET=macos_x86_64 PYTHON= ./release.sh $ PYTHON= ./release.sh Make sure to run using the official binaries for Python 3.7 and 3.10. You should end up with the same files created by Evergreen (except for the Windows wheel). #. To build the release package for Windows, launch a windows-64-vsMulti-small Evergreen spawn host, clone the repro, checkout the release tag, and run the release script:: $ git clone git@github.com:mongodb/libmongocrypt.git $ cd libmongocrypt/bindings/python $ git checkout "pymongocrypt " $ ./release.sh This will create the following distributions:: $ ls dist pymongocrypt--py2.py3-none-win_amd64.whl libmongocrypt-1.8.4/bindings/python/build-manylinux-wheel.sh000077500000000000000000000005711454530651600243300ustar00rootroot00000000000000#!/bin/bash -ex cd /python # Compile wheel # https://github.com/pypa/manylinux/issues/49 rm -rf build /opt/python/cp37-cp37m/bin/python setup.py bdist_wheel # Audit wheels and write manylinux tag for whl in dist/*.whl; do # Skip already built manylinux wheels. if [[ "$whl" != *"manylinux"* ]]; then auditwheel repair $whl -w dist rm $whl fi done libmongocrypt-1.8.4/bindings/python/pymongocrypt/000077500000000000000000000000001454530651600223155ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/pymongocrypt/__init__.py000066400000000000000000000012571454530651600244330ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from pymongocrypt.binding import libmongocrypt_version, lib from pymongocrypt.version import __version__ libmongocrypt-1.8.4/bindings/python/pymongocrypt/auto_encrypter.py000066400000000000000000000040051454530651600257310ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from pymongocrypt.mongocrypt import MongoCrypt from pymongocrypt.state_machine import run_state_machine class AutoEncrypter(object): def __init__(self, callback, mongo_crypt_opts): """Encrypts and decrypts MongoDB commands. This class is used by a driver to support automatic encryption and decryption of MongoDB commands. :Parameters: - `callback`: A :class:`MongoCryptCallback`. - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. """ self.callback = callback self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) def encrypt(self, database, cmd): """Encrypt a MongoDB command. :Parameters: - `database`: The database for this command. - `cmd`: A MongoDB command as BSON. :Returns: The encrypted command. """ with self.mongocrypt.encryption_context(database, cmd) as ctx: return run_state_machine(ctx, self.callback) def decrypt(self, response): """Decrypt a MongoDB command response. :Parameters: - `response`: A MongoDB command response as BSON. :Returns: The decrypted command response. """ with self.mongocrypt.decryption_context(response) as ctx: return run_state_machine(ctx, self.callback) def close(self): """Cleanup resources.""" self.mongocrypt.close() self.callback.close() libmongocrypt-1.8.4/bindings/python/pymongocrypt/binary.py000066400000000000000000000061241454530651600241560ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Internal helpers for dealing with mongocrypt_binary_t.""" from pymongocrypt.binding import ffi, lib from pymongocrypt.errors import MongoCryptError def _to_bytes(mongocrypt_binary): """Returns this mongocrypt_binary_t as bytes.""" data = lib.mongocrypt_binary_data(mongocrypt_binary) if data == ffi.NULL: raise MongoCryptError('mongocrypt_binary_data returned NULL') data_len = lib.mongocrypt_binary_len(mongocrypt_binary) return ffi.unpack(ffi.cast("char*", data), data_len) def _write_bytes(mongocrypt_binary, data): """Writes the given data to a mongocrypt_binary_t.""" buf = lib.mongocrypt_binary_data(mongocrypt_binary) if buf == ffi.NULL: raise MongoCryptError('mongocrypt_binary_data returned NULL') ffi.memmove(buf, data, len(data)) class _MongoCryptBinary(object): __slots__ = ("bin",) def __init__(self, binary): """Wraps a mongocrypt_binary_t.""" if binary == ffi.NULL: raise MongoCryptError( "unable to create new mongocrypt_binary object") self.bin = binary def _close(self): """Cleanup resources.""" if self.bin: lib.mongocrypt_binary_destroy(self.bin) self.bin = None def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self._close() def to_bytes(self): """Returns this mongocrypt_binary_t as bytes.""" data = lib.mongocrypt_binary_data(self.bin) if data == ffi.NULL: return b'' data_len = lib.mongocrypt_binary_len(self.bin) return ffi.unpack(ffi.cast("char*", data), data_len) class MongoCryptBinaryOut(_MongoCryptBinary): __slots__ = () def __init__(self): """Wraps a mongocrypt_binary_t.""" super(MongoCryptBinaryOut, self).__init__(lib.mongocrypt_binary_new()) class MongoCryptBinaryIn(_MongoCryptBinary): __slots__ = ("cref",) def __init__(self, data): """Creates a mongocrypt_binary_t from binary data.""" # mongocrypt_binary_t does not own the data it is passed so we need to # create a separate reference to keep the data alive. self.cref = ffi.from_buffer("uint8_t[]", data) super(MongoCryptBinaryIn, self).__init__( lib.mongocrypt_binary_new_from_data(self.cref, len(data))) def _close(self): """Cleanup resources.""" super(MongoCryptBinaryIn, self)._close() if self.cref is not None: ffi.release(self.cref) self.cref = None libmongocrypt-1.8.4/bindings/python/pymongocrypt/binding.py000066400000000000000000001544771454530651600243230ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import os.path import sys import cffi from pymongocrypt.compat import PY3 from pymongocrypt.version import _MIN_LIBMONGOCRYPT_VERSION try: from pkg_resources import parse_version as _parse_version except ImportError: from distutils.version import LooseVersion as _LooseVersion def _parse_version(version): return _LooseVersion(version) ffi = cffi.FFI() # Generated with strip_header.py ffi.cdef("""/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** @file mongocrypt.h The top-level handle to libmongocrypt. */ /** * @mainpage libmongocrypt * See all public API documentation in: @ref mongocrypt.h */ /* clang-format off */ /* clang-format on */ /** * Returns the version string for libmongocrypt. * * @param[out] len An optional length of the returned string. May be NULL. * @returns a NULL terminated version string for libmongocrypt. */ const char *mongocrypt_version(uint32_t *len); /** * A non-owning view of a byte buffer. * * When constructing a mongocrypt_binary_t it is the responsibility of the * caller to maintain the lifetime of the viewed data. However, all public * functions that take a mongocrypt_binary_t as an argument will make a copy of * the viewed data. For example, the following is valid: * * @code{.c} * mongocrypt_binary_t bin = mongocrypt_binary_new_from_data(mydata, mylen); * assert (mongocrypt_setopt_kms_provider_local (crypt), bin); * // The viewed data of bin has been copied. Ok to free the view and the data. * mongocrypt_binary_destroy (bin); * my_free_fn (mydata); * @endcode * * Functions with a mongocrypt_binary_t* out guarantee the lifetime of the * viewed data to live as long as the parent object. For example, @ref * mongocrypt_ctx_mongo_op guarantees that the viewed data of * mongocrypt_binary_t is valid until the parent ctx is destroyed with @ref * mongocrypt_ctx_destroy. */ typedef struct _mongocrypt_binary_t mongocrypt_binary_t; /** * Create a new non-owning view of a buffer (data + length). * * Use this to create a mongocrypt_binary_t used for output parameters. * * @returns A new mongocrypt_binary_t. */ mongocrypt_binary_t *mongocrypt_binary_new(void); /** * Create a new non-owning view of a buffer (data + length). * * @param[in] data A pointer to an array of bytes. This data is not copied. @p * data must outlive the binary object. * @param[in] len The length of the @p data byte array. * * @returns A new @ref mongocrypt_binary_t. */ mongocrypt_binary_t *mongocrypt_binary_new_from_data(uint8_t *data, uint32_t len); /** * Get a pointer to the viewed data. * * @param[in] binary The @ref mongocrypt_binary_t. * * @returns A pointer to the viewed data. */ uint8_t *mongocrypt_binary_data(const mongocrypt_binary_t *binary); /** * Get the length of the viewed data. * * @param[in] binary The @ref mongocrypt_binary_t. * * @returns The length of the viewed data. */ uint32_t mongocrypt_binary_len(const mongocrypt_binary_t *binary); /** * Free the @ref mongocrypt_binary_t. * * This does not free the viewed data. * * @param[in] binary The mongocrypt_binary_t destroy. */ void mongocrypt_binary_destroy(mongocrypt_binary_t *binary); /** * Indicates success or contains error information. * * Functions like @ref mongocrypt_ctx_encrypt_init follow a pattern to expose a * status. A boolean is returned. True indicates success, and false indicates * failure. On failure a status on the handle is set, and is accessible with a * corresponding (handle)_status function. E.g. @ref mongocrypt_ctx_status. */ typedef struct _mongocrypt_status_t mongocrypt_status_t; /** * Indicates the type of error. */ typedef enum { MONGOCRYPT_STATUS_OK = 0, MONGOCRYPT_STATUS_ERROR_CLIENT = 1, MONGOCRYPT_STATUS_ERROR_KMS = 2, MONGOCRYPT_STATUS_ERROR_CRYPT_SHARED = 3, } mongocrypt_status_type_t; /** * Create a new status object. * * Use a new status object to retrieve the status from a handle by passing * this as an out-parameter to functions like @ref mongocrypt_ctx_status. * When done, destroy it with @ref mongocrypt_status_destroy. * * @returns A new status object. */ mongocrypt_status_t *mongocrypt_status_new(void); /** * Set a status object with message, type, and code. * * Use this to set the @ref mongocrypt_status_t given in the crypto hooks. * * @param[in] type The status type. * @param[in] code The status code. * @param[in] message The message. * @param[in] message_len Due to historical behavior, pass 1 + the string length * of @p message (which differs from other functions accepting string * arguments). * Alternatively, if message is NULL terminated this may be -1 to tell * mongocrypt * to determine the string's length with strlen. * */ void mongocrypt_status_set(mongocrypt_status_t *status, mongocrypt_status_type_t type, uint32_t code, const char *message, int32_t message_len); /** * Indicates success or the type of error. * * @param[in] status The status object. * * @returns A @ref mongocrypt_status_type_t. */ mongocrypt_status_type_t mongocrypt_status_type(mongocrypt_status_t *status); /** * Get an error code or 0. * * @param[in] status The status object. * * @returns An error code. */ uint32_t mongocrypt_status_code(mongocrypt_status_t *status); /** * Get the error message associated with a status or NULL. * * @param[in] status The status object. * @param[out] len An optional length of the returned string (excluding the * trailing NULL byte). May be NULL. * * @returns A NULL terminated error message or NULL. */ const char *mongocrypt_status_message(mongocrypt_status_t *status, uint32_t *len); /** * Returns true if the status indicates success. * * @param[in] status The status to check. * * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_status_ok(mongocrypt_status_t *status); /** * Free the memory for a status object. * * @param[in] status The status to destroy. */ void mongocrypt_status_destroy(mongocrypt_status_t *status); /** * Indicates the type of log message. */ typedef enum { MONGOCRYPT_LOG_LEVEL_FATAL = 0, MONGOCRYPT_LOG_LEVEL_ERROR = 1, MONGOCRYPT_LOG_LEVEL_WARNING = 2, MONGOCRYPT_LOG_LEVEL_INFO = 3, MONGOCRYPT_LOG_LEVEL_TRACE = 4 } mongocrypt_log_level_t; /** * A log callback function. Set a custom log callback with @ref * mongocrypt_setopt_log_handler. * * @param[in] message A NULL terminated message. * @param[in] message_len The length of message. * @param[in] ctx A context provided by the caller of @ref * mongocrypt_setopt_log_handler. */ typedef void (*mongocrypt_log_fn_t)(mongocrypt_log_level_t level, const char *message, uint32_t message_len, void *ctx); /** * The top-level handle to libmongocrypt. * * Create a mongocrypt_t handle to perform operations within libmongocrypt: * encryption, decryption, registering log callbacks, etc. * * Functions on a mongocrypt_t are thread safe, though functions on derived * handles (e.g. mongocrypt_ctx_t) are not and must be owned by a single * thread. See each handle's documentation for thread-safety considerations. * * Multiple mongocrypt_t handles may be created. */ typedef struct _mongocrypt_t mongocrypt_t; /** * Allocate a new @ref mongocrypt_t object. * * Set options using mongocrypt_setopt_* functions, then initialize with @ref * mongocrypt_init. When done with the @ref mongocrypt_t, free with @ref * mongocrypt_destroy. * * @returns A new @ref mongocrypt_t object. */ mongocrypt_t *mongocrypt_new(void); /** * Set a handler on the @ref mongocrypt_t object to get called on every log * message. * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] log_fn The log callback. * @param[in] log_ctx A context passed as an argument to the log callback every * invocation. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_setopt_log_handler(mongocrypt_t *crypt, mongocrypt_log_fn_t log_fn, void *log_ctx); /** * Configure an AWS KMS provider on the @ref mongocrypt_t object. * * This has been superseded by the more flexible: * @ref mongocrypt_setopt_kms_providers * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] aws_access_key_id The AWS access key ID used to generate KMS * messages. * @param[in] aws_access_key_id_len The string length (in bytes) of @p * aws_access_key_id. Pass -1 to determine the string length with strlen (must * be NULL terminated). * @param[in] aws_secret_access_key The AWS secret access key used to generate * KMS messages. * @param[in] aws_secret_access_key_len The string length (in bytes) of @p * aws_secret_access_key. Pass -1 to determine the string length with strlen * (must be NULL terminated). * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_setopt_kms_provider_aws(mongocrypt_t *crypt, const char *aws_access_key_id, int32_t aws_access_key_id_len, const char *aws_secret_access_key, int32_t aws_secret_access_key_len); /** * Configure a local KMS provider on the @ref mongocrypt_t object. * * This has been superseded by the more flexible: * @ref mongocrypt_setopt_kms_providers * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] key A 96 byte master key used to encrypt and decrypt key vault * keys. The viewed data is copied. It is valid to destroy @p key with @ref * mongocrypt_binary_destroy immediately after. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_setopt_kms_provider_local(mongocrypt_t *crypt, mongocrypt_binary_t *key); /** * Configure KMS providers with a BSON document. * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] kms_providers A BSON document mapping the KMS provider names * to credentials. Set a KMS provider value to an empty document to supply * credentials on-demand with @ref mongocrypt_ctx_provide_kms_providers. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_setopt_kms_providers(mongocrypt_t *crypt, mongocrypt_binary_t *kms_providers); /** * Set a local schema map for encryption. * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] schema_map A BSON document representing the schema map supplied by * the user. The keys are collection namespaces and values are JSON schemas. The * viewed data copied. It is valid to destroy @p schema_map with @ref * mongocrypt_binary_destroy immediately after. * @pre @p crypt has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status */ bool mongocrypt_setopt_schema_map(mongocrypt_t *crypt, mongocrypt_binary_t *schema_map); /** * Set a local EncryptedFieldConfigMap for encryption. * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] efc_map A BSON document representing the EncryptedFieldConfigMap * supplied by the user. The keys are collection namespaces and values are * EncryptedFieldConfigMap documents. The viewed data copied. It is valid to * destroy @p efc_map with @ref mongocrypt_binary_destroy immediately after. * @pre @p crypt has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status */ bool mongocrypt_setopt_encrypted_field_config_map(mongocrypt_t *crypt, mongocrypt_binary_t *efc_map); /** * @brief Append an additional search directory to the search path for loading * the crypt_shared dynamic library. * * @param[in] crypt The @ref mongocrypt_t object to update * @param[in] path A null-terminated sequence of bytes for the search path. On * some filesystems, this may be arbitrary bytes. On other filesystems, this may * be required to be a valid UTF-8 code unit sequence. If the leading element of * the path is the literal string "$ORIGIN", that substring will be replaced * with the directory path containing the executable libmongocrypt module. If * the path string is literal "$SYSTEM", then libmongocrypt will defer to the * system's library resolution mechanism to find the crypt_shared library. * * @note If no crypt_shared dynamic library is found in any of the directories * specified by the search paths loaded here, @ref mongocrypt_init() will still * succeed and continue to operate without crypt_shared. * * @note The search paths are searched in the order that they are appended. This * allows one to provide a precedence in how the library will be discovered. For * example, appending known directories before appending "$SYSTEM" will allow * one to supersede the system's installed library, but still fall-back to it if * the library wasn't found otherwise. If one does not ever append "$SYSTEM", * then the system's library-search mechanism will never be consulted. * * @note If an absolute path to the library is specified using * @ref mongocrypt_setopt_set_crypt_shared_lib_path_override, then paths * appended here will have no effect. */ void mongocrypt_setopt_append_crypt_shared_lib_search_path(mongocrypt_t *crypt, const char *path); /** * @brief Set a single override path for loading the crypt_shared dynamic * library. * * @param[in] crypt The @ref mongocrypt_t object to update * @param[in] path A null-terminated sequence of bytes for a path to the * crypt_shared dynamic library. On some filesystems, this may be arbitrary * bytes. On other filesystems, this may be required to be a valid UTF-8 code * unit sequence. If the leading element of the path is the literal string * `$ORIGIN`, that substring will be replaced with the directory path containing * the executable libmongocrypt module. * * @note This function will do no IO nor path validation. All validation will * occur during the call to @ref mongocrypt_init. * * @note If a crypt_shared library path override is specified here, then no * paths given to @ref mongocrypt_setopt_append_crypt_shared_lib_search_path * will be consulted when opening the crypt_shared library. * * @note If a path is provided via this API and @ref mongocrypt_init fails to * initialize a valid crypt_shared library instance for the path specified, then * the initialization of mongocrypt_t will fail with an error. */ void mongocrypt_setopt_set_crypt_shared_lib_path_override(mongocrypt_t *crypt, const char *path); /** * @brief Opt-into handling the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state. * * If set, before entering the MONGOCRYPT_CTX_NEED_KMS state, * contexts may enter the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state * and then wait for credentials to be supplied through * @ref mongocrypt_ctx_provide_kms_providers. * * A context will only enter MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS * if an empty document was set for a KMS provider in @ref * mongocrypt_setopt_kms_providers. * * @param[in] crypt The @ref mongocrypt_t object to update */ void mongocrypt_setopt_use_need_kms_credentials_state(mongocrypt_t *crypt); /** * Initialize new @ref mongocrypt_t object. * * Set options before using @ref mongocrypt_setopt_kms_provider_local, @ref * mongocrypt_setopt_kms_provider_aws, or @ref mongocrypt_setopt_log_handler. * * @param[in] crypt The @ref mongocrypt_t object. * * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status Failure may occur if previously * set * options are invalid. */ bool mongocrypt_init(mongocrypt_t *crypt); /** * Get the status associated with a @ref mongocrypt_t object. * * @param[in] crypt The @ref mongocrypt_t object. * @param[out] status Receives the status. * * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_status(mongocrypt_t *crypt, mongocrypt_status_t *status); /** * Destroy the @ref mongocrypt_t object. * * @param[in] crypt The @ref mongocrypt_t object to destroy. */ void mongocrypt_destroy(mongocrypt_t *crypt); /** * Obtain a nul-terminated version string of the loaded crypt_shared dynamic * library, if available. * * If no crypt_shared was successfully loaded, this function returns NULL. * * @param[in] crypt The mongocrypt_t object after a successful call to * mongocrypt_init. * @param[out] len An optional output parameter to which the length of the * returned string is written. If provided and no crypt_shared library was * loaded, zero is written to *len. * * @return A nul-terminated string of the dynamically loaded crypt_shared * library. * * @note For a numeric value that can be compared against, use * @ref mongocrypt_crypt_shared_lib_version. */ const char *mongocrypt_crypt_shared_lib_version_string(const mongocrypt_t *crypt, uint32_t *len); /** * @brief Obtain a 64-bit constant encoding the version of the loaded * crypt_shared library, if available. * * @param[in] crypt The mongocrypt_t object after a successul call to * mongocrypt_init. * * @return A 64-bit encoded version number, with the version encoded as four * sixteen-bit integers, or zero if no crypt_shared library was loaded. * * The version is encoded as four 16-bit numbers, from high to low: * * - Major version * - Minor version * - Revision * - Reserved * * For example, version 6.2.1 would be encoded as: 0x0006'0002'0001'0000 */ uint64_t mongocrypt_crypt_shared_lib_version(const mongocrypt_t *crypt); /** * Manages the state machine for encryption or decryption. */ typedef struct _mongocrypt_ctx_t mongocrypt_ctx_t; /** * Create a new uninitialized @ref mongocrypt_ctx_t. * * Initialize the context with functions like @ref mongocrypt_ctx_encrypt_init. * When done, destroy it with @ref mongocrypt_ctx_destroy. * * @param[in] crypt The @ref mongocrypt_t object. * @returns A new context. */ mongocrypt_ctx_t *mongocrypt_ctx_new(mongocrypt_t *crypt); /** * Get the status associated with a @ref mongocrypt_ctx_t object. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[out] status Receives the status. * * @returns True if the output is an ok status, false if it is an error * status. * * @see mongocrypt_status_ok */ bool mongocrypt_ctx_status(mongocrypt_ctx_t *ctx, mongocrypt_status_t *status); /** * Set the key id to use for explicit encryption. * * It is an error to set both this and the key alt name. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] key_id The binary corresponding to the _id (a UUID) of the data * key to use from the key vault collection. Note, the UUID must be encoded with * RFC-4122 byte order. The viewed data is copied. It is valid to destroy * @p key_id with @ref mongocrypt_binary_destroy immediately after. * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_key_id(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *key_id); /** * Set the keyAltName to use for explicit encryption or * data key creation. * * Pass the binary encoding a BSON document like the following: * * { "keyAltName" : (BSON UTF8 value) } * * For explicit encryption, it is an error to set both the keyAltName * and the key id. * * For creating data keys, call this function repeatedly to set * multiple keyAltNames. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] key_alt_name The name to use. The viewed data is copied. It is * valid to destroy @p key_alt_name with @ref mongocrypt_binary_destroy * immediately after. * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_key_alt_name(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *key_alt_name); /** * Set the keyMaterial to use for encrypting data. * * Pass the binary encoding of a BSON document like the following: * * { "keyMaterial" : (BSON BINARY value) } * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] key_material The data encryption key to use. The viewed data is * copied. It is valid to destroy @p key_material with @ref * mongocrypt_binary_destroy immediately after. * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_key_material(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *key_material); /** * Set the algorithm used for encryption to either * deterministic or random encryption. This value * should only be set when using explicit encryption. * * If -1 is passed in for "len", then "algorithm" is * assumed to be a null-terminated string. * * Valid values for algorithm are: * "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" * "AEAD_AES_256_CBC_HMAC_SHA_512-Random" * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] algorithm A string specifying the algorithm to * use for encryption. * @param[in] len The length of the algorithm string. * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_algorithm(mongocrypt_ctx_t *ctx, const char *algorithm, int len); /// String constant for setopt_algorithm "Deterministic" encryption /// String constant for setopt_algorithm "Random" encryption /// String constant for setopt_algorithm "Indexed" explicit encryption /// String constant for setopt_algorithm "Unindexed" explicit encryption /// String constant for setopt_algorithm "rangePreview" explicit encryption /// NOTE: The RangePreview algorithm is experimental only. It is not intended /// for public use. /** * Identify the AWS KMS master key to use for creating a data key. * * This has been superseded by the more flexible: * @ref mongocrypt_ctx_setopt_key_encryption_key * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] region The AWS region. * @param[in] region_len The string length of @p region. Pass -1 to determine * the string length with strlen (must be NULL terminated). * @param[in] cmk The Amazon Resource Name (ARN) of the customer master key * (CMK). * @param[in] cmk_len The string length of @p cmk_len. Pass -1 to determine the * string length with strlen (must be NULL terminated). * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_masterkey_aws(mongocrypt_ctx_t *ctx, const char *region, int32_t region_len, const char *cmk, int32_t cmk_len); /** * Identify a custom AWS endpoint when creating a data key. * This is used internally to construct the correct HTTP request * (with the Host header set to this endpoint). This endpoint * is persisted in the new data key, and will be returned via * @ref mongocrypt_kms_ctx_endpoint. * * This has been superseded by the more flexible: * @ref mongocrypt_ctx_setopt_key_encryption_key * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] endpoint The endpoint. * @param[in] endpoint_len The string length of @p endpoint. Pass -1 to * determine the string length with strlen (must be NULL terminated). * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_masterkey_aws_endpoint(mongocrypt_ctx_t *ctx, const char *endpoint, int32_t endpoint_len); /** * Set the master key to "local" for creating a data key. * This has been superseded by the more flexible: * @ref mongocrypt_ctx_setopt_key_encryption_key * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_masterkey_local(mongocrypt_ctx_t *ctx); /** * Set key encryption key document for creating a data key or for rewrapping * datakeys. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] bin BSON representing the key encryption key document with * an additional "provider" field. The following forms are accepted: * * AWS * { * provider: "aws", * region: , * key: , * endpoint: * } * * Azure * { * provider: "azure", * keyVaultEndpoint: , * keyName: , * keyVersion: * } * * GCP * { * provider: "gcp", * projectId: , * location: , * keyRing: , * keyName: , * keyVersion: , * endpoint: * } * * Local * { * provider: "local" * } * * KMIP * { * provider: "kmip", * keyId: * endpoint: * } * * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status. */ bool mongocrypt_ctx_setopt_key_encryption_key(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *bin); /** * Initialize a context to create a data key. * * Associated options: * - @ref mongocrypt_ctx_setopt_masterkey_aws * - @ref mongocrypt_ctx_setopt_masterkey_aws_endpoint * - @ref mongocrypt_ctx_setopt_masterkey_local * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status * @pre A master key option has been set, and an associated KMS provider * has been set on the parent @ref mongocrypt_t. */ bool mongocrypt_ctx_datakey_init(mongocrypt_ctx_t *ctx); /** * Initialize a context for encryption. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] db The database name. * @param[in] db_len The byte length of @p db. Pass -1 to determine the string * length with strlen (must * be NULL terminated). * @param[in] cmd The BSON command to be encrypted. The viewed data is copied. * It is valid to destroy @p cmd with @ref mongocrypt_binary_destroy immediately * after. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_encrypt_init(mongocrypt_ctx_t *ctx, const char *db, int32_t db_len, mongocrypt_binary_t *cmd); /** * Explicit helper method to encrypt a single BSON object. Contexts * created for explicit encryption will not go through mongocryptd. * * To specify a key_id, algorithm, or iv to use, please use the * corresponding mongocrypt_setopt methods before calling this. * * This method expects the passed-in BSON to be of the form: * { "v" : BSON value to encrypt } * * The value of "v" is expected to be the BSON value passed to a driver * ClientEncryption.encrypt helper. * * Associated options for FLE 1: * - @ref mongocrypt_ctx_setopt_key_id * - @ref mongocrypt_ctx_setopt_key_alt_name * - @ref mongocrypt_ctx_setopt_algorithm * * Associated options for Queryable Encryption: * - @ref mongocrypt_ctx_setopt_key_id * - @ref mongocrypt_ctx_setopt_index_key_id * - @ref mongocrypt_ctx_setopt_contention_factor * - @ref mongocrypt_ctx_setopt_query_type * - @ref mongocrypt_ctx_setopt_algorithm_range * * An error is returned if FLE 1 and Queryable Encryption incompatible options * are set. * * @param[in] ctx A @ref mongocrypt_ctx_t. * @param[in] msg A @ref mongocrypt_binary_t the plaintext BSON value. The * viewed data is copied. It is valid to destroy @p msg with @ref * mongocrypt_binary_destroy immediately after. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *msg); /** * Explicit helper method to encrypt a Match Expression or Aggregate Expression. * Contexts created for explicit encryption will not go through mongocryptd. * Requires query_type to be "rangePreview". * NOTE: The RangePreview algorithm is experimental only. It is not intended for * public use. * * This method expects the passed-in BSON to be of the form: * { "v" : FLE2RangeFindDriverSpec } * * FLE2RangeFindDriverSpec is a BSON document with one of these forms: * * 1. A Match Expression of this form: * {$and: [{: {: , {: {: }}]} * 2. An Aggregate Expression of this form: * {$and: [{: [, ]}, {: [, ]}] * * may be $lt, $lte, $gt, or $gte. * * The value of "v" is expected to be the BSON value passed to a driver * ClientEncryption.encryptExpression helper. * * Associated options for FLE 1: * - @ref mongocrypt_ctx_setopt_key_id * - @ref mongocrypt_ctx_setopt_key_alt_name * - @ref mongocrypt_ctx_setopt_algorithm * * Associated options for Queryable Encryption: * - @ref mongocrypt_ctx_setopt_key_id * - @ref mongocrypt_ctx_setopt_index_key_id * - @ref mongocrypt_ctx_setopt_contention_factor * - @ref mongocrypt_ctx_setopt_query_type * - @ref mongocrypt_ctx_setopt_algorithm_range * * An error is returned if FLE 1 and Queryable Encryption incompatible options * are set. * * @param[in] ctx A @ref mongocrypt_ctx_t. * @param[in] msg A @ref mongocrypt_binary_t the plaintext BSON value. The * viewed data is copied. It is valid to destroy @p msg with @ref * mongocrypt_binary_destroy immediately after. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_explicit_encrypt_expression_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *msg); /** * Initialize a context for decryption. * * This method expects the passed-in BSON to be of the form: * { "v" : BSON value to encrypt } * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] doc The document to be decrypted. The viewed data is copied. It is * valid to destroy @p doc with @ref mongocrypt_binary_destroy immediately * after. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_decrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *doc); /** * Explicit helper method to decrypt a single BSON object. * * Pass the binary encoding of a BSON document containing the BSON value to * encrypt like the following: * * { "v" : (BSON BINARY value of subtype 6) } * * @param[in] ctx A @ref mongocrypt_ctx_t. * @param[in] msg A @ref mongocrypt_binary_t the encrypted BSON. The viewed data * is copied. It is valid to destroy @p msg with @ref mongocrypt_binary_destroy * immediately after. */ bool mongocrypt_ctx_explicit_decrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *msg); /** * @brief Initialize a context to rewrap datakeys. * * Associated options: * - @ref mongocrypt_ctx_setopt_key_encryption_key * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] filter The filter to use for the find command on the key vault * collection to retrieve datakeys to rewrap. * @return A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status. */ bool mongocrypt_ctx_rewrap_many_datakey_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *filter); /** * Indicates the state of the @ref mongocrypt_ctx_t. Each state requires * different handling. See [the integration * guide](https://github.com/mongodb/libmongocrypt/blob/master/integrating.md#state-machine) * for information on what to do for each state. */ typedef enum { MONGOCRYPT_CTX_ERROR = 0, MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */ MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */ MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */ MONGOCRYPT_CTX_NEED_KMS = 4, MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7, /* fetch/renew KMS credentials */ MONGOCRYPT_CTX_READY = 5, /* ready for encryption/decryption */ MONGOCRYPT_CTX_DONE = 6, } mongocrypt_ctx_state_t; /** * Get the current state of a context. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @returns A @ref mongocrypt_ctx_state_t. */ mongocrypt_ctx_state_t mongocrypt_ctx_state(mongocrypt_ctx_t *ctx); /** * Get BSON necessary to run the mongo operation when mongocrypt_ctx_t * is in MONGOCRYPT_CTX_NEED_MONGO_* states. * * @p op_bson is a BSON document to be used for the operation. * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter. * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter. * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a command to send to * mongocryptd. * * The lifetime of @p op_bson is tied to the lifetime of @p ctx. It is valid * until @ref mongocrypt_ctx_destroy is called. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[out] op_bson A BSON document for the MongoDB operation. The data * viewed by @p op_bson is guaranteed to be valid until @p ctx is destroyed with * @ref mongocrypt_ctx_destroy. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_mongo_op(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *op_bson); /** * Feed a BSON reply or result when mongocrypt_ctx_t is in * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times * depending on the operation. * * reply is a BSON document result being fed back for this operation. * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections * cursor. (Note, if listCollections returned no result, do not call this * function.) * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor. * (Note, if find returned no results, do not call this function. reply must * not * be NULL.) * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a reply from mongocryptd. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] reply A BSON document for the MongoDB operation. The viewed data * is copied. It is valid to destroy @p reply with @ref * mongocrypt_binary_destroy immediately after. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_mongo_feed(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *reply); /** * Call when done feeding the reply (or replies) back to the context. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_mongo_done(mongocrypt_ctx_t *ctx); /** * Manages a single KMS HTTP request/response. */ typedef struct _mongocrypt_kms_ctx_t mongocrypt_kms_ctx_t; /** * Get the next KMS handle. * * Multiple KMS handles may be retrieved at once. Drivers may do this to fan * out multiple concurrent KMS HTTP requests. Feeding multiple KMS requests * is thread-safe. * * If KMS handles are being handled synchronously, the driver can reuse the same * TLS socket to send HTTP requests and receive responses. * * @param[in] ctx A @ref mongocrypt_ctx_t. * @returns a new @ref mongocrypt_kms_ctx_t or NULL. */ mongocrypt_kms_ctx_t *mongocrypt_ctx_next_kms_ctx(mongocrypt_ctx_t *ctx); /** * Get the HTTP request message for a KMS handle. * * The lifetime of @p msg is tied to the lifetime of @p kms. It is valid * until @ref mongocrypt_ctx_kms_done is called. * * @param[in] kms A @ref mongocrypt_kms_ctx_t. * @param[out] msg The HTTP request to send to KMS. The data viewed by @p msg is * guaranteed to be valid until the call of @ref mongocrypt_ctx_kms_done of the * parent @ref mongocrypt_ctx_t. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_kms_ctx_status */ bool mongocrypt_kms_ctx_message(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *msg); /** * Get the hostname from which to connect over TLS. * * The storage for @p endpoint is not owned by the caller, but * is valid until calling @ref mongocrypt_ctx_kms_done. * * @param[in] kms A @ref mongocrypt_kms_ctx_t. * @param[out] endpoint The output endpoint as a NULL terminated string. * The endpoint consists of a hostname and port separated by a colon. * E.g. "example.com:123". A port is always present. * * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_kms_ctx_status */ bool mongocrypt_kms_ctx_endpoint(mongocrypt_kms_ctx_t *kms, const char **endpoint); /** * Indicates how many bytes to feed into @ref mongocrypt_kms_ctx_feed. * * @param[in] kms The @ref mongocrypt_kms_ctx_t. * @returns The number of requested bytes. */ uint32_t mongocrypt_kms_ctx_bytes_needed(mongocrypt_kms_ctx_t *kms); /** * Feed bytes from the HTTP response. * * Feeding more bytes than what has been returned in @ref * mongocrypt_kms_ctx_bytes_needed is an error. * * @param[in] kms The @ref mongocrypt_kms_ctx_t. * @param[in] bytes The bytes to feed. The viewed data is copied. It is valid to * destroy @p bytes with @ref mongocrypt_binary_destroy immediately after. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_kms_ctx_status */ bool mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes); /** * Get the status associated with a @ref mongocrypt_kms_ctx_t object. * * @param[in] kms The @ref mongocrypt_kms_ctx_t object. * @param[out] status Receives the status. * * @returns A boolean indicating success. If false, an error status is set. */ bool mongocrypt_kms_ctx_status(mongocrypt_kms_ctx_t *kms, mongocrypt_status_t *status); /** * Get the KMS provider identifier associated with this KMS request. * * This is used to conditionally configure TLS connections based on the KMS * request. It is useful for KMIP, which authenticates with a client * certificate. * * @param[in] kms The @ref mongocrypt_kms_ctx_t object. * @param[out] len Receives the length of the returned string. It may be NULL. * If it is not NULL, it is set to the length of the returned string without * the NULL terminator. * * @returns One of the NULL terminated static strings: "aws", "azure", "gcp", or * "kmip". */ const char *mongocrypt_kms_ctx_get_kms_provider(mongocrypt_kms_ctx_t *kms, uint32_t *len); /** * Call when done handling all KMS contexts. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_kms_done(mongocrypt_ctx_t *ctx); /** * Call in response to the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state * to set per-context KMS provider settings. These follow the same format * as @ref mongocrypt_setopt_kms_providers. If no keys are present in the * BSON input, the KMS provider settings configured for the @ref mongocrypt_t * at initialization are used. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] kms_providers_definition A BSON document mapping the KMS provider * names to credentials. * * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status. */ bool mongocrypt_ctx_provide_kms_providers(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *kms_providers_definition); /** * Perform the final encryption or decryption. * * @param[in] ctx A @ref mongocrypt_ctx_t. * @param[out] out The final BSON. The data viewed by @p out is guaranteed * to be valid until @p ctx is destroyed with @ref mongocrypt_ctx_destroy. * The meaning of this BSON depends on the type of @p ctx. * * If @p ctx was initialized with @ref mongocrypt_ctx_encrypt_init, then * this BSON is the (possibly) encrypted command to send to the server. * * If @p ctx was initialized with @ref mongocrypt_ctx_decrypt_init, then * this BSON is the decrypted result to return to the user. * * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_encrypt_init, * then this BSON has the form { "v": (BSON binary) } where the BSON binary * is the resulting encrypted value. * * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_decrypt_init, * then this BSON has the form { "v": (BSON value) } where the BSON value * is the resulting decrypted value. * * If @p ctx was initialized with @ref mongocrypt_ctx_datakey_init, then * this BSON is the document containing the new data key to be inserted into * the key vault collection. * * If @p ctx was initialized with @ref mongocrypt_ctx_rewrap_many_datakey_init, * then this BSON has the form: * { "v": [{ "_id": ..., "keyMaterial": ..., "masterKey": ... }, ...] } * where each BSON document in the array contains the updated fields of a * rewrapped datakey to be bulk-updated into the key vault collection. * Note: the updateDate field should be updated using the $currentDate operator. * * @returns a bool indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out); /** * Destroy and free all memory associated with a @ref mongocrypt_ctx_t. * * @param[in] ctx A @ref mongocrypt_ctx_t. */ void mongocrypt_ctx_destroy(mongocrypt_ctx_t *ctx); /** * An crypto AES-256-CBC encrypt or decrypt function. * * Note, @p in is already padded. Encrypt with padding disabled. * @param[in] ctx An optional context object that may have been set when hooks * were enabled. * @param[in] key An encryption key (32 bytes for AES_256). * @param[in] iv An initialization vector (16 bytes for AES_256); * @param[in] in The input. * @param[out] out A preallocated byte array for the output. See @ref * mongocrypt_binary_data. * @param[out] bytes_written Set this to the number of bytes written to @p out. * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status * with a message indiciating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_crypto_fn)(void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status); /** * A crypto signature or HMAC function. * * Currently used in callbacks for HMAC SHA-512, HMAC SHA-256, and RSA SHA-256 * signature. * * @param[in] ctx An optional context object that may have been set when hooks * were enabled. * @param[in] key An encryption key (32 bytes for HMAC_SHA512). * @param[in] in The input. * @param[out] out A preallocated byte array for the output. See @ref * mongocrypt_binary_data. * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status * with a message indiciating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_hmac_fn)(void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status); /** * A crypto hash (SHA-256) function. * * @param[in] ctx An optional context object that may have been set when hooks * were enabled. * @param[in] in The input. * @param[out] out A preallocated byte array for the output. See @ref * mongocrypt_binary_data. * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status * with a message indiciating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_hash_fn)(void *ctx, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status); /** * A crypto secure random function. * * @param[in] ctx An optional context object that may have been set when hooks * were enabled. * @param[out] out A preallocated byte array for the output. See @ref * mongocrypt_binary_data. * @param[in] count The number of random bytes requested. * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status * with a message indiciating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_random_fn)(void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_status_t *status); bool mongocrypt_setopt_crypto_hooks(mongocrypt_t *crypt, mongocrypt_crypto_fn aes_256_cbc_encrypt, mongocrypt_crypto_fn aes_256_cbc_decrypt, mongocrypt_random_fn random, mongocrypt_hmac_fn hmac_sha_512, mongocrypt_hmac_fn hmac_sha_256, mongocrypt_hash_fn sha_256, void *ctx); /** * Set a crypto hook for the AES256-CTR operations. * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] aes_256_ctr_encrypt The crypto callback function for encrypt * operation. * @param[in] aes_256_ctr_decrypt The crypto callback function for decrypt * operation. * @param[in] ctx A context passed as an argument to the crypto callback * every invocation. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status * */ bool mongocrypt_setopt_aes_256_ctr(mongocrypt_t *crypt, mongocrypt_crypto_fn aes_256_ctr_encrypt, mongocrypt_crypto_fn aes_256_ctr_decrypt, void *ctx); /** * Set an AES256-ECB crypto hook for the AES256-CTR operations. If CTR hook was * configured using @ref mongocrypt_setopt_aes_256_ctr, ECB hook will be * ignored. * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] aes_256_ecb_encrypt The crypto callback function for encrypt * operation. * @param[in] ctx A context passed as an argument to the crypto callback * every invocation. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status * */ bool mongocrypt_setopt_aes_256_ecb(mongocrypt_t *crypt, mongocrypt_crypto_fn aes_256_ecb_encrypt, void *ctx); /** * Set a crypto hook for the RSASSA-PKCS1-v1_5 algorithm with a SHA-256 hash. * * See: https://tools.ietf.org/html/rfc3447#section-8.2 * * Note: this function has the wrong name. It should be: * mongocrypt_setopt_crypto_hook_sign_rsassa_pkcs1_v1_5 * * @param[in] crypt The @ref mongocrypt_t object. * @param[in] sign_rsaes_pkcs1_v1_5 The crypto callback function. * @param[in] sign_ctx A context passed as an argument to the crypto callback * every invocation. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status * */ bool mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(mongocrypt_t *crypt, mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5, void *sign_ctx); /** * @brief Opt-into skipping query analysis. * * If opted in: * - The crypt_shared library will not attempt to be loaded. * - A mongocrypt_ctx_t will never enter the MONGOCRYPT_CTX_NEED_MARKINGS state. * * @param[in] crypt The @ref mongocrypt_t object to update */ void mongocrypt_setopt_bypass_query_analysis(mongocrypt_t *crypt); /** * Set the contention factor used for explicit encryption. * The contention factor is only used for indexed Queryable Encryption. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] contention_factor * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status. */ bool mongocrypt_ctx_setopt_contention_factor(mongocrypt_ctx_t *ctx, int64_t contention_factor); /** * Set the index key id to use for explicit Queryable Encryption. * * If the index key id not set, the key id from @ref * mongocrypt_ctx_setopt_key_id is used. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] key_id The binary corresponding to the _id (a UUID) of the data * key to use from the key vault collection. Note, the UUID must be encoded with * RFC-4122 byte order. The viewed data is copied. It is valid to destroy * @p key_id with @ref mongocrypt_binary_destroy immediately after. * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_index_key_id(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *key_id); /** * Set the query type to use for explicit Queryable Encryption. * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] query_type The query type string * @param[in] len The length of query_type, or -1 for automatic * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_type, int len); /** * Set options for explicit encryption with the "rangePreview" algorithm. * NOTE: The RangePreview algorithm is experimental only. It is not intended for * public use. * * @p opts is a BSON document of the form: * { * "min": Optional, * "max": Optional, * "sparsity": Int64, * "precision": Optional * } * * @param[in] ctx The @ref mongocrypt_ctx_t object. * @param[in] opts BSON. * @pre @p ctx has not been initialized. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_ctx_status */ bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *opts); /// String constants for setopt_query_type // NOTE: The RangePreview algorithm is experimental only. It is not intended for // public use. """) if PY3: def _to_string(cdata): """Decode a cdata c-string to a Python str.""" return ffi.string(cdata).decode() else: def _to_string(cdata): """Decode a cdata c-string to a Python str.""" return ffi.string(cdata) def libmongocrypt_version(): """Returns the version of libmongocrypt.""" return _to_string(lib.mongocrypt_version(ffi.NULL)) # Use the PYMONGOCRYPT_LIB environment variable to load a custom libmongocrypt # build without relying on platform specific library path environment # variables, like LD_LIBRARY_PATH. For example: # export PYMONGOCRYPT_LIB='/path/to/libmongocrypt.so' # If the PYMONGOCRYPT_LIB is not set then load the embedded library and # fallback to the relying on a system installed library. _base = os.path.dirname(os.path.realpath(__file__)) if sys.platform == 'win32': _path = os.path.join(_base, 'mongocrypt.dll') elif sys.platform == 'darwin': _path = os.path.join(_base, 'libmongocrypt.dylib') else: _path = os.path.join(_base, 'libmongocrypt.so') class _Library(object): """Helper class for delaying errors that would usually be raised at import time until the library is actually used.""" def __init__(self, error): self._error = error def __getattr__(self, name): raise self._error _PYMONGOCRYPT_LIB = os.environ.get('PYMONGOCRYPT_LIB') try: if _PYMONGOCRYPT_LIB: lib = ffi.dlopen(_PYMONGOCRYPT_LIB) else: try: lib = ffi.dlopen(_path) except OSError as exc: # Fallback to libmongocrypt installed on the system. lib = ffi.dlopen('mongocrypt') except OSError as exc: # dlopen raises OSError when the library cannot be found. # Delay the error until the library is actually used. lib = _Library(exc) else: # Check the libmongocrypt version when the library is found. _limongocrypt_version = _parse_version(libmongocrypt_version()) if _limongocrypt_version < _parse_version(_MIN_LIBMONGOCRYPT_VERSION): exc = RuntimeError( "Expected libmongocrypt version %s or greater, found %s" % ( _MIN_LIBMONGOCRYPT_VERSION, libmongocrypt_version())) lib = _Library(exc) libmongocrypt-1.8.4/bindings/python/pymongocrypt/compat.py000066400000000000000000000020031454530651600241450ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utility functions and definitions for Python compatibility.""" import sys PY3 = sys.version_info[0] == 3 if PY3: from abc import ABC unicode_type = str else: from abc import ABCMeta as _ABCMeta ABC = _ABCMeta('ABC', (object,), {}) unicode_type = unicode def str_to_bytes(string): """Convert a str (or unicode) to bytes.""" if isinstance(string, bytes): return string return string.encode('utf-8') libmongocrypt-1.8.4/bindings/python/pymongocrypt/credentials.py000066400000000000000000000117771454530651600252010ustar00rootroot00000000000000# Copyright 2022-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os from collections import namedtuple from datetime import datetime, timedelta try: from pymongo_auth_aws.auth import aws_temp_credentials _HAVE_AUTH_AWS = True except ImportError: _HAVE_AUTH_AWS = False from pymongocrypt.errors import MongoCryptError import requests _azure_creds = namedtuple("_azure_creds", ["access_token", "expires_in"]) _azure_creds_cache = None def _get_gcp_credentials(): """Get on-demand GCP credentials""" metadata_host = os.getenv("GCE_METADATA_HOST") or "metadata.google.internal" url = "http://%s/computeMetadata/v1/instance/service-accounts/default/token" % metadata_host headers = {"Metadata-Flavor": "Google"} try: response = requests.get(url, headers=headers) except Exception as e: msg = "unable to retrieve GCP credentials: %s" % e raise MongoCryptError(msg) if response.status_code != 200: msg = "Unable to retrieve GCP credentials: expected StatusCode 200, got StatusCode: %s. Response body:\n%s" % (response.status_code, response.content) raise MongoCryptError(msg) try: data = response.json() except Exception: raise MongoCryptError("unable to retrieve GCP credentials: error reading response body\n%s" % response.content) if not data.get("access_token"): msg = "unable to retrieve GCP credentials: got unexpected empty accessToken from GCP Metadata Server. Response body: %s" % response.content raise MongoCryptError(msg) return {'accessToken': data['access_token']} def _get_azure_credentials(): """Get on-demand Azure credentials""" global _azure_creds_cache # Credentials are considered expired when: Expiration - now < 1 mins. creds = _azure_creds_cache if creds: if creds.expires_in - datetime.utcnow() < timedelta(seconds=60): _azure_creds_cache = None else: return { 'accessToken': creds.access_token } url = "http://169.254.169.254/metadata/identity/oauth2/token" url += "?api-version=2018-02-01" url += "&resource=https://vault.azure.net" headers = { "Metadata": "true", "Accept": "application/json" } try: response = requests.get(url, headers=headers) except Exception as e: msg = "Failed to acquire IMDS access token: %s" % e raise MongoCryptError(msg) if response.status_code != 200: msg = "Failed to acquire IMDS access token." raise MongoCryptError(msg) try: data = response.json() except Exception: raise MongoCryptError("Azure IMDS response must be in JSON format.") for key in ["access_token", "expires_in"]: if not data.get(key): msg = "Azure IMDS response must contain %s, but was %s." msg = msg % (key, response.content) raise MongoCryptError(msg) try: expires_in = int(data["expires_in"]) except ValueError: raise MongoCryptError('Azure IMDS response must contain "expires_in" integer, but was %s.' % response.content) expiration_time = datetime.utcnow() + timedelta(seconds=expires_in) _azure_creds_cache = _azure_creds(data['access_token'], expiration_time) return { 'accessToken': data['access_token'] } def _ask_for_kms_credentials(kms_providers): """Get on-demand kms credentials. This is a separate function so it can be overridden in unit tests.""" global _azure_creds_cache on_demand_aws = 'aws' in kms_providers and not len(kms_providers['aws']) on_demand_gcp = 'gcp' in kms_providers and not len(kms_providers['gcp']) on_demand_azure = 'azure' in kms_providers and not len(kms_providers['azure']) if not any([on_demand_aws, on_demand_gcp, on_demand_azure]): return {} creds = {} if on_demand_aws: if not _HAVE_AUTH_AWS: raise RuntimeError( "On-demand AWS credentials require pymongo-auth-aws: " "install with: python -m pip install 'pymongo[aws]'" ) aws_creds = aws_temp_credentials() creds_dict = {"accessKeyId": aws_creds.username, "secretAccessKey": aws_creds.password} if aws_creds.token: creds_dict["sessionToken"] = aws_creds.token creds['aws'] = creds_dict if on_demand_gcp: creds['gcp'] = _get_gcp_credentials() if on_demand_azure: try: creds['azure'] = _get_azure_credentials() except Exception: _azure_creds_cache = None raise return creds libmongocrypt-1.8.4/bindings/python/pymongocrypt/crypto.py000066400000000000000000000140151454530651600242100ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Internal crypto callbacks for libmongocrypt.""" import os import traceback from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.hashes import Hash, SHA256, SHA512 from cryptography.hazmat.primitives.hmac import HMAC from cryptography.hazmat.primitives.serialization import load_der_private_key from pymongocrypt.binary import _to_bytes, _write_bytes from pymongocrypt.binding import ffi, lib from pymongocrypt.compat import str_to_bytes def _callback_error_handler(exception, exc_value, tb): """Set the mongocrypt_status_t on error.""" # From cffi docs: "First check if traceback is not None (it is None e.g. # if the whole function ran successfully but there was an error converting # the value returned: this occurs after the call)." if tb is not None: status = tb.tb_frame.f_locals['status'] msg = str_to_bytes(''.join(traceback.format_exception( exception, exc_value, tb))) lib.mongocrypt_status_set( status, lib.MONGOCRYPT_STATUS_ERROR_CLIENT, 1, msg, -1) return False def _aes_256_encrypt(key, mode, input, output, bytes_written): cipher = Cipher(algorithms.AES(_to_bytes(key)), mode, backend=default_backend()) encryptor = cipher.encryptor() data = encryptor.update(_to_bytes(input)) + encryptor.finalize() _write_bytes(output, data) bytes_written[0] = len(data) def _aes_256_decrypt(key, mode, input, output, bytes_written): cipher = Cipher(algorithms.AES(_to_bytes(key)), mode, backend=default_backend()) decryptor = cipher.decryptor() data = decryptor.update(_to_bytes(input)) + decryptor.finalize() _write_bytes(output, data) bytes_written[0] = len(data) @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", onerror=_callback_error_handler) def aes_256_cbc_encrypt(ctx, key, iv, input, output, bytes_written, status): # Note that libmongocrypt pads the input before calling this method. _aes_256_encrypt(key, modes.CBC(_to_bytes(iv)), input, output, bytes_written) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", onerror=_callback_error_handler) def aes_256_cbc_decrypt(ctx, key, iv, input, output, bytes_written, status): # Note that libmongocrypt pads the input before calling this method. _aes_256_decrypt(key, modes.CBC(_to_bytes(iv)), input, output, bytes_written) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", onerror=_callback_error_handler) def aes_256_ctr_encrypt(ctx, key, iv, input, output, bytes_written, status): _aes_256_encrypt(key, modes.CTR(_to_bytes(iv)), input, output, bytes_written) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", onerror=_callback_error_handler) def aes_256_ctr_decrypt(ctx, key, iv, input, output, bytes_written, status): _aes_256_decrypt(key, modes.CTR(_to_bytes(iv)), input, output, bytes_written) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_binary_t *, mongocrypt_status_t *)", onerror=_callback_error_handler) def hmac_sha_256(ctx, key, input, output, status): h = HMAC(_to_bytes(key), SHA256(), backend=default_backend()) h.update(_to_bytes(input)) data = h.finalize() _write_bytes(output, data) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_binary_t *, mongocrypt_status_t *)", onerror=_callback_error_handler) def hmac_sha_512(ctx, key, input, output, status): h = HMAC(_to_bytes(key), SHA512(), backend=default_backend()) h.update(_to_bytes(input)) data = h.finalize() _write_bytes(output, data) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_status_t *)", onerror=_callback_error_handler) def sha_256(ctx, input, output, status): digest = Hash(SHA256(), backend=default_backend()) digest.update(_to_bytes(input)) data = digest.finalize() _write_bytes(output, data) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, uint32_t, mongocrypt_status_t *)", onerror=_callback_error_handler) def secure_random(ctx, output, count, status): data = os.urandom(int(count)) _write_bytes(output, data) return True @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_binary_t *, mongocrypt_status_t *)", onerror=_callback_error_handler) def sign_rsaes_pkcs1_v1_5(ctx, key, input, output, status): rsa_private_key = load_der_private_key( _to_bytes(key), password=None, backend=default_backend()) signature = rsa_private_key.sign( _to_bytes(input), padding=padding.PKCS1v15(), algorithm=SHA256()) _write_bytes(output, signature) return True libmongocrypt-1.8.4/bindings/python/pymongocrypt/errors.py000066400000000000000000000025611454530651600242070ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from pymongocrypt.binding import ffi, lib, _to_string class MongoCryptError(Exception): def __init__(self, msg, code=-1): """Top level Exception for all MongoCrypt errors. :Parameters: - `msg`: An error message. - `code`: The mongocrypt_status_t code. """ super(MongoCryptError, self).__init__(msg) self.code = code @classmethod def from_status(cls, status): """Constructs an error from a mongocrypt_status_t. :Parameters: - `status`: A CFFI mongocrypt_status_t. """ if lib.mongocrypt_status_ok(status): raise ValueError("status must not be ok") msg = _to_string(lib.mongocrypt_status_message(status, ffi.NULL)) return cls(msg, lib.mongocrypt_status_code(status)) libmongocrypt-1.8.4/bindings/python/pymongocrypt/explicit_encrypter.py000066400000000000000000000255651454530651600266200ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from pymongocrypt.mongocrypt import MongoCrypt from pymongocrypt.state_machine import run_state_machine class ExplicitEncryptOpts(object): def __init__(self, algorithm, key_id=None, key_alt_name=None, query_type=None, contention_factor=None, range_opts=None, is_expression=False): """Options for explicit encryption. :Parameters: - `algorithm` (str): The algorithm to use. - `key_id`: The data key _id. - `key_alt_name` (bytes): Identifies a key vault document by 'keyAltName'. Must be BSON encoded document in the form: { "keyAltName" : (BSON UTF8 value) } - `query_type` (str): The query type to execute. - `contention_factor` (int): The contention factor to use when the algorithm is "Indexed". - `range_opts` (bytes): Options for explicit encryption with the "rangePreview" algorithm encoded as a BSON document. - `is_expression` (boolean): True if this is an encryptExpression() context. Defaults to False. .. versionchanged:: 1.3 Added the `query_type` and `contention_factor` parameters. .. versionchanged:: 1.5 Added the `range_opts` and `is_expression` parameters. """ self.algorithm = algorithm self.key_id = key_id self.key_alt_name = key_alt_name if query_type is not None: if not isinstance(query_type, str): raise TypeError( 'query_type must be str or None, not: %r' % (type(query_type),)) self.query_type = query_type if contention_factor is not None and not isinstance(contention_factor, int): raise TypeError( 'contention_factor must be an int or None, not: %r' % (type(contention_factor),)) self.contention_factor = contention_factor if range_opts is not None and not isinstance(range_opts, bytes): raise TypeError( 'range_opts must be an bytes or None, not: %r' % (type(range_opts),)) self.range_opts = range_opts self.is_expression = is_expression class DataKeyOpts(object): def __init__(self, master_key=None, key_alt_names=None, key_material=None): """Options for creating encryption keys. :Parameters: - `master_key`: Identifies a KMS-specific key used to encrypt the new data key. If the kmsProvider is "local" the `master_key` is not applicable and may be omitted. If the `kms_provider` is "aws" it is required and has the following fields:: - `region` (string): Required. The AWS region, e.g. "us-east-1". - `key` (string): Required. The Amazon Resource Name (ARN) to the AWS customer. - `endpoint` (string): Optional. An alternate host to send KMS requests to. May include port number, e.g. "kms.us-east-1.amazonaws.com:443". If the `kms_provider` is "azure" it is required and has the following fields:: - `keyVaultEndpoint` (string): Required. Host with optional port, e.g. "example.vault.azure.net". - `keyName` (string): Required. Key name in the key vault. - `keyVersion` (string): Optional. Version of the key to use. If the `kms_provider` is "gcp" it is required and has the following fields:: - `projectId` (string): Required. The Google cloud project ID. - `location` (string): Required. The GCP location, e.g. "us-east1". - `keyRing` (string): Required. Name of the key ring that contains the key to use. - `keyName` (string): Required. Name of the key to use. - `keyVersion` (string): Optional. Version of the key to use. - `endpoint` (string): Optional. Host with optional port. Defaults to "cloudkms.googleapis.com". If the `kms_provider` is "kmip" it is optional and has the following fields:: - `keyId` (string): Optional. `keyId` is the KMIP Unique Identifier to a 96 byte KMIP Secret Data managed object. If keyId is omitted, the driver creates a random 96 byte KMIP Secret Data managed object. - `endpoint` (string): Optional. Host with optional port, e.g. "example.vault.azure.net:". - `key_alt_names`: An optional list of bytes suitable to be passed to mongocrypt_ctx_setopt_key_alt_name. Each element must be BSON encoded document in the form: { "keyAltName" : (BSON UTF8 value) } - `key_material`: An optional binary value of 96 bytes to use as custom key material for the data key being created. If ``key_material`` is given, the custom key material is used for encrypting and decrypting data. Otherwise, the key material for the new data key is generated from a cryptographically secure random device. """ self.master_key = master_key self.key_alt_names = key_alt_names self.key_material = key_material class ExplicitEncrypter(object): def __init__(self, callback, mongo_crypt_opts): """Encrypts and decrypts BSON values. This class is used by a driver to support explicit encryption and decryption of individual fields in a BSON document. :Parameters: - `callback`: A :class:`MongoCryptCallback`. - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. """ self.callback = callback if mongo_crypt_opts.schema_map is not None: raise ValueError("mongo_crypt_opts.schema_map must be None") self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) def create_data_key(self, kms_provider, master_key=None, key_alt_names=None, key_material=None): """Creates a data key used for explicit encryption. :Parameters: - `kms_provider`: The KMS provider to use. Supported values are "aws", "azure", "gcp", "kmip", and "local". - `master_key`: See class:`DataKeyOpts`. - `key_alt_names` (optional): An optional list of string alternate names used to reference a key. If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by ``_id``. - `key_material`: (optional) See class:`DataKeyOpts`. :Returns: The _id of the created data key document. """ # CDRIVER-3275 each key_alt_name needs to be wrapped in a bson # document. encoded_names = [] if key_alt_names is not None: for name in key_alt_names: encoded_names.append( self.callback.bson_encode({'keyAltName': name})) if key_material is not None: key_material = self.callback.bson_encode({'keyMaterial': key_material}) opts = DataKeyOpts(master_key, encoded_names, key_material) with self.mongocrypt.data_key_context(kms_provider, opts) as ctx: key = run_state_machine(ctx, self.callback) return self.callback.insert_data_key(key) def rewrap_many_data_key(self, filter, provider=None, master_key=None): """Decrypts and encrypts all matching data keys with a possibly new `master_key` value. :Parameters: - `filter`: A document used to filter the data keys. - `provider`: (optional) The name of a different kms provider. - `master_key`: Optional document for the given provider. :Returns: A binary document with the rewrap data. """ with self.mongocrypt.rewrap_many_data_key_context(filter, provider, master_key) as ctx: return run_state_machine(ctx, self.callback) def encrypt(self, value, algorithm, key_id=None, key_alt_name=None, query_type=None, contention_factor=None, range_opts=None, is_expression=False): """Encrypts a BSON value. Note that exactly one of ``key_id`` or ``key_alt_name`` must be provided. :Parameters: - `value` (bytes): The BSON value to encrypt. - `algorithm` (string): The encryption algorithm to use. See :class:`Algorithm` for some valid options. - `key_id` (bytes): The bytes of the binary subtype 4 ``_id`` data key. For example, ``uuid.bytes`` or ``bytes(bson_binary)``. - `key_alt_name` (string): Identifies a key vault document by 'keyAltName'. - `query_type` (str): The query type to execute. - `contention_factor` (int): The contention factor to use when the algorithm is "Indexed". - `range_opts` (bytes): Options for explicit encryption with the "rangePreview" algorithm encoded as a BSON document. - `is_expression` (boolean): True if this is an encryptExpression() context. Defaults to False. :Returns: The encrypted BSON value. .. versionchanged:: 1.3 Added the `query_type` and `contention_factor` parameters. .. versionchanged:: 1.5 Added the `range_opts` and `is_expression` parameters. """ # CDRIVER-3275 key_alt_name needs to be wrapped in a bson document. if key_alt_name is not None: key_alt_name = self.callback.bson_encode( {'keyAltName': key_alt_name}) opts = ExplicitEncryptOpts( algorithm, key_id, key_alt_name, query_type, contention_factor, range_opts, is_expression) with self.mongocrypt.explicit_encryption_context(value, opts) as ctx: return run_state_machine(ctx, self.callback) def decrypt(self, value): """Decrypts a BSON value. :Parameters: - `value`: The encoded document to decrypt, which must be in the form { "v" : encrypted BSON value }}. :Returns: The decrypted BSON value. """ with self.mongocrypt.explicit_decryption_context(value) as ctx: return run_state_machine(ctx, self.callback) def close(self): """Cleanup resources.""" self.mongocrypt.close() libmongocrypt-1.8.4/bindings/python/pymongocrypt/mongocrypt.py000066400000000000000000000764031454530651600251020ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import copy from pymongocrypt.binary import (MongoCryptBinaryIn, MongoCryptBinaryOut) from pymongocrypt.binding import ffi, lib, _to_string from pymongocrypt.compat import str_to_bytes, unicode_type from pymongocrypt.credentials import _ask_for_kms_credentials from pymongocrypt.errors import MongoCryptError from pymongocrypt.state_machine import MongoCryptCallback from pymongocrypt.crypto import (aes_256_cbc_encrypt, aes_256_cbc_decrypt, aes_256_ctr_decrypt, aes_256_ctr_encrypt, hmac_sha_256, hmac_sha_512, sha_256, secure_random, sign_rsaes_pkcs1_v1_5) class MongoCryptOptions(object): def __init__(self, kms_providers, schema_map=None, encrypted_fields_map=None, bypass_query_analysis=False, crypt_shared_lib_path=None, crypt_shared_lib_required=False, bypass_encryption=False): """Options for :class:`MongoCrypt`. :Parameters: - `kms_providers`: Map of KMS provider options. The kms_providers map values differ by provider: - `aws`: Map with "accessKeyId" and "secretAccessKey" as strings, and optionally a "sessionToken" for temporary credentials. - `azure`: Map with "clientId" and "clientSecret" as strings. - `gcp`: Map with "email" as a string and "privateKey" as a byte array or a base64-encoded string. - `kmip`: Map with "endpoint" as a string. - `local`: Map with "key" as a 96-byte array or the equivalent base64-encoded string. - `schema_map`: Optional map of collection namespace ("db.coll") to JSON Schema. By default, a collection's JSONSchema is periodically polled with the listCollections command. But a JSONSchema may be specified locally with the schemaMap option. Supplying a `schema_map` provides more security than relying on JSON Schemas obtained from the server. It protects against a malicious server advertising a false JSON Schema, which could trick the client into sending unencrypted data that should be encrypted. Schemas supplied in the schemaMap only apply to configuring automatic encryption for client side encryption. Other validation rules in the JSON schema will not be enforced by the driver and will result in an error. - `encrypted_fields_map`: Optional map encoded to BSON `bytes`. - `bypass_query_analysis`: If ``True``, disable automatic analysis of outgoing commands. Set `bypass_query_analysis` to use explicit encryption on indexed fields without the MongoDB Enterprise Advanced licensed crypt_shared library. - `crypt_shared_lib_path`: Optional string path to the crypt_shared library. - `crypt_shared_lib_required`: Whether to require a crypt_shared library. - `bypass_encryption`: Whether to bypass encryption. .. versionadded:: 1.3 ``crypt_shared_lib_path``, ``crypt_shared_lib_path``, ``bypass_encryption`` parameters. .. versionadded:: 1.1 Support for "azure" and "gcp" kms_providers. Support for temporary AWS credentials via "sessionToken". .. versionchanged:: 1.1 For kmsProvider "local", the "key" field can now be specified as either a 96-byte array or the equivalent base64-encoded string. """ if not isinstance(kms_providers, dict): raise ValueError('kms_providers must be a dict') if not kms_providers: raise ValueError('at least one KMS provider must be configured') if 'aws' in kms_providers: aws = kms_providers["aws"] if not isinstance(aws, dict): raise ValueError("kms_providers['aws'] must be a dict") if len(aws): if "accessKeyId" not in aws or "secretAccessKey" not in aws: raise ValueError("kms_providers['aws'] must contain " "'accessKeyId' and 'secretAccessKey'") if 'azure' in kms_providers: azure = kms_providers["azure"] if not isinstance(azure, dict): raise ValueError("kms_providers['azure'] must be a dict") if len(azure): if 'clientId' not in azure or 'clientSecret' not in azure: raise ValueError("kms_providers['azure'] must contain " "'clientId' and 'clientSecret'") if 'gcp' in kms_providers: gcp = kms_providers['gcp'] if not isinstance(gcp, dict): raise ValueError("kms_providers['gcp'] must be a dict") if len(gcp): if 'email' not in gcp or 'privateKey' not in gcp: raise ValueError("kms_providers['gcp'] must contain " "'email' and 'privateKey'") if not isinstance(kms_providers['gcp']['privateKey'], (bytes, unicode_type)): raise TypeError("kms_providers['gcp']['privateKey'] must " "be an instance of bytes or str") if 'kmip' in kms_providers: kmip = kms_providers['kmip'] if not isinstance(kmip, dict): raise ValueError("kms_providers['kmip'] must be a dict") if 'endpoint' not in kmip: raise ValueError("kms_providers['kmip'] must contain " "'endpoint'") if not isinstance(kms_providers['kmip']['endpoint'], (str, unicode_type)): raise TypeError("kms_providers['kmip']['endpoint'] must " "be an instance of str") if 'local' in kms_providers: local = kms_providers['local'] if not isinstance(local, dict): raise ValueError("kms_providers['local'] must be a dict") if 'key' not in local: raise ValueError("kms_providers['local'] must contain 'key'") if not isinstance(kms_providers['local']['key'], (bytes, unicode_type)): raise TypeError("kms_providers['local']['key'] must be an " "instance of bytes or str") if schema_map is not None and not isinstance(schema_map, bytes): raise TypeError("schema_map must be bytes or None") if encrypted_fields_map is not None and not isinstance(encrypted_fields_map, bytes): raise TypeError("encrypted_fields_map must be bytes or None") self.kms_providers = kms_providers self.schema_map = schema_map self.encrypted_fields_map = encrypted_fields_map self.bypass_query_analysis = bypass_query_analysis self.crypt_shared_lib_path = crypt_shared_lib_path self.crypt_shared_lib_required = crypt_shared_lib_required self.bypass_encryption = bypass_encryption class MongoCrypt(object): def __init__(self, options, callback): """Abstracts libmongocrypt's mongocrypt_t type. :Parameters: - `options`: A :class:`MongoCryptOptions`. - `callback`: A :class:`MongoCryptCallback`. """ self.__opts = options # type: MongoCryptOptions self.__callback = callback self.__crypt = None if not isinstance(options, MongoCryptOptions): raise TypeError("options must be a MongoCryptOptions") if not isinstance(callback, MongoCryptCallback): raise TypeError("callback must be a MongoCryptCallback") self.__crypt = lib.mongocrypt_new() if self.__crypt == ffi.NULL: raise MongoCryptError("unable to create new mongocrypt object") try: self.__init() except Exception: # Destroy the mongocrypt object on error. self.close() raise def __init(self): """Internal init helper.""" kms_providers = self.__opts.kms_providers with MongoCryptBinaryIn( self.__callback.bson_encode(kms_providers)) as kmsopt: if not lib.mongocrypt_setopt_kms_providers( self.__crypt, kmsopt.bin): self.__raise_from_status() schema_map = self.__opts.schema_map if schema_map is not None: with MongoCryptBinaryIn(schema_map) as binary_schema_map: if not lib.mongocrypt_setopt_schema_map( self.__crypt, binary_schema_map.bin): self.__raise_from_status() encrypted_fields_map = self.__opts.encrypted_fields_map if encrypted_fields_map is not None: with MongoCryptBinaryIn(encrypted_fields_map) as binary_encrypted_fields_map: if not lib.mongocrypt_setopt_encrypted_field_config_map( self.__crypt, binary_encrypted_fields_map.bin): self.__raise_from_status() if self.__opts.bypass_query_analysis: lib.mongocrypt_setopt_bypass_query_analysis(self.__crypt) if not lib.mongocrypt_setopt_crypto_hooks( self.__crypt, aes_256_cbc_encrypt, aes_256_cbc_decrypt, secure_random, hmac_sha_512, hmac_sha_256, sha_256, ffi.NULL): self.__raise_from_status() if not lib.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( self.__crypt, sign_rsaes_pkcs1_v1_5, ffi.NULL): self.__raise_from_status() if not lib.mongocrypt_setopt_aes_256_ctr( self.__crypt, aes_256_ctr_encrypt, aes_256_ctr_decrypt, ffi.NULL): self.__raise_from_status() if self.__opts.crypt_shared_lib_path is not None: lib.mongocrypt_setopt_set_crypt_shared_lib_path_override( self.__crypt, self.__opts.crypt_shared_lib_path.encode("utf-8")) if not self.__opts.bypass_encryption: lib.mongocrypt_setopt_append_crypt_shared_lib_search_path(self.__crypt, b"$SYSTEM") on_demand_aws = 'aws' in kms_providers and not len(kms_providers['aws']) on_demand_gcp = 'gcp' in kms_providers and not len(kms_providers['gcp']) on_demand_azure = 'azure' in kms_providers and not len(kms_providers['azure']) if any([on_demand_aws, on_demand_gcp, on_demand_azure]): lib.mongocrypt_setopt_use_need_kms_credentials_state(self.__crypt) if not lib.mongocrypt_init(self.__crypt): self.__raise_from_status() if self.__opts.crypt_shared_lib_required and self.crypt_shared_lib_version is None: raise MongoCryptError( "crypt_shared_lib_required=True but the crypt_shared library could not be loaded " "from crypt_shared_lib_path={}".format( self.__opts.crypt_shared_lib_path) + " or the operating system's dynamic library search path") def __raise_from_status(self): status = lib.mongocrypt_status_new() try: lib.mongocrypt_status(self.__crypt, status) exc = MongoCryptError.from_status(status) finally: lib.mongocrypt_status_destroy(status) raise exc @property def crypt_shared_lib_version(self): ver = lib.mongocrypt_crypt_shared_lib_version_string(self.__crypt, ffi.NULL) if ver == ffi.NULL: return None return ver def close(self): """Cleanup resources.""" if self.__crypt is None: return # Since close is called by __del__, we need to be sure to guard # against the case where global variables are set to None at # interpreter shutdown, see PYTHON-3530. if lib is not None: lib.mongocrypt_destroy(self.__crypt) self.__crypt = None def __del__(self): self.close() def _create_context(self): """Returns a new mongocrypt_ctx_t""" ctx = lib.mongocrypt_ctx_new(self.__crypt) if ctx == ffi.NULL: self.__raise_from_status() return ctx def encryption_context(self, database, command): """Creates a context to use for encryption. :Parameters: - `database`: The database name. - `command`: The encoded BSON command to encrypt. :Returns: A :class:`EncryptionContext`. """ return EncryptionContext(self._create_context(), self.__opts.kms_providers, database, command) def decryption_context(self, command): """Creates a context to use for decryption. :Parameters: - `command`: The encoded BSON command to decrypt. :Returns: A :class:`DecryptionContext`. """ return DecryptionContext(self._create_context(), self.__opts.kms_providers, command) def explicit_encryption_context(self, value, opts): """Creates a context to use for explicit encryption. :Parameters: - `value`: The encoded document to encrypt, which must be in the form { "v" : BSON value to encrypt }}. - `opts`: A :class:`ExplicitEncryptOpts`. :Returns: A :class:`ExplicitEncryptionContext`. """ return ExplicitEncryptionContext( self._create_context(), self.__opts.kms_providers, value, opts) def explicit_decryption_context(self, value): """Creates a context to use for explicit decryption. :Parameters: - `value`: The encoded document to decrypt, which must be in the form { "v" : encrypted BSON value }}. :Returns: A :class:`ExplicitDecryptionContext`. """ return ExplicitDecryptionContext(self._create_context(), self.__opts.kms_providers, value) def data_key_context(self, kms_provider, opts=None): """Creates a context to use for key generation. :Parameters: - `kms_provider`: The KMS provider. - `opts`: An optional class:`DataKeyOpts`. :Returns: A :class:`DataKeyContext`. """ return DataKeyContext(self._create_context(), self.__opts.kms_providers, kms_provider, opts, self.__callback) def rewrap_many_data_key_context(self, filter, provider, master_key): """Creates a context to use for rewrapping many data keys. :Parameters: - `filter`: A document used to filter the data keys. - `provider`: (optional) The name of a different kms provider. - `master_key`: Optional document for the given provider. MUST have the fields corresponding to the given provider as specified in master_key. master_key MUST NOT be given if it is not applicable for the given provider. :Returns: A :class:`RewrapManyDataKeyContext`. """ return RewrapManyDataKeyContext(self._create_context(), self.__opts.kms_providers, filter, provider, master_key, self.__callback) class MongoCryptContext(object): __slots__ = ("__ctx", "__kms_providers") def __init__(self, ctx, kms_providers): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: - `ctx`: A mongocrypt_ctx_t. This MongoCryptContext takes ownership of the underlying mongocrypt_ctx_t. - `kms_providers`: The KMS provider map. """ self.__ctx = ctx self.__kms_providers = kms_providers def _close(self): """Cleanup resources.""" if self.__ctx is None: return lib.mongocrypt_ctx_destroy(self.__ctx) self.__ctx = None def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self._close() @property def state(self): """The current state of the mongocrypt_ctx_t.""" return lib.mongocrypt_ctx_state(self.__ctx) def _raise_from_status(self): status = lib.mongocrypt_status_new() try: lib.mongocrypt_ctx_status(self.__ctx, status) exc = MongoCryptError.from_status(status) finally: lib.mongocrypt_status_destroy(status) raise exc def mongo_operation(self): """Returns the mongo operation to execute as bson bytes.""" with MongoCryptBinaryOut() as binary: if not lib.mongocrypt_ctx_mongo_op(self.__ctx, binary.bin): self._raise_from_status() return binary.to_bytes() def add_mongo_operation_result(self, document): """Adds the mongo operation's command response. :Parameters: - `document`: A raw BSON command response document. """ with MongoCryptBinaryIn(document) as binary: if not lib.mongocrypt_ctx_mongo_feed(self.__ctx, binary.bin): self._raise_from_status() def complete_mongo_operation(self): """Completes the mongo operation.""" if not lib.mongocrypt_ctx_mongo_done(self.__ctx): self._raise_from_status() def ask_for_kms_credentials(self): """Get on-demand kms credentials""" return _ask_for_kms_credentials(self.__kms_providers) def provide_kms_providers(self, providers): """Provide a map of KMS providers.""" with MongoCryptBinaryIn(providers) as binary: if not lib.mongocrypt_ctx_provide_kms_providers(self.__ctx, binary.bin): self._raise_from_status() def kms_contexts(self): """Yields the MongoCryptKmsContexts.""" ctx = lib.mongocrypt_ctx_next_kms_ctx(self.__ctx) while ctx != ffi.NULL: yield MongoCryptKmsContext(ctx) ctx = lib.mongocrypt_ctx_next_kms_ctx(self.__ctx) def complete_kms(self): """Indicates that all MongoCryptKmsContexts have been completed""" if not lib.mongocrypt_ctx_kms_done(self.__ctx): self._raise_from_status() def finish(self): """Returns the finished mongo operation as bson bytes.""" with MongoCryptBinaryOut() as binary: if not lib.mongocrypt_ctx_finalize(self.__ctx, binary.bin): self._raise_from_status() return binary.to_bytes() class EncryptionContext(MongoCryptContext): __slots__ = ("database",) def __init__(self, ctx, kms_providers, database, command): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: - `ctx`: A mongocrypt_ctx_t. This MongoCryptContext takes ownership of the underlying mongocrypt_ctx_t. - `kms_providers`: The KMS provider map. - `database`: Optional, the name of the database. - `command`: The BSON command to encrypt. """ super(EncryptionContext, self).__init__(ctx, kms_providers) self.database = database try: with MongoCryptBinaryIn(command) as binary: database = str_to_bytes(database) if not lib.mongocrypt_ctx_encrypt_init( ctx, database, len(database), binary.bin): self._raise_from_status() except Exception: # Destroy the context on error. self._close() raise class DecryptionContext(MongoCryptContext): __slots__ = () def __init__(self, ctx, kms_providers, command): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: - `ctx`: A mongocrypt_ctx_t. This MongoCryptContext takes ownership of the underlying mongocrypt_ctx_t. - `kms_providers`: The KMS provider map. - `command`: The encoded BSON command to decrypt. """ super(DecryptionContext, self).__init__(ctx, kms_providers) try: with MongoCryptBinaryIn(command) as binary: if not lib.mongocrypt_ctx_decrypt_init(ctx, binary.bin): self._raise_from_status() except Exception: # Destroy the context on error. self._close() raise class ExplicitEncryptionContext(MongoCryptContext): __slots__ = () def __init__(self, ctx, kms_providers, value, opts): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: - `ctx`: A mongocrypt_ctx_t. This MongoCryptContext takes ownership of the underlying mongocrypt_ctx_t. - `kms_providers`: The KMS provider map. - `value`: The encoded document to encrypt, which must be in the form { "v" : BSON value to encrypt }}. - `opts`: A :class:`ExplicitEncryptOpts`. """ super(ExplicitEncryptionContext, self).__init__(ctx, kms_providers) try: algorithm = str_to_bytes(opts.algorithm) if not lib.mongocrypt_ctx_setopt_algorithm(ctx, algorithm, -1): self._raise_from_status() if opts.key_id is not None: with MongoCryptBinaryIn(opts.key_id) as binary: if not lib.mongocrypt_ctx_setopt_key_id(ctx, binary.bin): self._raise_from_status() if opts.key_alt_name is not None: with MongoCryptBinaryIn(opts.key_alt_name) as binary: if not lib.mongocrypt_ctx_setopt_key_alt_name(ctx, binary.bin): self._raise_from_status() if opts.query_type is not None: qt = str_to_bytes(opts.query_type) if not lib.mongocrypt_ctx_setopt_query_type(ctx, qt, -1): self._raise_from_status() if opts.contention_factor is not None: if not lib.mongocrypt_ctx_setopt_contention_factor(ctx, opts.contention_factor): self._raise_from_status() if opts.range_opts is not None: with MongoCryptBinaryIn(opts.range_opts) as range_opts: if not lib.mongocrypt_ctx_setopt_algorithm_range(ctx, range_opts.bin): self._raise_from_status() with MongoCryptBinaryIn(value) as binary: if opts.is_expression: if not lib.mongocrypt_ctx_explicit_encrypt_expression_init(ctx, binary.bin): self._raise_from_status() else: if not lib.mongocrypt_ctx_explicit_encrypt_init(ctx, binary.bin): self._raise_from_status() except Exception: # Destroy the context on error. self._close() raise class ExplicitDecryptionContext(MongoCryptContext): __slots__ = () def __init__(self, ctx, kms_providers, value): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: - `ctx`: A mongocrypt_ctx_t. This MongoCryptContext takes ownership of the underlying mongocrypt_ctx_t. - `kms_providers`: The KMS provider map. - `value`: The encoded BSON value to decrypt. """ super(ExplicitDecryptionContext, self).__init__(ctx, kms_providers) try: with MongoCryptBinaryIn(value) as binary: if not lib.mongocrypt_ctx_explicit_decrypt_init(ctx, binary.bin): self._raise_from_status() except Exception: # Destroy the context on error. self._close() raise class DataKeyContext(MongoCryptContext): __slots__ = () def __init__(self, ctx, kms_providers, kms_provider, opts, callback): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: - `ctx`: A mongocrypt_ctx_t. This MongoCryptContext takes ownership of the underlying mongocrypt_ctx_t. - `kms_providers`: The KMS provider map. - `kms_provider`: The KMS provider. - `opts`: An optional class:`DataKeyOpts`. - `callback`: A :class:`MongoCryptCallback`. """ super(DataKeyContext, self).__init__(ctx, kms_providers) try: if kms_provider not in ['aws', 'gcp', 'azure', 'kmip', 'local']: raise ValueError('unknown kms_provider: %s' % (kms_provider,)) if opts is None or opts.master_key is None: if kms_provider in ['kmip', 'local']: master_key = {} else: raise ValueError( 'master_key is required for kms_provider: "%s"' % ( kms_provider,)) else: master_key = opts.master_key.copy() if kms_provider == 'aws': if ('region' not in master_key or 'key' not in master_key): raise ValueError( 'master_key must include "region" and "key" for ' 'kms_provider: "aws"') elif kms_provider == 'azure': if ('keyName' not in master_key or 'keyVaultEndpoint' not in master_key): raise ValueError( 'master key must include "keyName" and ' '"keyVaultEndpoint" for kms_provider: "azure"') elif kms_provider == 'gcp': if ('projectId' not in master_key or 'location' not in master_key or 'keyRing' not in master_key or 'keyName' not in master_key): raise ValueError( 'master key must include "projectId", "location",' '"keyRing", and "keyName" for kms_provider: "gcp"') master_key['provider'] = kms_provider with MongoCryptBinaryIn( callback.bson_encode(master_key)) as mkey: if not lib.mongocrypt_ctx_setopt_key_encryption_key( ctx, mkey.bin): self._raise_from_status() if opts.key_alt_names: for key_alt_name in opts.key_alt_names: with MongoCryptBinaryIn(key_alt_name) as binary: if not lib.mongocrypt_ctx_setopt_key_alt_name( ctx, binary.bin): self._raise_from_status() if opts.key_material: with MongoCryptBinaryIn(opts.key_material) as binary: if not lib.mongocrypt_ctx_setopt_key_material( ctx, binary.bin): self._raise_from_status() if not lib.mongocrypt_ctx_datakey_init(ctx): self._raise_from_status() except Exception: # Destroy the context on error. self._close() raise class MongoCryptKmsContext(object): __slots__ = ("__ctx",) def __init__(self, ctx): """Abstracts libmongocrypt's mongocrypt_kms_ctx_t type. :Parameters: - `ctx`: A mongocrypt_kms_ctx_t. """ self.__ctx = ctx def _close(self): """Clear the mongocrypt_kms_ctx_t.""" self.__ctx = None def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self._close() @property def endpoint(self): """The kms hostname to connect over TLS.""" p = ffi.new("char *[]", 1) try: if not lib.mongocrypt_kms_ctx_endpoint(self.__ctx, p): self.__raise_from_status() return _to_string(p[0]) finally: ffi.release(p) @property def message(self): """The HTTP request message to send to the given endpoint.""" with MongoCryptBinaryOut() as binary: if not lib.mongocrypt_kms_ctx_message(self.__ctx, binary.bin): self.__raise_from_status() return binary.to_bytes() @property def bytes_needed(self): """Indicates how many bytes to send to :meth:`feed`.""" return lib.mongocrypt_kms_ctx_bytes_needed(self.__ctx) @property def kms_provider(self): """The KMS provider identifier associated with this KMS request. :Returns: The KMS provider as a string, eg "aws", "azure", "gcp", or "kmip". .. versionadded:: 1.2 """ return _to_string( lib.mongocrypt_kms_ctx_get_kms_provider(self.__ctx, ffi.NULL)) def feed(self, data): """Feed bytes from the HTTP response. :Parameters: - `data`: The bytes of the HTTP response. Must not exceed :attr:`bytes_needed`. """ with MongoCryptBinaryIn(data) as binary: if not lib.mongocrypt_kms_ctx_feed(self.__ctx, binary.bin): self.__raise_from_status() def __raise_from_status(self): status = lib.mongocrypt_status_new() try: lib.mongocrypt_kms_ctx_status(self.__ctx, status) exc = MongoCryptError.from_status(status) finally: lib.mongocrypt_status_destroy(status) raise exc class RewrapManyDataKeyContext(MongoCryptContext): __slots__ = () def __init__(self, ctx, kms_providers, filter, provider, master_key, callback): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: - `ctx`: A mongocrypt_ctx_t. This MongoCryptContext takes ownership of the underlying mongocrypt_ctx_t. - `kms_providers`: The KMS provider map. - `filter`: The filter to use when finding data keys to rewrap in the key vault collection.. - `provider`: (optional) The name of a different kms provider. - `master_key`: Optional document for the given provider. - `callback`: A :class:`MongoCryptCallback`. """ super(RewrapManyDataKeyContext, self).__init__(ctx, kms_providers) key_encryption_key_bson = None if provider is not None: data = dict(provider=provider) if master_key: data.update(master_key) key_encryption_key_bson = callback.bson_encode(data) try: if key_encryption_key_bson: with MongoCryptBinaryIn(key_encryption_key_bson) as binary: if not lib.mongocrypt_ctx_setopt_key_encryption_key(ctx, binary.bin): self._raise_from_status() filter_bson = callback.bson_encode(filter) with MongoCryptBinaryIn(filter_bson) as binary: if not lib.mongocrypt_ctx_rewrap_many_datakey_init(ctx, binary.bin): self._raise_from_status() except Exception: # Destroy the context on error. self._close() raise libmongocrypt-1.8.4/bindings/python/pymongocrypt/state_machine.py000066400000000000000000000113621454530651600254760ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from abc import abstractmethod from pymongocrypt.binding import lib from pymongocrypt.compat import ABC from pymongocrypt.errors import MongoCryptError class MongoCryptCallback(ABC): """Callback ABC to perform I/O on behalf of libbmongocrypt.""" @abstractmethod def kms_request(self, kms_context): """Complete a KMS request. :Parameters: - `kms_context`: A :class:`MongoCryptKmsContext`. :Returns: None """ pass @abstractmethod def collection_info(self, database, filter): """Get the collection info for a namespace. The returned collection info is passed to libmongocrypt which reads the JSON schema. :Parameters: - `database`: The database on which to run listCollections. - `filter`: The filter to pass to listCollections. :Returns: The first document from the listCollections command response as BSON. """ pass @abstractmethod def mark_command(self, database, cmd): """Mark a command for encryption. :Parameters: - `database`: The database on which to run this command. - `cmd`: The BSON command to run. :Returns: The marked command response from mongocryptd. """ pass @abstractmethod def fetch_keys(self, filter): """Yields one or more keys from the key vault. :Parameters: - `filter`: The filter to pass to find. :Returns: A generator which yields the requested keys from the key vault. """ pass @abstractmethod def insert_data_key(self, data_key): """Insert a data key into the key vault. :Parameters: - `data_key`: The data key document to insert. :Returns: The _id of the inserted data key document. """ pass @abstractmethod def bson_encode(self, doc): """Encode a document to BSON. A document can be any mapping type (like :class:`dict`). :Parameters: - `doc`: mapping type representing a document :Returns: The encoded BSON bytes. """ pass @abstractmethod def close(self): """Release resources.""" pass def run_state_machine(ctx, callback): """Run the libmongocrypt state machine until completion. :Parameters: - `ctx`: A :class:`MongoCryptContext`. - `callback`: A :class:`MongoCryptCallback`. :Returns: The completed libmongocrypt operation. """ while True: state = ctx.state # Check for terminal states first. if state == lib.MONGOCRYPT_CTX_ERROR: ctx._raise_from_status() elif state == lib.MONGOCRYPT_CTX_READY: return ctx.finish() elif state == lib.MONGOCRYPT_CTX_DONE: return None if state == lib.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: list_colls_filter = ctx.mongo_operation() coll_info = callback.collection_info( ctx.database, list_colls_filter) if coll_info: ctx.add_mongo_operation_result(coll_info) ctx.complete_mongo_operation() elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: mongocryptd_cmd = ctx.mongo_operation() result = callback.mark_command(ctx.database, mongocryptd_cmd) ctx.add_mongo_operation_result(result) ctx.complete_mongo_operation() elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS: key_filter = ctx.mongo_operation() for key in callback.fetch_keys(key_filter): ctx.add_mongo_operation_result(key) ctx.complete_mongo_operation() elif state == lib.MONGOCRYPT_CTX_NEED_KMS: for kms_ctx in ctx.kms_contexts(): with kms_ctx: callback.kms_request(kms_ctx) ctx.complete_kms() elif state == lib.MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: creds = ctx.ask_for_kms_credentials() ctx.provide_kms_providers(callback.bson_encode(creds)) else: raise MongoCryptError('unknown state: %r' % (state,)) libmongocrypt-1.8.4/bindings/python/pymongocrypt/version.py000066400000000000000000000012071454530651600243540ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __version__ = '1.5.3.dev0' _MIN_LIBMONGOCRYPT_VERSION = '1.7.0' libmongocrypt-1.8.4/bindings/python/release.sh000077500000000000000000000074011454530651600215240ustar00rootroot00000000000000#!/bin/bash -ex # This script should be run on macOS and Cygwin on Windows. # On macOS it will create the following distributions: # pymongocrypt-.tar.gz # pymongocrypt--py2.py3-none-manylinux2010_x86_64.whl # pymongocrypt--py2.py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl # pymongocrypt--py2.py3-none-macosx_10_9_x86_64.whl # # On Windows it will create the following distribution: # pymongocrypt--py2.py3-none-win_amd64.whl set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail # The libmongocrypt git revision release to embed in our wheels. REVISION=$(git rev-list -n 1 1.7.3) # The libmongocrypt release branch. BRANCH="r1.7" MACOS_TARGET=${MACOS_TARGET:="macos"} if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin rm -rf venv37 virtualenv -p C:\\python\\Python37\\python.exe venv37 && . ./venv37/Scripts/activate # Build the Windows wheel. rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt-release/windows-test/${BRANCH}/${REVISION}/libmongocrypt.tar.gz mkdir libmongocrypt tar xzf libmongocrypt.tar.gz -C ./libmongocrypt NOCRYPTO_SO=libmongocrypt/nocrypto/bin/mongocrypt.dll chmod +x ${NOCRYPTO_SO} cp ${NOCRYPTO_SO} pymongocrypt/ rm -rf ./libmongocrypt libmongocrypt.tar.gz # Ensure updated deps. python -m pip install --upgrade pip setuptools wheel python setup.py bdist_wheel rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib ls dist elif [ "Darwin" = "$(uname -s)" ]; then # Build the mac wheel. PYTHON=${PYTHON:="/Library/Frameworks/Python.framework/Versions/3.10/bin/python3"} # Ensure updated deps. $PYTHON -m pip install --upgrade pip setuptools wheel rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib # Install the sdist. $PYTHON setup.py sdist curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt-release/${MACOS_TARGET}/${BRANCH}/${REVISION}/libmongocrypt.tar.gz mkdir libmongocrypt tar xzf libmongocrypt.tar.gz -C ./libmongocrypt NOCRYPTO_SO=libmongocrypt/nocrypto/lib/libmongocrypt.dylib chmod +x ${NOCRYPTO_SO} cp ${NOCRYPTO_SO} pymongocrypt/ rm -rf ./libmongocrypt libmongocrypt.tar.gz $PYTHON setup.py bdist_wheel rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib ls dist fi if [ $(command -v docker) ]; then # Build the manylinux2010 wheels. rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt-release/rhel-62-64-bit/${BRANCH}/${REVISION}/libmongocrypt.tar.gz mkdir libmongocrypt tar xzf libmongocrypt.tar.gz -C ./libmongocrypt NOCRYPTO_SO=libmongocrypt/nocrypto/lib64/libmongocrypt.so chmod +x ${NOCRYPTO_SO} cp ${NOCRYPTO_SO} pymongocrypt/ rm -rf ./libmongocrypt libmongocrypt.tar.gz # 2021-05-05-1ac6ef3 was the last release to generate pip < 20.3 compatible # wheels. After that auditwheel was upgraded to v4 which produces PEP 600 # manylinux_x_y wheels which requires pip >= 20.3. We use the older docker # image to support older pip versions. images=(quay.io/pypa/manylinux2010_x86_64:2021-05-05-1ac6ef3 \ quay.io/pypa/manylinux2010_x86_64) for image in "${images[@]}"; do docker pull $image docker run --rm -v `pwd`:/python $image /python/build-manylinux-wheel.sh done # Sudo is needed to remove the files created by docker. sudo rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib ls dist fi libmongocrypt-1.8.4/bindings/python/setup.py000066400000000000000000000065571454530651600212720ustar00rootroot00000000000000import os import sys from setuptools import setup, find_packages if sys.version_info[:3] < (3, 7): raise RuntimeError("pymongocrypt requires Python version >= 3.7") # Make our Windows and macOS wheels platform specific because we embed # libmongocrypt. On Linux we ship manylinux2010 wheels which cannot do this or # else auditwheel raises the following error: # RuntimeError: Invalid binary wheel, found the following shared # library/libraries in purelib folder: # libmongocrypt.so # The wheel has to be platlib compliant in order to be repaired by auditwheel. cmdclass = {} if sys.platform in ('win32', 'darwin'): try: from wheel.bdist_wheel import bdist_wheel as _bdist_wheel class bdist_wheel(_bdist_wheel): def finalize_options(self): _bdist_wheel.finalize_options(self) self.root_is_pure = False def get_tag(self): python, abi, plat = _bdist_wheel.get_tag(self) # Our python source is py3 compatible. python, abi = 'py3', 'none' return python, abi, plat cmdclass['bdist_wheel'] = bdist_wheel except ImportError: # Version of wheel is too old, use None to fail a bdist_wheel attempt. cmdclass['bdist_wheel'] = None with open('README.rst', 'rb') as f: LONG_DESCRIPTION = f.read().decode('utf8') # Single source the version. version_file = os.path.realpath(os.path.join( os.path.dirname(__file__), 'pymongocrypt', 'version.py')) version = {} with open(version_file) as fp: exec(fp.read(), version) setup( name="pymongocrypt", version=version['__version__'], description="Python bindings for libmongocrypt", long_description=LONG_DESCRIPTION, packages=find_packages(exclude=['test']), package_data={'pymongocrypt': ['*.dll', '*.so', '*.dylib']}, zip_safe=False, # Note cryptography is uncapped because it does not follow semver. install_requires=[ "cffi>=1.12.0,<2", "cryptography>=2.0", # cryptography 40 dropped support for PyPy <7.3.10. "cryptography<40;platform_python_implementation=='PyPy' and implementation_version<'7.3.10'", "requests<3.0.0" ], author="Shane Harvey", author_email="mongodb-user@googlegroups.com", url="https://github.com/mongodb/libmongocrypt/tree/master/bindings/python", keywords=["mongo", "mongodb", "pymongocrypt", "pymongo", "mongocrypt", "bson"], test_suite="test", license="Apache License, Version 2.0", python_requires=">=3.7", classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database"], cmdclass=cmdclass, ) libmongocrypt-1.8.4/bindings/python/strip_header.py000066400000000000000000000026551454530651600225760ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Generate a CFFI.cdef() string from a C header file Usage (on macOS):: python strip_header.py ../../src/mongocrypt.h | pbcopy """ import itertools import re import sys DROP_RE = re.compile(r'^\s*(#|MONGOCRYPT_EXPORT)') def strip_file(content): fold = content.replace('\\\n', ' ') all_lines = fold.split('\n') + [''] keep_lines = (line for line in all_lines if not DROP_RE.match(line)) fin = '' for line, peek in itertools.pairwise(keep_lines): if peek == '' and line == '': # Drop adjacent empty lines continue yield line fin = peek yield fin def strip(hdr): with open(hdr) as fp: out = strip_file(fp.read()) print('\n'.join(out)) if __name__ == "__main__": if len(sys.argv) != 2: raise Exception("Usage: strip_header.py header.h") strip(sys.argv[1]) libmongocrypt-1.8.4/bindings/python/test-requirements.txt000066400000000000000000000001041454530651600237770ustar00rootroot00000000000000pymongo[aws]>=4 cffi>=1.12.0,<2 cryptography>=2 requests_mock>=1.10 libmongocrypt-1.8.4/bindings/python/test/000077500000000000000000000000001454530651600205225ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/__init__.py000066400000000000000000000015131454530651600226330ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest sys.path[0:0] = [""] try: # Enable the fault handler to dump the traceback of each running thread # after a segfault. import faulthandler faulthandler.enable() except ImportError: pass from unittest import mock libmongocrypt-1.8.4/bindings/python/test/data/000077500000000000000000000000001454530651600214335ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/collection-info.json000066400000000000000000000020611454530651600254110ustar00rootroot00000000000000{ "type": "collection", "name": "test", "idIndex": { "ns": "test.test", "name": "_id_", "key": { "_id": { "$numberInt": "1" } }, "v": { "$numberInt": "2" } }, "options": { "validator": { "$jsonSchema": { "properties": { "ssn": { "encrypt": { "keyId": [ { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }libmongocrypt-1.8.4/bindings/python/test/data/command-reply.json000066400000000000000000000002361454530651600250760ustar00rootroot00000000000000{ "cursor": { "firstBatch": [ { "_id": 1, "ssn": "457-55-5462" } ], "id": 0, "ns": "test.test" }, "ok": 1 } libmongocrypt-1.8.4/bindings/python/test/data/command.json000066400000000000000000000001121454530651600237360ustar00rootroot00000000000000{ "find": "test", "filter": { "ssn": "457-55-5462" } }libmongocrypt-1.8.4/bindings/python/test/data/compact/000077500000000000000000000000001454530651600230615ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/compact/success/000077500000000000000000000000001454530651600245315ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/compact/success/cmd.json000066400000000000000000000000561454530651600261700ustar00rootroot00000000000000{ "compactStructuredEncryptionData": "test" } libmongocrypt-1.8.4/bindings/python/test/data/compact/success/encrypted-field-config-map.json000066400000000000000000000025011454530651600325160ustar00rootroot00000000000000{ "db.test": { "escCollection": "esc", "eccCollection": "ecc", "ecocCollection": "ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encrypted", "bsonType": "string", "queries": { "queryType": "equality", "contention": 0 } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "nested.encrypted", "bsonType": "string", "queries": { "queryType": "equality", "contention": 0 } }, { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEw==", "subType": "04" } }, "path": "nested.notindexed", "bsonType": "string" } ] } } libmongocrypt-1.8.4/bindings/python/test/data/compact/success/encrypted-payload.json000066400000000000000000000011001454530651600310400ustar00rootroot00000000000000{ "compactStructuredEncryptionData": "test", "compactionTokens": { "nested.notindexed": { "$binary": { "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", "subType": "00" } }, "nested.encrypted": { "$binary": { "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", "subType": "00" } }, "encrypted": { "$binary": { "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", "subType": "00" } } } }libmongocrypt-1.8.4/bindings/python/test/data/encrypted-command-reply.json000066400000000000000000000005251454530651600270720ustar00rootroot00000000000000{ "cursor" : { "firstBatch" : [ { "_id": 1, "ssn": { "$binary": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", "$type": "06" } } ], "id" : 0, "ns" : "test.test" }, "ok" : 1 }libmongocrypt-1.8.4/bindings/python/test/data/encrypted-command.json000066400000000000000000000004471454530651600257440ustar00rootroot00000000000000{ "find": "test", "filter": { "ssn": { "$eq": { "$binary": { "base64": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", "subType": "06" } } } } } libmongocrypt-1.8.4/bindings/python/test/data/encrypted-field-config-map.json000066400000000000000000000025371454530651600274310ustar00rootroot00000000000000{ "test.test": { "escCollection": "fle2.basic.esc", "eccCollection": "fle2.basic.ecc", "ecocCollection": "fle2.basic.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "KEY1+AAAAAAAAAAAAAAAAA==", "subType": "04" } }, "path": "firstName", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } } ] }, "test.test2": { "escCollection": "fle2.basic.esc", "eccCollection": "fle2.basic.ecc", "ecocCollection": "fle2.basic.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "KEY2+AAAAAAAAAAAAAAAAA==", "subType": "04" } }, "path": "firstName", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } } ] } }libmongocrypt-1.8.4/bindings/python/test/data/encrypted-value.json000066400000000000000000000002461454530651600254370ustar00rootroot00000000000000{ "v": { "$binary": "AWFhYWFhYWFhYWFhYWFhYWECW+zDjR/69eS6VtuMD5+O2lZw6JyiWOw3avI7mnUkdpKzPfvy8F/nlZrgZa2cGmQsb0TmLZuk5trldosnGKD91w==", "$type": "06" } } libmongocrypt-1.8.4/bindings/python/test/data/fle2-find-range-explicit-v2/000077500000000000000000000000001454530651600264375ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/fle2-find-range-explicit-v2/int32/000077500000000000000000000000001454530651600273765ustar00rootroot00000000000000encrypted-payload.json000066400000000000000000000024421454530651600336400ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/fle2-find-range-explicit-v2/int32{ "v": { "$and": [ { "age": { "$gte": { "$binary": { "base64": "Dd0BAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAAA==", "subType": "06" } } } }, { "age": { "$lte": { "$binary": { "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", "subType": "06" } } } } ] } } libmongocrypt-1.8.4/bindings/python/test/data/fle2-find-range-explicit-v2/int32/rangeopts.json000066400000000000000000000002251454530651600322720ustar00rootroot00000000000000{ "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" }, "sparsity": { "$numberLong": "1" } } value-to-encrypt.json000066400000000000000000000005761454530651600334400ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/fle2-find-range-explicit-v2/int32{ "v": { "$and": [ { "age": { "$gte": { "$numberInt": "23" } } }, { "age": { "$lte": { "$numberInt": "35" } } } ] } } libmongocrypt-1.8.4/bindings/python/test/data/key-document-azure.json000066400000000000000000000017371454530651600260660ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "masterKey": { "provider": "azure", "keyVaultEndpoint": "example.com", "keyName": "foo" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": ["name1", "name2"] }libmongocrypt-1.8.4/bindings/python/test/data/key-document-gcp.json000066400000000000000000000020031454530651600254740ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "masterKey": { "provider": "gcp", "projectId": "foo", "location": "foo", "keyRing": "foo", "keyName": "foo" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": ["name1", "name2"] }libmongocrypt-1.8.4/bindings/python/test/data/key-document.json000066400000000000000000000020251454530651600247310ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "masterKey": { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "provider": "aws" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": ["name1", "name2"] }libmongocrypt-1.8.4/bindings/python/test/data/key-filter.json000066400000000000000000000003631454530651600244030ustar00rootroot00000000000000{ "$or": [ { "_id": { "$in": [ { "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", "$type": "04" } ] } }, { "keyAltNames": { "$in": [] } } ] }libmongocrypt-1.8.4/bindings/python/test/data/keys/000077500000000000000000000000001454530651600224065ustar00rootroot0000000000000012345678123498761234123456789012-local-document.json000066400000000000000000000013741454530651600314200ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/keys{ "_id": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "1ZbBTB1i/z4LcmBKi9+nnWqkVB4Wl6P4G7/TFQvXATRF2fX0lhBLIM6rT1U547FX2YgMtaP7sid+jpd4Vhz5kS+UlgtmCFfjeO4qOnJ78KEXRzeIebzKWKQz1pMhYZ3OURDL4wCtNqt3tbSr11kfTADmCMuzgp8U8P8T21RWWBU0f2XDcxiIShYncOS3poKu7GJaPCTav4r3h5h2xRklDA==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648914851981" } }, "updateDate": { "$date": { "$numberLong": "1648914851981" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } 12345678123498761234123456789013-local-document.json000066400000000000000000000013741454530651600314210ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/keys{ "_id": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEw==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "YQXu48YyDbXvVQ1OhPsodQQNA1gLVWZSV0udYVmCTpVrgyAZePHQmsWWnQzNZj+ZsTxRm02soje/FJCqWGLeth3gKdvIsRg15CDEUOqLdDEpHl46hadosXyJIfo0umZ/LVTkvxRhmDCDxAkd0+Dg4/vWSiG0FgNzGrlvOUsTLGbqWtNMuOdZ8pKAdnFRrqce5cwBGQmd2VVBA2OQ0/IMxQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1650631142512" } }, "updateDate": { "$date": { "$numberLong": "1650631142512" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } ABCDEFAB123498761234123456789012-local-document.json000066400000000000000000000013741454530651600316040ustar00rootroot00000000000000libmongocrypt-1.8.4/bindings/python/test/data/keys{ "_id": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "27OBvUqHAuYFy60nwCdvq2xmZ4kFzVySphXzBGq+HEot13comCoydEfnltBzLTuXLbV9cnREFJIO5f0jMqrlkxIuvAV8yO84p5VJTEa8j/xSNe7iA594rx7UeKT0fOt4VqM47fht8h+8PZYc5JVezvEMvwk115IBCwENxDjLtT0g+y8Hf+aTUEGtxrYToH8zf1/Y7S16mHiIc4jK3/vxHw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648915408923" } }, "updateDate": { "$date": { "$numberLong": "1648915408923" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } libmongocrypt-1.8.4/bindings/python/test/data/kms-encrypt-reply.txt000066400000000000000000000011251454530651600256000ustar00rootroot00000000000000HTTP/1.1 200 OK x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e Content-Type: application/x-amz-json-1.1 Content-Length: 446 Connection: close {"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "CiphertextBlob": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gHCPOT4UQIpMTvAVABLqnXlAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLxAm0nO3rccdoWA6AIBEIB7HUe6+aPvgNu/4sLEXBQVDIJVBueI3q7zdOMBSkRKkgZWqEuQgA6iDuEZbhHhOVCUXPBaLX6QWRwyMmjvIy/2Bg5q+TmwnfRo6QKdw2vee1W32/FdPWIoQy1yKOoIhNy6XMWldS3JuWK8ffQOYkssEqx0V4LW6PKuFv7D"}libmongocrypt-1.8.4/bindings/python/test/data/kms-reply-azure.txt000066400000000000000000000007731454530651600252520ustar00rootroot00000000000000HTTP/1.1 200 OK x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e Content-Type: application/x-amz-json-1.1 Content-Length: 374 {"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "plaintext": "TqhXy3tKckECjy4/ZNykMWG8amBF46isVPzeOgeusKrwheBmYaU8TMG5AHR/NeUDKukqo8hBGgogiQOVpLPkqBQHD8YkLsNbDmHoGOill5QAHnniF/Lz405bGucB5TfR", "value": "TqhXy3tKckECjy4/ZNykMWG8amBF46isVPzeOgeusKrwheBmYaU8TMG5AHR/NeUDKukqo8hBGgogiQOVpLPkqBQHD8YkLsNbDmHoGOill5QAHnniF/Lz405bGucB5TfR"}libmongocrypt-1.8.4/bindings/python/test/data/kms-reply-gcp.txt000066400000000000000000000005561454530651600246740ustar00rootroot00000000000000HTTP/1.1 200 OK x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e Content-Type: application/x-amz-json-1.1 Content-Length: 233 {"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "plaintext": "TqhXy3tKckECjy4/ZNykMWG8amBF46isVPzeOgeusKrwheBmYaU8TMG5AHR/NeUDKukqo8hBGgogiQOVpLPkqBQHD8YkLsNbDmHoGOill5QAHnniF/Lz405bGucB5TfR"}libmongocrypt-1.8.4/bindings/python/test/data/kms-reply.txt000066400000000000000000000005561454530651600241250ustar00rootroot00000000000000HTTP/1.1 200 OK x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e Content-Type: application/x-amz-json-1.1 Content-Length: 233 {"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "Plaintext": "TqhXy3tKckECjy4/ZNykMWG8amBF46isVPzeOgeusKrwheBmYaU8TMG5AHR/NeUDKukqo8hBGgogiQOVpLPkqBQHD8YkLsNbDmHoGOill5QAHnniF/Lz405bGucB5TfR"}libmongocrypt-1.8.4/bindings/python/test/data/list-collections-filter.json000066400000000000000000000000241454530651600270740ustar00rootroot00000000000000{ "name": "test" }libmongocrypt-1.8.4/bindings/python/test/data/mongocryptd-command.json000066400000000000000000000012631454530651600263110ustar00rootroot00000000000000{ "find": "test", "filter": { "ssn": "457-55-5462" }, "jsonSchema": { "properties": { "ssn": { "encrypt": { "keyId": [ { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "isRemoteSchema": true }libmongocrypt-1.8.4/bindings/python/test/data/mongocryptd-reply.json000066400000000000000000000007471454530651600260340ustar00rootroot00000000000000{ "schemaRequiresEncryption": true, "ok": { "$numberInt": "1" }, "result": { "find": "test", "filter": { "ssn": { "$eq": { "$binary": { "base64": "ADgAAAAQYQABAAAABWtpABAAAAAEYWFhYWFhYWFhYWFhYWFhYQJ2AAwAAAA0NTctNTUtNTQ2MgAA", "subType": "06" } } } } }, "hasEncryptedPlaceholders": true }libmongocrypt-1.8.4/bindings/python/test/data/schema-map.json000066400000000000000000000015041454530651600243410ustar00rootroot00000000000000{ "test.test": { "properties": { "ssn": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "test.test2": { "properties": { "ssn": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } }, "bsonType": "object" } }libmongocrypt-1.8.4/bindings/python/test/test_binding.py000066400000000000000000000045361454530651600235550ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Test the binding module.""" import sys sys.path[0:0] = [""] import pymongocrypt from pymongocrypt.binding import ffi, lib, _parse_version from test import unittest class TestBinding(unittest.TestCase): def assertVersionLike(self, version): self.assertTrue(isinstance(version, str), msg=version) # There should be at least one dot: "1.0" or "1.0.0" not "1". self.assertGreaterEqual(len(version.split('.')), 2, msg=version) def test_pymongocrypt_version(self): self.assertVersionLike(pymongocrypt.__version__) def test_libmongocrypt_version(self): self.assertVersionLike(pymongocrypt.libmongocrypt_version()) def test_mongocrypt_new(self): data = lib.mongocrypt_new() self.assertNotEqual(data, ffi.NULL) lib.mongocrypt_destroy(data) def test_mongocrypt_binary_new(self): data = lib.mongocrypt_binary_new() self.assertNotEqual(data, ffi.NULL) lib.mongocrypt_binary_destroy(data) def test_mongocrypt_status_new(self): data = lib.mongocrypt_status_new() self.assertNotEqual(data, ffi.NULL) lib.mongocrypt_status_destroy(data) def test_parse_version(self): # Dev versions, betas, RCs should be less than stable releases. for v in ('1.1.0-beta1', '1.1.0-b2', '1.1.0-rc1', '1.1.0-beta1', '1.1.0-pre1'): self.assertLess(_parse_version(v), _parse_version('1.1.0')) # Dev versions should parse correctly. _parse_version('1.1.0-beta1+20201102git80202647fc') # Hyphenation in patch version should be disregarded. self.assertEqual(_parse_version('1.1.0-beta1'), _parse_version('1.1.0beta1')) if __name__ == "__main__": unittest.main() libmongocrypt-1.8.4/bindings/python/test/test_crypto.py000066400000000000000000000066271454530651600234660ustar00rootroot00000000000000# Copyright 2020-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Test the crypto module.""" import sys sys.path[0:0] = [""] import base64 from pymongocrypt.binary import MongoCryptBinaryIn from pymongocrypt.binding import ffi, lib from pymongocrypt.crypto import sign_rsaes_pkcs1_v1_5 from test import unittest class TestCrypto(unittest.TestCase): def test_sign_rsaes_pkcs1_v1_5(self): key_b64 = 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJxCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xYuXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CMprqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrShXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqImRYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlxdc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4umxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAxbLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4VnrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a' ciphertext_b64 = "VocBRhpMmQ2XCzVehWSqheQLnU889gf3dhU4AnVnQTJjsKx/CM23qKDPkZDd2A/BnQsp99SN7ksIX5Raj0TPwyN5OCN/YrNFNGoOFlTsGhgP/hyE8X3Duiq6sNO0SMvRYNPFFGlJFsp1Fw3Z94eYMg4/Wpw5s4+Jo5Zm/qY7aTJIqDKDQ3CNHLeJgcMUOc9sz01/GzoUYKDVODHSxrYEk5ireFJFz9vP8P7Ha+VDUZuQIQdXer9NBbGFtYmWprY3nn4D3Dw93Sn0V0dIqYeIo91oKyslvMebmUM95S2PyIJdEpPb2DJDxjvX/0LLwSWlSXRWy9gapWoBkb4ynqZBsg==" value = b'data to sign' with MongoCryptBinaryIn(b'1' * 256) as output, \ MongoCryptBinaryIn(base64.b64decode(key_b64)) as key,\ MongoCryptBinaryIn(value) as value: retval = sign_rsaes_pkcs1_v1_5( ffi.NULL, key.bin, value.bin, output.bin, lib.mongocrypt_status_new()) self.assertTrue(retval) self.assertEqual( output.to_bytes(), base64.b64decode(ciphertext_b64)) if __name__ == "__main__": unittest.main() libmongocrypt-1.8.4/bindings/python/test/test_mongocrypt.py000066400000000000000000001056301454530651600243410ustar00rootroot00000000000000# Copyright 2019-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Test the mongocrypt module.""" import base64 import copy import json import os import sys import bson from bson.raw_bson import RawBSONDocument from bson import json_util from bson.binary import Binary, UuidRepresentation from bson.codec_options import CodecOptions from bson.json_util import JSONOptions from bson.son import SON sys.path[0:0] = [""] import pymongocrypt.mongocrypt from pymongo_auth_aws.auth import AwsCredential from pymongocrypt.auto_encrypter import AutoEncrypter from pymongocrypt.binding import lib from pymongocrypt.compat import unicode_type, PY3 from pymongocrypt.errors import MongoCryptError from pymongocrypt.explicit_encrypter import ExplicitEncrypter from pymongocrypt.mongocrypt import (MongoCrypt, MongoCryptBinaryIn, MongoCryptBinaryOut, MongoCryptOptions) from pymongocrypt.state_machine import MongoCryptCallback from test import unittest, mock import requests.exceptions import requests_mock # Data for testing libbmongocrypt binding. DATA_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), 'data')) def to_base64(data): b64 = base64.b64encode(data) if not PY3: return unicode_type(b64) return b64.decode('utf-8') class TestMongoCryptBinary(unittest.TestCase): def test_mongocrypt_binary_in(self): with MongoCryptBinaryIn(b'1\x0023') as binary: self.assertIsNotNone(binary.bin) self.assertEqual(binary.to_bytes(), b'1\x0023') self.assertIsNone(binary.bin) with MongoCryptBinaryIn(b'') as binary: self.assertIsNotNone(binary.bin) self.assertEqual(binary.to_bytes(), b'') self.assertIsNone(binary.bin) # Memoryview with MongoCryptBinaryIn(memoryview(b'1\x0023')) as binary: self.assertIsNotNone(binary.bin) self.assertEqual(binary.to_bytes(), b'1\x0023') self.assertIsNone(binary.bin) def test_mongocrypt_binary_out(self): with MongoCryptBinaryOut() as binary: self.assertIsNotNone(binary.bin) self.assertEqual(binary.to_bytes(), b'') self.assertIsNone(binary.bin) class TestMongoCryptOptions(unittest.TestCase): def test_mongocrypt_options(self): schema_map = bson_data('schema-map.json') valid = [ ({'local': {'key': b'1' * 96}}, None), ({ 'aws' : {} }, schema_map), ({'aws': {'accessKeyId': '', 'secretAccessKey': ''}}, schema_map), ({'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo'}}, None), ({'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo', 'sessionToken': 'token'}}, None), ({'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo'}, 'local': {'key': b'1' * 96}}, None), ({'local': {'key': to_base64(b'1' * 96)}}, None), ({'local': {'key': Binary(b'1' * 96)}}, None), ({'azure': {}}, None), ({'azure': {'clientId': 'foo', 'clientSecret': 'bar'}}, None), ({'gcp': {}}, None), ({'gcp': {'email': 'foo@bar.baz', 'privateKey': b'1'}}, None), ({'gcp': {'email': 'foo@bar.baz', 'privateKey': to_base64(b'1')}}, None), ({'gcp': {'email': 'foo@bar.baz', 'privateKey': Binary(b'1')}}, None) ] for kms_providers, schema_map in valid: opts = MongoCryptOptions(kms_providers, schema_map) self.assertEqual(opts.kms_providers, kms_providers, msg=kms_providers) self.assertEqual(opts.schema_map, schema_map) self.assertIsNone(opts.encrypted_fields_map) self.assertFalse(opts.bypass_query_analysis) encrypted_fields_map = bson_data('encrypted-field-config-map.json') opts = MongoCryptOptions(valid[0][0], schema_map, encrypted_fields_map=encrypted_fields_map, bypass_query_analysis=True) self.assertEqual(opts.encrypted_fields_map, encrypted_fields_map) self.assertTrue(opts.bypass_query_analysis) def test_mongocrypt_options_validation(self): with self.assertRaisesRegex( ValueError, 'at least one KMS provider must be configured'): MongoCryptOptions({}) for invalid_kms_providers in [ {'aws': {'accessKeyId': 'foo'}}, {'aws': {'secretAccessKey': 'foo'}}]: with self.assertRaisesRegex( ValueError, r"kms_providers\['aws'\] must contain " "'accessKeyId' and 'secretAccessKey'"): MongoCryptOptions(invalid_kms_providers) with self.assertRaisesRegex( TypeError, r"kms_providers\['local'\]\['key'\] must be an " r"instance of bytes or str"): MongoCryptOptions({'local': {'key': None}}) with self.assertRaisesRegex( TypeError, r"kms_providers\['gcp'\]\['privateKey'\] must be an " r"instance of bytes or str"): MongoCryptOptions({'gcp': {'email': "foo@bar.baz", "privateKey": None}}) valid_kms = {'aws': {'accessKeyId': '', 'secretAccessKey': ''}} with self.assertRaisesRegex( TypeError, "schema_map must be bytes or None"): MongoCryptOptions(valid_kms, schema_map={}) with self.assertRaisesRegex( TypeError, "encrypted_fields_map must be bytes or None"): MongoCryptOptions(valid_kms, encrypted_fields_map={}) class TestMongoCrypt(unittest.TestCase): maxDiff = None def test_mongocrypt(self): kms_providers = { 'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo'}} opts = MongoCryptOptions(kms_providers) mc = MongoCrypt(opts, MockCallback()) mc.close() mc.close() def test_mongocrypt_aws_session_token(self): kms_providers = { 'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo', 'sessionToken': 'token'}} opts = MongoCryptOptions(kms_providers) mc = MongoCrypt(opts, MockCallback()) mc.close() def test_mongocrypt_validation(self): callback = MockCallback() options = MongoCryptOptions({'local': {'key': b'\x00' * 96}}) with self.assertRaisesRegex( TypeError, 'options must be a MongoCryptOptions'): MongoCrypt({}, callback) with self.assertRaisesRegex( TypeError, 'options must be a MongoCryptOptions'): MongoCrypt(None, callback) with self.assertRaisesRegex( TypeError, 'callback must be a MongoCryptCallback'): MongoCrypt(options, {}) with self.assertRaisesRegex( TypeError, 'callback must be a MongoCryptCallback'): MongoCrypt(options, None) invalid_key_len_opts = MongoCryptOptions({'local': {'key': b'1'}}) with self.assertRaisesRegex( MongoCryptError, "local key must be 96 bytes"): MongoCrypt(invalid_key_len_opts, callback) def test_setopt_kms_provider_base64_or_bytes(self): test_fields = [("local", "key"), ("gcp", "privateKey")] callback = MockCallback() base_kms_dict = {'local': {'key': b'\x00' * 96}, 'gcp': {'email': 'foo@bar.baz', 'privateKey': b'\x00'}} for f1, f2 in test_fields: kms_dict = copy.deepcopy(base_kms_dict) # Case 1: pass key as string containing bytes (valid) kms_dict[f1][f2] = b'\x00' * 96 options = MongoCryptOptions(kms_dict) mc = MongoCrypt(options, callback) mc.close() # Case 2: pass key as base64-encoded unicode literal (valid) kms_dict[f1][f2] = to_base64(b'\x00' * 96) options = MongoCryptOptions(kms_dict) mc = MongoCrypt(options, callback) mc.close() # Case 3: pass key as unicode string containing bytes (invalid) kms_dict[f1][f2] = unicode_type(b'\x00' * 96) options = MongoCryptOptions(kms_dict) with self.assertRaisesRegex( MongoCryptError, "unable to parse base64 from UTF-8 field %s.%s" % ( f1, f2)): MongoCrypt(options, callback) # Case 4: pass key as base64-encoded string (invalid) # Only applicable to "local" as key length is not validated for gcp. kms_dict = copy.deepcopy(base_kms_dict) kms_dict['local']['key'] = base64.b64encode(b'\x00' * 96) options = MongoCryptOptions(kms_dict) with self.assertRaisesRegex( MongoCryptError, "local key must be 96 bytes"): MongoCrypt(options, callback) @staticmethod def create_mongocrypt(**kwargs): return MongoCrypt(MongoCryptOptions({ 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, 'local': {'key': b'\x00'*96}}, **kwargs), MockCallback()) def _test_kms_context(self, ctx): key_filter = ctx.mongo_operation() self.assertEqual(key_filter, bson_data('key-filter.json')) ctx.add_mongo_operation_result(bson_data('key-document.json')) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_KMS) km_contexts = list(ctx.kms_contexts()) self.assertEqual(len(km_contexts), 1) with km_contexts[0] as kms_ctx: self.assertEqual(kms_ctx.kms_provider, "aws") self.assertEqual(kms_ctx.endpoint, "kms.us-east-1.amazonaws.com:443") self.assertEqual(len(kms_ctx.message), 790) self.assertEqual(kms_ctx.bytes_needed, 1024) kms_ctx.feed(http_data('kms-reply.txt')) self.assertEqual(kms_ctx.bytes_needed, 0) self.assertEqual(kms_ctx.kms_provider, "aws") ctx.complete_kms() def test_encrypt(self): mc = self.create_mongocrypt() self.addCleanup(mc.close) if mc.crypt_shared_lib_version is not None: self.skipTest("this test must be skipped when crypt_shared is loaded") with mc.encryption_context('text', bson_data('command.json')) as ctx: self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO) list_colls_filter = ctx.mongo_operation() self.assertEqual(list_colls_filter, bson_data('list-collections-filter.json')) ctx.add_mongo_operation_result(bson_data('collection-info.json')) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS) mongocryptd_cmd = ctx.mongo_operation() self.assertEqual(bson.decode(mongocryptd_cmd, OPTS), json_data('mongocryptd-command.json')) self.assertEqual(mongocryptd_cmd, bson_data('mongocryptd-command.json')) ctx.add_mongo_operation_result(bson_data('mongocryptd-reply.json')) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) self._test_kms_context(ctx) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_READY) encrypted = ctx.finish() self.assertEqual(bson.decode(encrypted, OPTS), json_data('encrypted-command.json')) self.assertEqual(encrypted, bson_data('encrypted-command.json')) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_DONE) def test_decrypt(self): mc = self.create_mongocrypt() self.addCleanup(mc.close) with mc.decryption_context( bson_data('encrypted-command-reply.json')) as ctx: self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) self._test_kms_context(ctx) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_READY) encrypted = ctx.finish() self.assertEqual(bson.decode(encrypted, OPTS), json_data('command-reply.json')) self.assertEqual(encrypted, bson_data('command-reply.json')) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_DONE) def test_encrypt_encrypted_fields_map(self): encrypted_fields_map = bson_data('compact/success/encrypted-field-config-map.json') mc = self.create_mongocrypt(encrypted_fields_map=encrypted_fields_map) self.addCleanup(mc.close) with mc.encryption_context('db', bson_data('compact/success/cmd.json')) as ctx: self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) ctx.mongo_operation() ctx.add_mongo_operation_result(bson_data( 'keys/12345678123498761234123456789012-local-document.json')) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) ctx.mongo_operation() ctx.add_mongo_operation_result(bson_data( 'keys/ABCDEFAB123498761234123456789012-local-document.json')) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) ctx.mongo_operation() ctx.add_mongo_operation_result(bson_data( 'keys/12345678123498761234123456789013-local-document.json')) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_READY) encrypted = ctx.finish() self.assertEqual(bson.decode(encrypted, OPTS), json_data('compact/success/encrypted-payload.json')) self.assertEqual(encrypted, bson_data('compact/success/encrypted-payload.json')) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_DONE) class MockCallback(MongoCryptCallback): def __init__(self, list_colls_result=None, mongocryptd_reply=None, key_docs=None, kms_reply=None): self.list_colls_result = list_colls_result self.mongocryptd_reply = mongocryptd_reply self.key_docs = key_docs self.kms_reply = kms_reply self.kms_endpoint = None def kms_request(self, kms_context): self.kms_endpoint = kms_context.endpoint kms_context.feed(self.kms_reply) def collection_info(self, ns, filter): return self.list_colls_result def mark_command(self, ns, cmd): return self.mongocryptd_reply def fetch_keys(self, filter): return self.key_docs def insert_data_key(self, data_key): raise NotImplementedError def bson_encode(self, doc): return bson.encode(doc) def close(self): pass class TestMongoCryptCallback(unittest.TestCase): maxDiff = None @staticmethod def mongo_crypt_opts(): return MongoCryptOptions({ 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, 'local': {'key': b'\x00'*96}}) @unittest.skipUnless(os.getenv("TEST_CRYPT_SHARED"), "this test requires TEST_CRYPT_SHARED=1") def test_crypt_shared(self): kms_providers = { 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, 'local': {'key': b'\x00'*96}} mc = MongoCrypt(MongoCryptOptions(kms_providers), MockCallback()) self.addCleanup(mc.close) self.assertIsNotNone(mc.crypt_shared_lib_version) # Test that we can pick up crypt_shared automatically encrypter = AutoEncrypter(MockCallback(), MongoCryptOptions( kms_providers, bypass_encryption=False, crypt_shared_lib_required=True)) self.addCleanup(encrypter.close) encrypter = AutoEncrypter(MockCallback(), MongoCryptOptions( kms_providers, crypt_shared_lib_path=os.environ["CRYPT_SHARED_PATH"], crypt_shared_lib_required=True)) self.addCleanup(encrypter.close) with self.assertRaisesRegex(MongoCryptError, "/doesnotexist"): AutoEncrypter(MockCallback(), MongoCryptOptions( kms_providers, crypt_shared_lib_path="/doesnotexist", crypt_shared_lib_required=True)) def test_encrypt(self): encrypter = AutoEncrypter(MockCallback( list_colls_result=bson_data('collection-info.json'), mongocryptd_reply=bson_data('mongocryptd-reply.json'), key_docs=[bson_data('key-document.json')], kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) self.addCleanup(encrypter.close) encrypted = encrypter.encrypt('test', bson_data('command.json')) self.assertEqual(bson.decode(encrypted, OPTS), json_data('encrypted-command.json')) self.assertEqual(encrypted, bson_data('encrypted-command.json')) def test_decrypt(self): encrypter = AutoEncrypter(MockCallback( list_colls_result=bson_data('collection-info.json'), mongocryptd_reply=bson_data('mongocryptd-reply.json'), key_docs=[bson_data('key-document.json')], kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) self.addCleanup(encrypter.close) decrypted = encrypter.decrypt( bson_data('encrypted-command-reply.json')) self.assertEqual(bson.decode(decrypted, OPTS), json_data('command-reply.json')) self.assertEqual(decrypted, bson_data('command-reply.json')) def test_need_kms_aws_credentials(self): kms_providers = { 'aws': {} } opts = MongoCryptOptions(kms_providers) callback = MockCallback( list_colls_result=bson_data('collection-info.json'), mongocryptd_reply=bson_data('mongocryptd-reply.json'), key_docs=[bson_data('key-document.json')], kms_reply=http_data('kms-reply.txt')) encrypter = AutoEncrypter(callback, opts) self.addCleanup(encrypter.close) with mock.patch("pymongocrypt.credentials.aws_temp_credentials") as m: m.return_value = AwsCredential("example", "example", None) decrypted = encrypter.decrypt( bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertEqual(bson.decode(decrypted, OPTS), json_data('command-reply.json')) self.assertEqual(decrypted, bson_data('command-reply.json')) def test_need_kms_gcp_credentials(self): kms_providers = { 'gcp': {} } opts = MongoCryptOptions(kms_providers) callback = MockCallback( list_colls_result=bson_data('collection-info.json'), mongocryptd_reply=bson_data('mongocryptd-reply.json'), key_docs=[bson_data('key-document-gcp.json')], kms_reply=http_data('kms-reply-gcp.txt')) encrypter = AutoEncrypter(callback, opts) self.addCleanup(encrypter.close) with requests_mock.Mocker() as m: data = {"access_token": "foo"} url = "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" m.get(url, text=json.dumps(data)) decrypted = encrypter.decrypt( bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertEqual(bson.decode(decrypted, OPTS), json_data('command-reply.json')) self.assertEqual(decrypted, bson_data('command-reply.json')) class TestNeedKMSAzureCredentials(unittest.TestCase): maxDiff = None def get_encrypter(self, clear_cache=True): if clear_cache: pymongocrypt.credentials._azure_creds_cache = None kms_providers = { 'azure': {} } opts = MongoCryptOptions(kms_providers) callback = MockCallback( list_colls_result=bson_data('collection-info.json'), mongocryptd_reply=bson_data('mongocryptd-reply.json'), key_docs=[bson_data('key-document-azure.json')], kms_reply=http_data('kms-reply-azure.txt')) encrypter = AutoEncrypter(callback, opts) self.addCleanup(encrypter.close) return encrypter def test_success(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: data = {"access_token": "foo", "expires_in": 4000} url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, text=json.dumps(data)) decrypted = encrypter.decrypt( bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertEqual(bson.decode(decrypted, OPTS), json_data('command-reply.json')) self.assertEqual(decrypted, bson_data('command-reply.json')) self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) def test_empty_json(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, text=json.dumps({})) with self.assertRaisesRegex(MongoCryptError, "Azure IMDS response must contain"): encrypter.decrypt(bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) def test_bad_json(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, text="a'") with self.assertRaisesRegex(MongoCryptError, "Azure IMDS response must be in JSON format"): encrypter.decrypt(bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) def test_http_404(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, status_code=404) with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token."): encrypter.decrypt(bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) def test_http_500(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, status_code=500) with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token."): encrypter.decrypt(bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) def test_slow_response(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, exc=requests.exceptions.ConnectTimeout) with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token: "): encrypter.decrypt(bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) def test_cache(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: data = {"access_token": "foo", "expires_in": 4000} url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, text=json.dumps(data)) decrypted = encrypter.decrypt( bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) # Should use the cached value. decrypted = encrypter.decrypt(bson_data('encrypted-command-reply.json')) self.assertEqual(decrypted, bson_data('command-reply.json')) self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) def test_cache_expires_soon(self): encrypter = self.get_encrypter() with requests_mock.Mocker() as m: data = {"access_token": "foo", "expires_in": 10} url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, text=json.dumps(data)) decrypted = encrypter.decrypt( bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) # Should not use the cached value. encrypter = self.get_encrypter(False) self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) with requests_mock.Mocker() as m: url = "http://169.254.169.254/metadata/identity/oauth2/token" m.get(url, exc=requests.exceptions.ConnectTimeout) with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token: "): encrypter.decrypt(bson_data('encrypted-command-reply.json')) self.assertTrue(m.called) self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) class KeyVaultCallback(MockCallback): def __init__(self, kms_reply=None): super(KeyVaultCallback, self).__init__(kms_reply=kms_reply) self.data_key = None def fetch_keys(self, filter): return self.data_key def insert_data_key(self, data_key): self.data_key = data_key return bson.decode(data_key, OPTS)['_id'] class TestExplicitEncryption(unittest.TestCase): maxDiff = None @staticmethod def mongo_crypt_opts(): return MongoCryptOptions({ 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, 'local': {'key': b'\x00'*96}}) def _test_encrypt_decrypt(self, key_id=None, key_alt_name=None): encrypter = ExplicitEncrypter(MockCallback( key_docs=[bson_data('key-document.json')], kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) self.addCleanup(encrypter.close) val = {'v': 'hello'} encoded_val = bson.encode(val) algo = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" encrypted = encrypter.encrypt( encoded_val, algo, key_id=key_id, key_alt_name=key_alt_name) self.assertEqual(bson.decode(encrypted, OPTS), json_data('encrypted-value.json')) self.assertEqual(encrypted, bson_data('encrypted-value.json')) decrypted = encrypter.decrypt(encrypted) self.assertEqual(bson.decode(decrypted, OPTS), val) self.assertEqual(encoded_val, decrypted) def test_encrypt_decrypt(self): key_id = json_data('key-document.json')['_id'] self._test_encrypt_decrypt(key_id=key_id) def test_encrypt_decrypt_key_alt_name(self): key_alt_name = json_data('key-document.json')['keyAltNames'][0] self._test_encrypt_decrypt(key_alt_name=key_alt_name) def test_encrypt_errors(self): key_id = json_data('key-document.json')['_id'] encrypter = ExplicitEncrypter(MockCallback(key_docs=[]), self.mongo_crypt_opts()) self.addCleanup(encrypter.close) val = {'v': 'value123'} encoded_val = bson.encode(val) # Invalid algorithm. with self.assertRaisesRegex(MongoCryptError, "algorithm"): encrypter.encrypt(encoded_val, "Invalid", key_id) # Invalid query_type type. with self.assertRaisesRegex(TypeError, "query_type"): encrypter.encrypt(encoded_val, "Indexed", key_id, query_type=42) # Invalid query_type string. with self.assertRaisesRegex(MongoCryptError, "query_type"): encrypter.encrypt(encoded_val, "Indexed", key_id, query_type='invalid query type string') # Invalid contention_factor type. with self.assertRaisesRegex(TypeError, "contention_factor"): encrypter.encrypt(encoded_val, "Indexed", key_id, contention_factor='not an int') with self.assertRaisesRegex(MongoCryptError, "contention"): encrypter.encrypt(encoded_val, "Indexed", key_id, contention_factor=-1) # Invalid: Unindexed + query_type is an error. with self.assertRaisesRegex(MongoCryptError, "query"): encrypter.encrypt(encoded_val, "Unindexed", key_id, query_type='equality') # Invalid: Unindexed + contention_factor is an error. with self.assertRaisesRegex(MongoCryptError, "contention"): encrypter.encrypt(encoded_val, "Unindexed", key_id, contention_factor=1) def test_encrypt_indexed(self): key_path = 'keys/ABCDEFAB123498761234123456789012-local-document.json' key_id = json_data(key_path)['_id'] encrypter = ExplicitEncrypter(MockCallback( key_docs=[bson_data(key_path)], kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) self.addCleanup(encrypter.close) val = {'v': 'value123'} encoded_val = bson.encode(val) for kwargs in [ dict(algorithm='Indexed', contention_factor=0), dict(algorithm='Indexed', query_type='equality', contention_factor=0), dict(algorithm='Indexed', contention_factor=100), dict(algorithm='Unindexed'), ]: kwargs['key_id'] = key_id encrypted = encrypter.encrypt(encoded_val, **kwargs) encrypted_val = bson.decode(encrypted, OPTS)['v'] self.assertIsInstance(encrypted_val, Binary) self.assertEqual(encrypted_val.subtype, 6) # Queryable Encryption find payloads cannot be round-tripped. if 'query_type' not in kwargs: decrypted = encrypter.decrypt(encrypted) self.assertEqual(bson.decode(decrypted, OPTS), val) self.assertEqual(encoded_val, decrypted) def test_data_key_creation(self): mock_key_vault = KeyVaultCallback( kms_reply=http_data('kms-encrypt-reply.txt')) encrypter = ExplicitEncrypter(mock_key_vault, self.mongo_crypt_opts()) self.addCleanup(encrypter.close) valid_args = [ ('local', None, ['first', 'second']), ('aws', {'region': 'region', 'key': 'cmk'}, ['third', 'forth']), # Unicode region and key ('aws', {'region': u'region-unicode', 'key': u'cmk-unicode'}, []), # Endpoint ('aws', {'region': 'region', 'key': 'cmk', 'endpoint': 'kms.us-east-1.amazonaws.com:443'}, []), ] for kms_provider, master_key, key_alt_names in valid_args: key_id = encrypter.create_data_key( kms_provider, master_key=master_key, key_alt_names=key_alt_names) self.assertIsInstance(key_id, Binary) self.assertEqual(key_id.subtype, 4) data_key = bson.decode(mock_key_vault.data_key, OPTS) # CDRIVER-3277 The order of key_alt_names is not maintained. for name in key_alt_names: self.assertIn(name, data_key['keyAltNames']) # Assert that the custom endpoint is passed to libmongocrypt. master_key = { "region": "region", "key": "key", "endpoint": "example.com" } key_material = base64.b64decode('xPTAjBRG5JiPm+d3fj6XLi2q5DMXUS/f1f+SMAlhhwkhDRL0kr8r9GDLIGTAGlvC+HVjSIgdL+RKwZCvpXSyxTICWSXTUYsWYPyu3IoHbuBZdmw2faM3WhcRIgbMReU5') if not PY3: key_material = Binary(key_material) encrypter.create_data_key("aws", master_key=master_key, key_material=key_material) self.assertEqual("example.com:443", mock_key_vault.kms_endpoint) def test_data_key_creation_bad_key_material(self): mock_key_vault = KeyVaultCallback( kms_reply=http_data('kms-encrypt-reply.txt')) encrypter = ExplicitEncrypter(mock_key_vault, self.mongo_crypt_opts()) self.addCleanup(encrypter.close) key_material = Binary(b'0' * 97) with self.assertRaisesRegex(MongoCryptError, "keyMaterial should have length 96, but has length 97"): encrypter.create_data_key("local", key_material=key_material) def test_rewrap_many_data_key(self): key_path = 'keys/ABCDEFAB123498761234123456789012-local-document.json' key_path2 = 'keys/12345678123498761234123456789012-local-document.json' encrypter = ExplicitEncrypter(MockCallback( key_docs=[bson_data(key_path), bson_data(key_path2)]), self.mongo_crypt_opts()) self.addCleanup(encrypter.close) result = encrypter.rewrap_many_data_key({}) raw_doc = RawBSONDocument(result) assert len(raw_doc['v']) == 2 def test_range_query_int32(self): key_path = 'keys/ABCDEFAB123498761234123456789012-local-document.json' key_id = json_data(key_path)['_id'] encrypter = ExplicitEncrypter(MockCallback( key_docs=[bson_data(key_path)], kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) self.addCleanup(encrypter.close) range_opts = bson_data("fle2-find-range-explicit-v2/int32/rangeopts.json") value = bson_data("fle2-find-range-explicit-v2/int32/value-to-encrypt.json") expected = json_data("fle2-find-range-explicit-v2/int32/encrypted-payload.json") encrypted = encrypter.encrypt( value, "rangePreview", key_id=key_id, query_type="rangePreview", contention_factor=4, range_opts=range_opts, is_expression=True) encrypted_val = bson.decode(encrypted, OPTS) self.assertEqual(encrypted_val, expected) def read(filename, **kwargs): with open(os.path.join(DATA_DIR, filename), **kwargs) as fp: return fp.read() OPTS = CodecOptions(uuid_representation=UuidRepresentation.UNSPECIFIED) # Use SON to preserve the order of fields while parsing json. if sys.version_info[:2] < (3, 6): document_class = SON else: document_class = dict JSON_OPTS = JSONOptions(document_class=document_class, uuid_representation=UuidRepresentation.UNSPECIFIED) def json_data(filename): return json_util.loads(read(filename), json_options=JSON_OPTS) def bson_data(filename): return bson.encode(json_data(filename), codec_options=OPTS) def http_data(filename): data = read(filename, mode='rb') return data.replace(b'\n', b'\r\n') if __name__ == "__main__": unittest.main() libmongocrypt-1.8.4/cmake/000077500000000000000000000000001454530651600155055ustar00rootroot00000000000000libmongocrypt-1.8.4/cmake/FetchMongoC.cmake000066400000000000000000000016631454530651600206510ustar00rootroot00000000000000include (FetchContent) # Set the tag that we will fetch. set (MONGOC_FETCH_TAG_FOR_LIBBSON "1.17.7" CACHE STRING "The Git tag of mongo-c-driver that will be fetched to obtain libbson") # Fetch the source archive for the requested tag from GitHub FetchContent_Declare ( embedded_mcd URL "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/${MONGOC_FETCH_TAG_FOR_LIBBSON}.tar.gz" ) # Populate it: FetchContent_GetProperties (embedded_mcd) if (NOT embedded_mcd_POPULATED) message (STATUS "Downloading mongo-c-driver ${MONGOC_FETCH_TAG_FOR_LIBBSON} for libbson") FetchContent_Populate (embedded_mcd) endif () # Store the directory path to the external mongoc project: get_filename_component (MONGOCRYPT_MONGOC_DIR "${embedded_mcd_SOURCE_DIR}" ABSOLUTE) # The project wants a VERSION_CURRENT file. We know that based on the tag. file (WRITE "${embedded_mcd_SOURCE_DIR}/VERSION_CURRENT" "${MONGOC_FETCH_TAG_FOR_LIBBSON}") libmongocrypt-1.8.4/cmake/ImportBSON.cmake000066400000000000000000000256601454530651600204540ustar00rootroot00000000000000#[[ This file defines, exports, and installs two INTERFACE targets: '_mongocrypt::libbson_for_static' and '_mongocrypt::libbson_for_shared', that are used to link libbson correctly for the build configuration of libmongocrypt. At find_package() time, we can resolve these interface targets to link to the appropriate libbson based on the build configurations of libmongocrypt. mongo::mongocrypt must link to _mongocrypt::libbson_for_shared, and mongo::mongocrypt_static must link to _mongocrypt::libbson_for_static. At configure+build time, these target will create BUILD_INTERFACE-only usage requirements appropriate for libmongocrypt to build against a libbson. Once these targets are installed, they retain no usage requirements defined here. Instead, the installed version of these targets will be manipulated in mongocrypt-config.cmake based on user settings and build configuration options of the installed libmongocrypt in order to ensure that users have satisfied the linking requirements of libmongocrypt. Refer to mongocrypt-config.cmake for more information This file calls add_subdirectory(EXCLUDE_FROM_ALL) on a mongo-c-driver project directory. This will expose libbson targets that we can link and use for the libmongocrypt build. The boolean option USE_SHARED_LIBBSON controls the behavior of libbson_for_shared: If USE_SHARED_LIBBSON=FALSE: - libbson_for_shared will transitively link the static libbson from the MONGOCRYPT_MONGOC_DIR. - The result is that mongo::mongocrypt (which is a SHARED library) will have the translation units of libbson directly embedded into the resulting binary. - The symbols from libbson that are merged into mongo::mongocrypt will be suppressed using linker scripts such that consumers of mongo::mongocrypt will not see the libbson symbols that were statically linked into the shared library. This allows consumers to link against a completely independent libbson without interfering with the libbson symbols that were merged into mongo::mongocrypt - The installed libbson_for_shared will have no usage requirements. If USE_SHARED_LIBBSON=TRUE: - libbson_for_shared will transitively use the shared libbson library from the MONGOCRYPT_MONGOC_DIR. - mongo::mongocrypt will be built with a dynamic link requirement on a libbson dynamic library, which must be resolved at runtime by consumers. The translation units from the MONGOCRYPT_MONGOC_DIR *will not* be included in the mongo::mongocrypt library. - The installed libbson_for_shared will dynamically link to a libbson on the user's system by using a find_library() call. In both of the above cases, libbson_for_static will require that the final consumer provide their own definitions of the libbson symbols, regardless of the value of USE_SHARED_LIBBSON. ]] include (CheckCSourceCompiles) include (CMakePushCheckState) cmake_push_check_state () # Even though we aren't going to use the system's libbson, try to detect whether it has # extra-alignment enabled. We want to match that setting as our default, for convenience # purposes only. find_path (SYSTEM_BSON_INCLUDE_DIR bson/bson.h PATH_SUFFIXES libbson-1.0) if (SYSTEM_BSON_INCLUDE_DIR AND NOT DEFINED ENABLE_EXTRA_ALIGNMENT) set (CMAKE_REQUIRED_INCLUDES "${SYSTEM_BSON_INCLUDE_DIR}") set (_extra_alignment_default OFF) check_c_source_compiles ([[ #include int main() { } ]] HAVE_SYSTEM_LIBBSON) if (HAVE_SYSTEM_LIBBSON) # We have a libbson, check for extra alignment check_c_source_compiles ([[ #include #ifndef BSON_EXTRA_ALIGN #error "Not extra-aligned" #endif int main() {} ]] SYSTEM_LIBBSON_IS_EXTRA_ALIGNED) if (SYSTEM_LIBBSON_IS_EXTRA_ALIGNED) # Extra aligned! We'll use extra alignment by default. set (_extra_alignment_default ON) endif () endif () endif () cmake_pop_check_state () set (init OFF) if (DEFINED ENABLED_SHARED_BSON) message (STATUS "ENABLE_SHARED_BSON is now named USE_SHARED_LIBBSON") set (init "${ENABLE_SHARED_BSON}") endif () option (USE_SHARED_LIBBSON "Dynamically link libbson for the libmongocrypt dynamic library (default is static)" ${init}) if (NOT DEFINED MONGOCRYPT_MONGOC_DIR) # The user did not provide a MONGOCRYPT_MONGOC_DIR, so we'll get one include (FetchContent OPTIONAL) if (NOT COMMAND FetchContent_Declare) # We need FetchContent in order to download the project. message (FATAL_ERROR "No MONGOCRYPT_MONGOC_DIR setting was defined, and the FetchContent.cmake " "module is not available. Upgrade your CMake version, or provide a " "MONGOCRYPT_MONGOC_DIR path to a mongo-c-driver directory (This is required " "for libmongocrypt to find a libbson to use and link against).") endif () include (FetchMongoC) # The FetchMongoC module defines a MONGOCRYPT_MONGOC_DIR for us to use endif () function (_import_bson) if (MONGOCRYPT_MONGOC_DIR STREQUAL "USE-SYSTEM" AND USE_SHARED_LIBBSON AND NOT ENABLE_ONLINE_TESTS) message (STATUS "NOTE: Using system-wide libbson library. This is intended only for package maintainers.") find_library (_MONGOCRYPT_SYSTEM_LIBBSON_SHARED "${CMAKE_SHARED_LIBRARY_PREFIX}bson-1.0${CMAKE_SHARED_LIBRARY_SUFFIX}") find_library (_MONGOCRYPT_SYSTEM_LIBBSON_STATIC "${CMAKE_STATIC_LIBRARY_PREFIX}bson-static-1.0${CMAKE_STATIC_LIBRARY_SUFFIX}") find_path (_MONGOCRYPT_SYSTEM_LIBBSON_INCLUDE_DIR bson/bson.h PATH_SUFFIXES libbson-1.0) add_library (bson_shared SHARED IMPORTED) add_library (bson_static STATIC IMPORTED) set_target_properties (bson_shared bson_static PROPERTIES IMPORTED_CONFIGURATIONS "Release" INTERFACE_INCLUDE_DIRECTORIES "${_MONGOCRYPT_SYSTEM_LIBBSON_INCLUDE_DIR}" ) set_property (TARGET bson_shared PROPERTY IMPORTED_LOCATION "${_MONGOCRYPT_SYSTEM_LIBBSON_SHARED}") set_property (TARGET bson_static PROPERTY IMPORTED_LOCATION "${_MONGOCRYPT_SYSTEM_LIBBSON_STATIC}") set_property ( CACHE _MONGOCRYPT_SYSTEM_LIBBSON_SHARED _MONGOCRYPT_SYSTEM_LIBBSON_INCLUDE_DIR PROPERTY ADVANCED TRUE ) else () message (STATUS "Using [${MONGOCRYPT_MONGOC_DIR}] as a sub-project for libbson") # Disable AWS_AUTH, to prevent it from building the kms-message symbols, which we build ourselves set (ENABLE_MONGODB_AWS_AUTH OFF CACHE BOOL "Disable kms-message content in mongoc for libmongocrypt" FORCE) # Disable install() for the libbson static library. We'll do it ourselves set (ENABLE_STATIC BUILD_ONLY) # Disable libzstd, which isn't necessary for libmongocrypt and isn't necessarily available. set (ENABLE_ZSTD OFF CACHE BOOL "Toggle libzstd for the mongoc subproject (not required by libmongocrypt)") # Disable snappy, which isn't necessary for libmongocrypt and isn't necessarily available. set (ENABLE_SNAPPY OFF CACHE BOOL "Toggle snappy for the mongoc subproject (not required by libmongocrypt)") # Disable deprecated automatic init and cleanup. (May be overridden by the user) set (ENABLE_AUTOMATIC_INIT_AND_CLEANUP OFF CACHE BOOL "Enable automatic init and cleanup (GCC only)") # Disable over-alignment of bson types. (May be overridden by the user) set (ENABLE_EXTRA_ALIGNMENT ${_extra_alignment_default} CACHE BOOL "Toggle extra alignment of bson_t") # We don't want the subproject to find libmongocrypt set (ENABLE_CLIENT_SIDE_ENCRYPTION OFF CACHE BOOL "Disable client-side encryption for the libmongoc subproject") # Add the subdirectory as a project. EXCLUDE_FROM_ALL to inhibit building and installing of components unless requested # SYSTEM (on applicable CMake versions) to prevent warnings (particularly from -Wconversion/-Wsign-conversion) from the C driver code if (CMAKE_VERSION VERSION_GREATER 3.25) add_subdirectory ("${MONGOCRYPT_MONGOC_DIR}" _mongo-c-driver EXCLUDE_FROM_ALL SYSTEM) else () add_subdirectory ("${MONGOCRYPT_MONGOC_DIR}" _mongo-c-driver EXCLUDE_FROM_ALL) endif () if (TARGET mongoc_static) # Workaround: Embedded mongoc_static does not set its INCLUDE_DIRECTORIES for user targets target_include_directories (mongoc_static PUBLIC "$" "$" ) endif () endif () endfunction () # Do the import in a function to isolate variable scope _import_bson () # Define interface targets to be used to control the libbson used at both build and import time. # Refer to mongocrypt-config.cmake to see how these targets are used by consumers add_library (_mongocrypt-libbson_for_static INTERFACE) add_library (_mongocrypt-libbson_for_shared INTERFACE) add_library (_mongocrypt::libbson_for_static ALIAS _mongocrypt-libbson_for_static) add_library (_mongocrypt::libbson_for_shared ALIAS _mongocrypt-libbson_for_shared) install ( TARGETS _mongocrypt-libbson_for_static _mongocrypt-libbson_for_shared EXPORT mongocrypt_targets ) # Link to the requested libbson, only exporting that usage for the local build tree. # The mongocrypt-config file will later add the appropriate link library for downstream # users during find_package() if (USE_SHARED_LIBBSON) target_link_libraries (_mongocrypt-libbson_for_shared INTERFACE $) else () target_link_libraries (_mongocrypt-libbson_for_shared INTERFACE $) endif () # libbson_for_static always links to the static libbson: target_link_libraries (_mongocrypt-libbson_for_static INTERFACE $) if (TARGET mongoc_static) # And an alias to the mongoc target for use in some test cases add_library (_mongocrypt::mongoc ALIAS mongoc_static) endif () # Put the libbson dynamic library into the current binary directory (plus possible config suffix). # This ensures that libbson DLL will resolve on Windows when it searches during tests set_property (TARGET bson_shared PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") if (ENABLE_STATIC) # We are going to build a static libmongocrypt. # We want the static libbson target from the embedded mongoc. Enable the static library as # part of "all", and install the archive alongside the rest of our static libraries. # (Useful for some users for convenience of static-linking libmongocrypt: CDRIVER-3187) set_target_properties (bson_static PROPERTIES EXCLUDE_FROM_ALL FALSE OUTPUT_NAME bson-static-for-libmongocrypt ) install ( FILES $ DESTINATION "${CMAKE_INSTALL_LIBDIR}" RENAME ${CMAKE_STATIC_LIBRARY_PREFIX}bson-static-for-libmongocrypt${CMAKE_STATIC_LIBRARY_SUFFIX} ) endif () libmongocrypt-1.8.4/cmake/ImportDFP.cmake000066400000000000000000000064771454530651600203310ustar00rootroot00000000000000#[[ This file handles importing the DFP (decimal floating point) library for decimal128 support. It is patterned after ImportBSON in this same directory. Initially, the only supported DFP implementation is Intel DFP. However, this module will allow for the future addition of support for libdfp. This file defines, exports, and installs one INTERFACE target: mongocrypt::intel_dfp. The target(s) from this file are used to link the DFP library correctly for the build configuration of libmongocrypt. At find_package() time, we can resolve these interface targets to link to the DFP library based on the build configurations of libmongocrypt. In the initial implementation both mongo::mongocrypt and mongo::mongocrypt_static must link to mongocrypt::intel_dfp (this is because if we link to the Intel DFP which is vendored with libmongocrypt then we will link the object files directly and if we use the system Intel DFP then we will be linking with .a static library archives). The default behavior is to use the Intel DFP which is vendored in this repository. By setting MONGOCRYPT_DFP_DIR=USE-SYSTEM the build will assume that an appropriate Intel DFP implementation can be found in a location where it has been installed system-wide (most likely under /usr or /usr/local). ]] if (DEFINED MONGOCRYPT_DFP_DIR AND NOT MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM") message (FATAL_ERROR "The only valid value for MONGOCRYPT_DFP_DIR is USE-SYSTEM") endif () function (_import_dfp) find_library (_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC "${CMAKE_STATIC_LIBRARY_PREFIX}bidgcc000${CMAKE_STATIC_LIBRARY_SUFFIX}") find_path (_MONGOCRYPT_SYSTEM_INTEL_DFP_INCLUDE_DIR bid_conf.h) add_library (intel_dfp STATIC IMPORTED) set_target_properties (intel_dfp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_MONGOCRYPT_SYSTEM_INTEL_DFP_INCLUDE_DIR}" ) set_property (TARGET intel_dfp PROPERTY IMPORTED_LOCATION "${_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC}") set_property ( CACHE _MONGOCRYPT_SYSTEM_INTEL_DFP_INCLUDE_DIR PROPERTY ADVANCED TRUE ) endfunction () if (NOT DEFINED MONGOCRYPT_DFP_DIR) # The user did not provide a MONGOCRYPT_DFP_DIR, so we'll set one up include (IntelDFP) elseif (MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM") message (STATUS "NOTE: Using system-wide Intel DFP library. This is intended only for package maintainers.") set (USE_SYSTEM_INTEL_DFP "ON") # Do the import in a function to isolate variable scope _import_dfp () # Define interface targets to be used to control the DFP used at both build and import time. # Refer to mongocrypt-config.cmake to see how these targets are used by consumers add_library (_mongocrypt-intel_dfp INTERFACE) add_library (mongocrypt::intel_dfp ALIAS _mongocrypt-intel_dfp) install ( TARGETS _mongocrypt-intel_dfp EXPORT mongocrypt_targets ) # Link to Intel DFP, only exporting that usage for the local build tree. # The mongocrypt-config file will later add the appropriate link library for downstream # users during find_package() target_link_libraries (_mongocrypt-intel_dfp INTERFACE $) # Notify in-tree consumers that IntelDFP is available: target_compile_definitions (_mongocrypt-intel_dfp INTERFACE $) endif () libmongocrypt-1.8.4/cmake/IntelDFP.cmake000066400000000000000000000356611454530651600201270ustar00rootroot00000000000000 include (FetchContent) find_program (GIT_EXECUTABLE git) find_program (PATCH_EXECUTABLE patch) set (_default_url "${PROJECT_SOURCE_DIR}/third-party/IntelRDFPMathLib20U2.tar.xz") set (INTEL_DFP_LIBRARY_URL "${_default_url}" CACHE STRING "The URL of an Intel DFP library to use") set (INTEL_DFP_LIBRARY_URL_HASH "SHA256=ac157e69c05556f3fa468ab34caeb1114a3b88ae18241bd41cc57b85a02dd314" CACHE STRING "The hash of the archive that lives at INTEL_DFP_LIBRARY_URL (Spelled: =)") option (INTEL_DFP_LIBRARY_PATCH_ENABLED "Whether to apply patches to the Intel DFP library" ON) set (_hash_arg) if (NOT INTEL_DFP_LIBRARY_URL_SHA256 STREQUAL "no-verify") set (_hash_arg URL_HASH "${INTEL_DFP_LIBRARY_URL_HASH}") endif () # Make the PATCH_COMMAND a no-op if it was disabled set (patch_command) if (NOT INTEL_DFP_LIBRARY_PATCH_ENABLED) set (patch_command "${CMAKE_COMMAND}" -E true) elseif (GIT_EXECUTABLE) set (patch_command "${GIT_EXECUTABLE}" --work-tree= apply) else () set (patch_command "${PATCH_EXECUTABLE}" --dir=) endif () # NOTE: The applying of the patch expects the correct input directly from the # expanded archive. If the patch needs to be reapplied, you may see errors # about trying to update the intel_dfp component. If you are seeing such # errors, delete the `_deps/` subdirectory in the build tree and # re-run CMake the project. FetchContent_Declare ( intel_dfp URL "${_default_url}" ${_hash_arg} PATCH_COMMAND ${patch_command} -p 4 # Strip four path components "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-s390x.patch" "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-MONGOCRYPT-571.patch" "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-libmongocrypt-pr-625.patch" --verbose ) FetchContent_GetProperties (intel_dfp) if (NOT intel_dfp_POPULATED) message (STATUS "Obtaining Intel Decimal FP library: ${INTEL_DFP_LIBRARY_URL}") FetchContent_Populate (intel_dfp) endif () # This list of sources matches the ones used within MongoDB server. The # "" prefix is replaced below. # Refer: https://github.com/mongodb/mongo/blob/e9be40f47a77af1931773ad671d4927c0fe6969a/src/third_party/IntelRDFPMathLib20U1/SConscript set (_dfp_sources "/float128/dpml_exception.c" "/float128/dpml_four_over_pi.c" "/float128/dpml_ux_bessel.c" "/float128/dpml_ux_bid.c" "/float128/dpml_ux_cbrt.c" "/float128/dpml_ux_erf.c" "/float128/dpml_ux_exp.c" "/float128/dpml_ux_int.c" "/float128/dpml_ux_inv_hyper.c" "/float128/dpml_ux_inv_trig.c" "/float128/dpml_ux_lgamma.c" "/float128/dpml_ux_log.c" "/float128/dpml_ux_mod.c" "/float128/dpml_ux_ops.c" "/float128/dpml_ux_ops_64.c" "/float128/dpml_ux_pow.c" "/float128/dpml_ux_powi.c" "/float128/dpml_ux_sqrt.c" "/float128/dpml_ux_trig.c" "/float128/sqrt_tab_t.c" "/src/bid128.c" "/src/bid128_2_str_tables.c" "/src/bid128_acos.c" "/src/bid128_acosh.c" "/src/bid128_add.c" "/src/bid128_asin.c" "/src/bid128_asinh.c" "/src/bid128_atan.c" "/src/bid128_atan2.c" "/src/bid128_atanh.c" "/src/bid128_cbrt.c" "/src/bid128_compare.c" "/src/bid128_cos.c" "/src/bid128_cosh.c" "/src/bid128_div.c" "/src/bid128_erf.c" "/src/bid128_erfc.c" "/src/bid128_exp.c" "/src/bid128_exp10.c" "/src/bid128_exp2.c" "/src/bid128_expm1.c" "/src/bid128_fdimd.c" "/src/bid128_fma.c" "/src/bid128_fmod.c" "/src/bid128_frexp.c" "/src/bid128_hypot.c" "/src/bid128_ldexp.c" "/src/bid128_lgamma.c" "/src/bid128_llrintd.c" "/src/bid128_log.c" "/src/bid128_log10.c" "/src/bid128_log1p.c" "/src/bid128_log2.c" "/src/bid128_logb.c" "/src/bid128_logbd.c" "/src/bid128_lrintd.c" "/src/bid128_lround.c" "/src/bid128_minmax.c" "/src/bid128_modf.c" "/src/bid128_mul.c" "/src/bid128_nearbyintd.c" "/src/bid128_next.c" "/src/bid128_nexttowardd.c" "/src/bid128_noncomp.c" "/src/bid128_pow.c" "/src/bid128_quantexpd.c" "/src/bid128_quantize.c" "/src/bid128_rem.c" "/src/bid128_round_integral.c" "/src/bid128_scalb.c" "/src/bid128_scalbl.c" "/src/bid128_sin.c" "/src/bid128_sinh.c" "/src/bid128_sqrt.c" "/src/bid128_string.c" "/src/bid128_tan.c" "/src/bid128_tanh.c" "/src/bid128_tgamma.c" "/src/bid128_to_int16.c" "/src/bid128_to_int32.c" "/src/bid128_to_int64.c" "/src/bid128_to_int8.c" "/src/bid128_to_uint16.c" "/src/bid128_to_uint32.c" "/src/bid128_to_uint64.c" "/src/bid128_to_uint8.c" "/src/bid32_acos.c" "/src/bid32_acosh.c" "/src/bid32_add.c" "/src/bid32_asin.c" "/src/bid32_asinh.c" "/src/bid32_atan.c" "/src/bid32_atan2.c" "/src/bid32_atanh.c" "/src/bid32_cbrt.c" "/src/bid32_compare.c" "/src/bid32_cos.c" "/src/bid32_cosh.c" "/src/bid32_div.c" "/src/bid32_erf.c" "/src/bid32_erfc.c" "/src/bid32_exp.c" "/src/bid32_exp10.c" "/src/bid32_exp2.c" "/src/bid32_expm1.c" "/src/bid32_fdimd.c" "/src/bid32_fma.c" "/src/bid32_fmod.c" "/src/bid32_frexp.c" "/src/bid32_hypot.c" "/src/bid32_ldexp.c" "/src/bid32_lgamma.c" "/src/bid32_llrintd.c" "/src/bid32_log.c" "/src/bid32_log10.c" "/src/bid32_log1p.c" "/src/bid32_log2.c" "/src/bid32_logb.c" "/src/bid32_logbd.c" "/src/bid32_lrintd.c" "/src/bid32_lround.c" "/src/bid32_minmax.c" "/src/bid32_modf.c" "/src/bid32_mul.c" "/src/bid32_nearbyintd.c" "/src/bid32_next.c" "/src/bid32_nexttowardd.c" "/src/bid32_noncomp.c" "/src/bid32_pow.c" "/src/bid32_quantexpd.c" "/src/bid32_quantize.c" "/src/bid32_rem.c" "/src/bid32_round_integral.c" "/src/bid32_scalb.c" "/src/bid32_scalbl.c" "/src/bid32_sin.c" "/src/bid32_sinh.c" "/src/bid32_sqrt.c" "/src/bid32_string.c" "/src/bid32_sub.c" "/src/bid32_tan.c" "/src/bid32_tanh.c" "/src/bid32_tgamma.c" "/src/bid32_to_bid128.c" "/src/bid32_to_bid64.c" "/src/bid32_to_int16.c" "/src/bid32_to_int32.c" "/src/bid32_to_int64.c" "/src/bid32_to_int8.c" "/src/bid32_to_uint16.c" "/src/bid32_to_uint32.c" "/src/bid32_to_uint64.c" "/src/bid32_to_uint8.c" "/src/bid64_acos.c" "/src/bid64_acosh.c" "/src/bid64_add.c" "/src/bid64_asin.c" "/src/bid64_asinh.c" "/src/bid64_atan.c" "/src/bid64_atan2.c" "/src/bid64_atanh.c" "/src/bid64_cbrt.c" "/src/bid64_compare.c" "/src/bid64_cos.c" "/src/bid64_cosh.c" "/src/bid64_div.c" "/src/bid64_erf.c" "/src/bid64_erfc.c" "/src/bid64_exp.c" "/src/bid64_exp10.c" "/src/bid64_exp2.c" "/src/bid64_expm1.c" "/src/bid64_fdimd.c" "/src/bid64_fma.c" "/src/bid64_fmod.c" "/src/bid64_frexp.c" "/src/bid64_hypot.c" "/src/bid64_ldexp.c" "/src/bid64_lgamma.c" "/src/bid64_llrintd.c" "/src/bid64_log.c" "/src/bid64_log10.c" "/src/bid64_log1p.c" "/src/bid64_log2.c" "/src/bid64_logb.c" "/src/bid64_logbd.c" "/src/bid64_lrintd.c" "/src/bid64_lround.c" "/src/bid64_minmax.c" "/src/bid64_modf.c" "/src/bid64_mul.c" "/src/bid64_nearbyintd.c" "/src/bid64_next.c" "/src/bid64_nexttowardd.c" "/src/bid64_noncomp.c" "/src/bid64_pow.c" "/src/bid64_quantexpd.c" "/src/bid64_quantize.c" "/src/bid64_rem.c" "/src/bid64_round_integral.c" "/src/bid64_scalb.c" "/src/bid64_scalbl.c" "/src/bid64_sin.c" "/src/bid64_sinh.c" "/src/bid64_sqrt.c" "/src/bid64_string.c" "/src/bid64_tan.c" "/src/bid64_tanh.c" "/src/bid64_tgamma.c" "/src/bid64_to_bid128.c" "/src/bid64_to_int16.c" "/src/bid64_to_int32.c" "/src/bid64_to_int64.c" "/src/bid64_to_int8.c" "/src/bid64_to_uint16.c" "/src/bid64_to_uint32.c" "/src/bid64_to_uint64.c" "/src/bid64_to_uint8.c" "/src/bid_binarydecimal.c" "/src/bid_convert_data.c" "/src/bid_decimal_data.c" "/src/bid_decimal_globals.c" "/src/bid_dpd.c" "/src/bid_feclearexcept.c" "/src/bid_fegetexceptflag.c" "/src/bid_feraiseexcept.c" "/src/bid_fesetexceptflag.c" "/src/bid_fetestexcept.c" "/src/bid_flag_operations.c" "/src/bid_from_int.c" "/src/bid_round.c" "/src/strtod128.c" "/src/strtod32.c" "/src/strtod64.c" "/src/wcstod128.c" "/src/wcstod32.c" "/src/wcstod64.c" ) # Put in the actual library path: string (REPLACE "" "${intel_dfp_SOURCE_DIR}/LIBRARY" _dfp_sources "${_dfp_sources}") #[[ Intel DFP gives us a very blunt yet powerful hammer to avoid symbol collision, since other library may also want a conflicting DFP version: Just rename everything! All function names are #defined with a `bid` or `binary` prefix, and are aliased to their "actual" names with a `__bid` or `__binary` prefix, respectively. So we can ship our own decimal library without worry, we'll rename those hidden symbols. ]] file (READ "${intel_dfp_SOURCE_DIR}/LIBRARY/src/bid_conf.h" dfp_conf_content) string (REGEX REPLACE #[[ Match every "#define X Y" where X begins with `"bid" or "binary", and Y begins with "__bid" or "__binary". X and Y must be separated by one or more spaces. ]] "#define ((bid|binary)[^ ]+ +)__(bid|binary)([^ +])" # Replace Y with "__mongocrypt_bid" or "__mongocrypt_binary" as the new prefix. "#define \\1 __mongocrypt_\\3\\4" new_content "${dfp_conf_content}" ) if (NOT new_content STREQUAL dfp_conf_content) # Only rewrite the file if we changed anything, otherwise we update build # input timestamps and will trigger a rebuild of DFP. file (WRITE "${intel_dfp_SOURCE_DIR}/LIBRARY/src/bid_conf.h" "${new_content}") endif () # Define the object library add_library (intel_dfp_obj OBJECT ${_dfp_sources}) # Build with -fPIC, since these objects may go into a static OR dynamic library. set_property (TARGET intel_dfp_obj PROPERTY POSITION_INDEPENDENT_CODE TRUE) # DFP needs information about the build target platform. Compute that: set (proc_lower $) set (ia32_list i386 i486 i586 i686 pentium3 pentium4 athlon geode emscripted x86 arm) set (efi2_list aarch64 arm64 x86_64 ppc64le riscv64) set (is_linux $) set (is_windows $) set (is_unix $) # These compiler definitions may seem a bit strange, but the whole DFP library's # config process is strange. These options match those used in MongoDB server. target_compile_definitions (intel_dfp_obj PUBLIC DECIMAL_CALL_BY_REFERENCE=0 DECIMAL_GLOBAL_ROUNDING=0 DECIMAL_GLOBAL_EXCEPTION_FLAGS=0 UNCHANGED_BINARY_STATUS_FLAGS=0 USE_COMPILER_F128_TYPE=0 USE_COMPILER_F80_TYPE=0 USE_NATIVE_QUAD_TYPE=0 $<${is_unix}:LINUX=1> $<$:mach=1> $<$:freebsd=1> $<$:linux=1> $<${is_windows}: WINDOWS=1 WNT=1 winnt=1 > $<$: IA32=1 ia32=1 > $<$: EFI2=1 efi2=1 > $<$: s390x=1 BID_BIG_ENDIAN=1 > ) # Suppress warnings in the Intel library, as it generates a lot that aren't of interest target_compile_options (intel_dfp_obj PRIVATE -w) target_include_directories(intel_dfp_obj PUBLIC ${intel_dfp_SOURCE_DIR}/LIBRARY/src) # Define an interface library that attaches the built TUs to the consumer add_library (_mongocrypt_intel_dfp INTERFACE) add_library (mongocrypt::intel_dfp ALIAS _mongocrypt_intel_dfp) # Notify in-tree consumers that IntelDFP is available: target_compile_definitions (_mongocrypt_intel_dfp INTERFACE $) target_sources (_mongocrypt_intel_dfp #[[ For targets *within this build* that link with mongocrypt::intel_dfp, inject the generated TUs (object files) from the intel_dfp_obj library. This will be stripped out of the interface library when it is installed, since we don't want to ship the DFP object separately. Instead, users will link to libmongocrypt, which will contain the necessary TUs for the library (because they link to this interface library). ]] INTERFACE $> ) target_link_libraries (_mongocrypt_intel_dfp INTERFACE $ # We do want to propagate an interface requirement: Some platforms need a # separate link library to support special math functions. $<$:m> ) # Give the installed target a name to indicate its hidden-ness set_property (TARGET _mongocrypt_intel_dfp PROPERTY EXPORT_NAME private::intel_dfp_interface) install (TARGETS _mongocrypt_intel_dfp EXPORT mongocrypt_targets) libmongocrypt-1.8.4/cmake/LTO.cmake000066400000000000000000000034651454530651600171550ustar00rootroot00000000000000 set (MONGO_LTO "OFF" CACHE STRING "Enable cross-translation unit optimizations (A.K.A. IPO/LTO/LTCG) [OFF/DEFAULT/FAT/THIN]" ) set_property (CACHE MONGO_LTO PROPERTY STRINGS OFF DEFAULT FAT THIN) if (MONGO_LTO STREQUAL "OFF") # Nothing to do return () endif () # CMake will know if LTO is supported at any basic level include (CheckIPOSupported) check_ipo_supported (RESULT supported OUTPUT out) if (NOT supported) message (SEND_ERROR "LTO is not supported by the compiler (requested by MONGO_LTO=${MONGO_LTO}):\n${out}") return () endif () # Set the appropriate compile/link flags for LTO: set (_c_flags) set (_link_flags) if (MONGO_LTO STREQUAL "DEFAULT") # Just use CMake's default INTERPROCEDURAL_OPTIMIZATION message (STATUS "Enabling INTERPROCEDURAL_OPTIMIZATION") set_property (DIRECTORY PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) elseif (MONGO_LTO STREQUAL "THIN") set (_c_flags -flto=thin) set (_link_flags -flto=thin) elseif (MONGO_LTO STREQUAL "FAT") set (_c_flags -flto -ffat-lto-objects) set (_link_flags -flto=auto) else () message (SEND_ERROR "Unknown MONGO_LTO setting '${MONGO_LTO}'") return () endif () # We need try_compile(), because we need more than one source file to accurately # check for LTO support try_compile ( MONGO_HAVE_LTO_${MONGO_LTO} "${CMAKE_CURRENT_BINARY_DIR}/_mongo-lto-check/${MONGO_LTO}" SOURCES "${CMAKE_CURRENT_LIST_DIR}/ltocheck-lib.c" "${CMAKE_CURRENT_LIST_DIR}/ltocheck-main.c" COMPILE_DEFINITIONS ${_c_flags} LINK_LIBRARIES ${_link_flags} OUTPUT_VARIABLE out ) if (NOT MONGO_HAVE_LTO_${MONGO_LTO}) message (SEND_ERROR "MONGO_LTO=${MONGO_LTO} is not supported by the current compiler:\n${out}") return () endif () add_compile_options (${_c_flags}) link_libraries (${_link_flags}) libmongocrypt-1.8.4/cmake/MongoC-Warnings.cmake000066400000000000000000000061711454530651600214640ustar00rootroot00000000000000#[[ This file sets warning options for the directories in which it is include()'d These warnings are intended to be ported to each supported platform, and especially for high-value warnings that are very likely to catch latent bugs early in the process before the code is even run. ]] set (__is_gnu "$") set (__is_clang "$,$>") set (__is_gnu_like "$") set (__is_msvc "$") # "Old" GNU is GCC < 5, which is missing several warning options set (__is_old_gnu "$,5>>") set (__not_old_gnu "$") #[[ Define additional compile options, conditional on the compiler being used. Each option should be prefixed by `gnu:`, `clang:`, `msvc:`, or `gnu-like:`. Those options will be conditionally enabled for GCC, Clang, or MSVC. These options are attached to the source directory and its children. ]] function (mongoc_add_platform_compile_options) foreach (opt IN LISTS ARGV) if (NOT opt MATCHES "^(gnu-like|gnu|clang|msvc):(.*)") message (SEND_ERROR "Invalid option '${opt}' (Should be prefixed by 'msvc:', 'gnu:', 'clang:', or 'gnu-like:'") continue () endif () if (CMAKE_MATCH_1 STREQUAL "gnu-like") add_compile_options ("$<${__is_gnu_like}:${CMAKE_MATCH_2}>") elseif (CMAKE_MATCH_1 STREQUAL gnu) add_compile_options ("$<${__is_gnu}:${CMAKE_MATCH_2}>") elseif (CMAKE_MATCH_1 STREQUAL clang) add_compile_options ("$<${__is_clang}:${CMAKE_MATCH_2}>") elseif (CMAKE_MATCH_1 STREQUAL "msvc") add_compile_options ("$<${__is_msvc}:${CMAKE_MATCH_2}>") else () message (SEND_ERROR "Invalid option to mongoc_add_platform_compile_options(): '${opt}'") endif () endforeach () endfunction () if (CMAKE_VERSION VERSION_LESS 3.3) # On older CMake versions, we'll just always pass the warning options, even # if the generate warnings for the C++ check file set (is_c_lang "1") else () # $ is only valid in CMake 3.3+ set (is_c_lang "$") endif () # These below warnings should always be unconditional hard errors, as the code is # almost definitely broken mongoc_add_platform_compile_options ( # Implicit function or variable declarations gnu-like:$<${is_c_lang}:-Werror=implicit> msvc:/we4013 msvc:/we4431 # Missing return types/statements gnu-like:-Werror=return-type msvc:/we4716 # Incompatible pointer types gnu-like:$<$:-Werror=incompatible-pointer-types> msvc:/we4113 # Integral/pointer conversions gnu-like:$<$:-Werror=int-conversion> msvc:/we4047 # Discarding qualifiers gnu:$<$:-Werror=discarded-qualifiers> clang:$<${is_c_lang}:-Werror=ignored-qualifiers> msvc:/we4090 # Definite use of uninitialized value gnu-like:-Werror=uninitialized msvc:/we4700 # Aside: Disable CRT insecurity warnings msvc:/D_CRT_SECURE_NO_WARNINGS ) libmongocrypt-1.8.4/cmake/Platform.cmake000066400000000000000000000027311454530651600202760ustar00rootroot00000000000000#[[ Defines a platform-support target _mongocrypt::platform. This target sets certain internal-only compile definitions, and defines usage requirements on certain platform features required by libmongocrypt (Threads, dlopen(), math) ]] add_library (lmc-platform INTERFACE) add_library (mongocrypt::platform ALIAS lmc-platform) install (TARGETS lmc-platform EXPORT mongocrypt_targets) set_property ( TARGET lmc-platform PROPERTY EXPORT_NAME mongocrypt::platform ) # Threads: find_package (Threads REQUIRED) # Special math: if (NOT APPLE) find_library (M_LIBRARY m) endif () # Special runtime: find_library (RT_LIBRARY rt) # Endian detection: if (DEFINED CMAKE_C_BYTE_ORDER) # Newer CMake knows this immediately: set (MONGOCRYPT_ENDIAN_DEF "MONGOCRYPT_${CMAKE_C_BYTE_ORDER}") else () include (TestBigEndian) test_big_endian (_is_big) set (MONGOCRYPT_ENDIAN_DEF "MONGOCRYPT_$_ENDIAN") endif () target_compile_definitions (lmc-platform INTERFACE "$" ) target_link_libraries (lmc-platform INTERFACE Threads::Threads # These are build-interface libs, but still required. These will be added # to the platform library in mongocrypt-config.cmake using the same # find_library() calls: $ $:${M_LIBRARY}>> $:${RT_LIBRARY}>> ) libmongocrypt-1.8.4/cmake/libmongocrypt-hidden-symbols.map000066400000000000000000000001431454530651600240110ustar00rootroot00000000000000mongocrypt { local: bson*; bcon*; jsonsl*; _*; kms*; };libmongocrypt-1.8.4/cmake/libmongocrypt-hidden-symbols.txt000066400000000000000000000000401454530651600240470ustar00rootroot00000000000000_bson* _bcon* _jsonsl* __* _kms*libmongocrypt-1.8.4/cmake/libmongocrypt-static.pc.in000066400000000000000000000004411454530651600226120ustar00rootroot00000000000000Name: ${PROJECT_NAME} Description: ${PROJECT_DESCRIPTION} Version: ${PROJECT_VERSION} Requires: ${PKG_CONFIG_STATIC_REQUIRES} prefix=${CMAKE_INSTALL_PREFIX} includedir=${PKG_CONFIG_INCLUDEDIR} libdir=${PKG_CONFIG_LIBDIR} Libs: ${PKG_CONFIG_STATIC_LIBS} Cflags: ${PKG_CONFIG_STATIC_CFLAGS} libmongocrypt-1.8.4/cmake/libmongocrypt.pc.in000066400000000000000000000004751454530651600213340ustar00rootroot00000000000000Name: ${PROJECT_NAME} Description: ${PROJECT_DESCRIPTION} Version: ${PROJECT_VERSION} Requires: ${PKG_CONFIG_REQUIRES} Requires.private: ${PKG_CONFIG_REQUIRES_PRIVATE} prefix=${CMAKE_INSTALL_PREFIX} includedir=${PKG_CONFIG_INCLUDEDIR} libdir=${PKG_CONFIG_LIBDIR} Libs: ${PKG_CONFIG_LIBS} Cflags: ${PKG_CONFIG_CFLAGS} libmongocrypt-1.8.4/cmake/ltocheck-lib.c000066400000000000000000000000661454530651600202130ustar00rootroot00000000000000 extern int answer (int a, int b) { return a + b; }libmongocrypt-1.8.4/cmake/ltocheck-main.c000066400000000000000000000001331454530651600203640ustar00rootroot00000000000000extern int answer (int, int); int main () { int a = answer (3, 4); return a != 7; } libmongocrypt-1.8.4/cmake/mongocrypt-config.cmake000066400000000000000000000050571454530651600221620ustar00rootroot00000000000000include(CMakeFindDependencyMacro) find_dependency(kms_message 0.0.1) include("${CMAKE_CURRENT_LIST_DIR}/mongocrypt_targets.cmake") if (DEFINED MONGOCRYPT_LIBBSON_STATIC_USE) # The user has named a library that should be linked as the static libbson library set_property ( TARGET mongo::_mongocrypt-libbson_for_static APPEND PROPERTY INTERFACE_LINK_LIBRARIES "$" ) endif () # BOOL: Whether the libmongocrypt dynamic library in this package needs to link to an external libbson. # In the default configuration, the shared lib will include the TUs for a pinned version of libbson # and will use linker scripts to "hide" these symbols from the outside world. # # If the libmongocrypt package was built to link against a shared libbson library, then the # libmongocrypt dynamic library will contain pending references to libbson symbols that will # need to be resolved before the library can be used. # # (Note: static libmongocrypt *always* needs to link against an external libbson, as it does not # embed the libbson symbols.) set (_using_shared_libbson "@USE_SHARED_LIBBSON@") if (_using_shared_libbson AND DEFINED MONGOCRYPT_LIBBSON_SHARED_USE) # The user has named a library that should be linked as the shared libbson library set_property ( TARGET mongo::_mongocrypt-libbson_for_shared APPEND PROPERTY INTERFACE_LINK_LIBRARIES "$" ) endif () set (_using_system_intel_dfp "@USE_SYSTEM_INTEL_DFP@") if (_using_system_intel_dfp) find_library (_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC "${CMAKE_STATIC_LIBRARY_PREFIX}bidgcc000${CMAKE_STATIC_LIBRARY_SUFFIX}") set_property ( TARGET mongo::_mongocrypt-intel_dfp PROPERTY IMPORTED_LOCATION "${_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC}" ) endif () find_dependency(Threads) # Link for dlopen(): set_property (TARGET mongo::mongocrypt::platform APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS}) # Link for special math functions: if (NOT APPLE) find_library (_MONGOCRYPT_M_LIBRARY m) mark_as_advanced (_MONGOCRYPT_M_LIBRARY) if (_MONGOCRYPT_M_LIBRARY) set_property (TARGET mongo::mongocrypt::platform APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${_MONGOCRYPT_M_LIBRARY}") endif () endif () # Special runtime: find_library (_MONGOCRYPT_RT_LIBRARY rt) mark_as_advanced (_MONGOCRYPT_RT_LIBRARY) if (_MONGOCRYPT_RT_LIBRARY) set_property (TARGET mongo::mongocrypt::platform APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${_MONGOCRYPT_RT_LIBRARY}") endif () libmongocrypt-1.8.4/doc/000077500000000000000000000000001454530651600151725ustar00rootroot00000000000000libmongocrypt-1.8.4/doc/Doxygen000066400000000000000000003217451454530651600165460ustar00rootroot00000000000000# Doxyfile 1.8.13 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "libmongocrypt" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = ./doc # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 0. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.idl \ *.ddl \ *.odl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.cs \ *.d \ *.php \ *.php4 \ *.php5 \ *.phtml \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.pyw \ *.f90 \ *.f95 \ *.f03 \ *.f08 \ *.f \ *.for \ *.tcl \ *.vhd \ *.vhdl \ *.ucf \ *.qsf # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = *-private.h \ *.c # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /