From 7b1024e711b8debbf9a918b935a9c4c130c4eb54 Mon Sep 17 00:00:00 2001 From: Lai Power Date: Sat, 8 Oct 2022 02:41:03 +0000 Subject: [PATCH] installed plugin `WP-WebAuthn` version 1.2.8 --- wp-content/plugins/wp-webauthn/LICENSE | 674 ++++ .../wp-webauthn/blocks/blocks.build.js | 1 + .../wp-webauthn-tr_TR-wwa_block_js.json | 1 + .../wp-webauthn-zh_CN-wwa_block_js.json | 1 + .../wp-webauthn-zh_HK-wwa_block_js.json | 1 + .../wp-webauthn-zh_TW-wwa_block_js.json | 1 + wp-content/plugins/wp-webauthn/css/admin.css | 54 + .../plugins/wp-webauthn/css/frontend.css | 260 ++ wp-content/plugins/wp-webauthn/css/login.css | 54 + wp-content/plugins/wp-webauthn/js/admin.js | 85 + .../plugins/wp-webauthn/js/default_wa.js | 70 + wp-content/plugins/wp-webauthn/js/frontend.js | 635 ++++ wp-content/plugins/wp-webauthn/js/login.js | 400 +++ wp-content/plugins/wp-webauthn/js/profile.js | 466 +++ .../wp-webauthn/languages/template.pot | 583 +++ .../languages/wp-webauthn-fr_FR.mo | Bin 0 -> 12337 bytes .../languages/wp-webauthn-fr_FR.po | 524 +++ .../languages/wp-webauthn-tr_TR.mo | Bin 0 -> 16201 bytes .../languages/wp-webauthn-tr_TR.po | 644 ++++ wp-content/plugins/wp-webauthn/readme.txt | 147 + .../plugins/wp-webauthn/vendor/autoload.php | 12 + .../beberlei/assert/.github/workflows/ci.yml | 64 + .../vendor/beberlei/assert/LICENSE | 11 + .../vendor/beberlei/assert/composer.json | 64 + .../beberlei/assert/lib/Assert/Assert.php | 85 + .../beberlei/assert/lib/Assert/Assertion.php | 2797 +++++++++++++++ .../assert/lib/Assert/AssertionChain.php | 247 ++ .../lib/Assert/AssertionFailedException.php | 32 + .../lib/Assert/InvalidArgumentException.php | 74 + .../assert/lib/Assert/LazyAssertion.php | 228 ++ .../lib/Assert/LazyAssertionException.php | 53 + .../beberlei/assert/lib/Assert/functions.php | 72 + .../vendor/brick/math/CHANGELOG.md | 415 +++ .../wp-webauthn/vendor/brick/math/LICENSE | 20 + .../wp-webauthn/vendor/brick/math/SECURITY.md | 17 + .../vendor/brick/math/composer.json | 35 + .../vendor/brick/math/src/BigDecimal.php | 895 +++++ .../vendor/brick/math/src/BigInteger.php | 1184 +++++++ .../vendor/brick/math/src/BigNumber.php | 572 +++ .../vendor/brick/math/src/BigRational.php | 523 +++ .../src/Exception/DivisionByZeroException.php | 41 + .../Exception/IntegerOverflowException.php | 27 + .../math/src/Exception/MathException.php | 14 + .../src/Exception/NegativeNumberException.php | 12 + .../src/Exception/NumberFormatException.php | 35 + .../Exception/RoundingNecessaryException.php | 21 + .../brick/math/src/Internal/Calculator.php | 756 ++++ .../Internal/Calculator/BcMathCalculator.php | 116 + .../src/Internal/Calculator/GmpCalculator.php | 156 + .../Internal/Calculator/NativeCalculator.php | 634 ++++ .../vendor/brick/math/src/RoundingMode.php | 107 + .../vendor/composer/ClassLoader.php | 572 +++ .../vendor/composer/InstalledVersions.php | 352 ++ .../wp-webauthn/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 673 ++++ .../vendor/composer/autoload_files.php | 103 + .../vendor/composer/autoload_namespaces.php | 9 + .../vendor/composer/autoload_psr4.php | 35 + .../vendor/composer/autoload_real.php | 55 + .../vendor/composer/autoload_static.php | 960 +++++ .../vendor/composer/installed.json | 2474 +++++++++++++ .../wp-webauthn/vendor/composer/installed.php | 311 ++ .../phpasn1/.github/workflows/phpunit.yml | 35 + .../vendor/fgrosse/phpasn1/CHANGELOG.md | 55 + .../vendor/fgrosse/phpasn1/LICENSE | 19 + .../vendor/fgrosse/phpasn1/README.md | 167 + .../vendor/fgrosse/phpasn1/composer.json | 49 + .../fgrosse/phpasn1/lib/ASN1/ASNObject.php | 355 ++ .../phpasn1/lib/ASN1/AbstractString.php | 136 + .../fgrosse/phpasn1/lib/ASN1/AbstractTime.php | 78 + .../fgrosse/phpasn1/lib/ASN1/Base128.php | 63 + .../ASN1/Composite/AttributeTypeAndValue.php | 35 + .../phpasn1/lib/ASN1/Composite/RDNString.php | 37 + .../Composite/RelativeDistinguishedName.php | 50 + .../fgrosse/phpasn1/lib/ASN1/Construct.php | 202 ++ .../Exception/NotImplementedException.php | 15 + .../lib/ASN1/Exception/ParserException.php | 29 + .../lib/ASN1/ExplicitlyTaggedObject.php | 131 + .../fgrosse/phpasn1/lib/ASN1/Identifier.php | 339 ++ .../vendor/fgrosse/phpasn1/lib/ASN1/OID.php | 199 ++ .../fgrosse/phpasn1/lib/ASN1/Parsable.php | 32 + .../phpasn1/lib/ASN1/TemplateParser.php | 70 + .../phpasn1/lib/ASN1/Universal/BMPString.php | 41 + .../phpasn1/lib/ASN1/Universal/BitString.php | 88 + .../phpasn1/lib/ASN1/Universal/Boolean.php | 75 + .../lib/ASN1/Universal/CharacterString.php | 28 + .../phpasn1/lib/ASN1/Universal/Enumerated.php | 21 + .../lib/ASN1/Universal/GeneralString.php | 34 + .../lib/ASN1/Universal/GeneralizedTime.php | 134 + .../lib/ASN1/Universal/GraphicString.php | 34 + .../phpasn1/lib/ASN1/Universal/IA5String.php | 35 + .../phpasn1/lib/ASN1/Universal/Integer.php | 130 + .../phpasn1/lib/ASN1/Universal/NullObject.php | 54 + .../lib/ASN1/Universal/NumericString.php | 38 + .../lib/ASN1/Universal/ObjectDescriptor.php | 26 + .../lib/ASN1/Universal/ObjectIdentifier.php | 138 + .../lib/ASN1/Universal/OctetString.php | 91 + .../lib/ASN1/Universal/PrintableString.php | 53 + .../Universal/RelativeObjectIdentifier.php | 57 + .../phpasn1/lib/ASN1/Universal/Sequence.php | 23 + .../phpasn1/lib/ASN1/Universal/Set.php | 21 + .../phpasn1/lib/ASN1/Universal/T61String.php | 36 + .../phpasn1/lib/ASN1/Universal/UTCTime.php | 77 + .../phpasn1/lib/ASN1/Universal/UTF8String.php | 34 + .../lib/ASN1/Universal/UniversalString.php | 36 + .../lib/ASN1/Universal/VisibleString.php | 34 + .../lib/ASN1/UnknownConstructedObject.php | 59 + .../phpasn1/lib/ASN1/UnknownObject.php | 59 + .../phpasn1/lib/Utility/BigInteger.php | 195 + .../phpasn1/lib/Utility/BigIntegerBcmath.php | 133 + .../phpasn1/lib/Utility/BigIntegerGmp.php | 133 + .../phpasn1/lib/X509/AlgorithmIdentifier.php | 22 + .../phpasn1/lib/X509/CSR/Attributes.php | 68 + .../fgrosse/phpasn1/lib/X509/CSR/CSR.php | 159 + .../lib/X509/CertificateExtensions.php | 100 + .../phpasn1/lib/X509/CertificateSubject.php | 108 + .../fgrosse/phpasn1/lib/X509/PrivateKey.php | 35 + .../fgrosse/phpasn1/lib/X509/PublicKey.php | 35 + .../fgrosse/phpasn1/lib/X509/SAN/DNSName.php | 28 + .../phpasn1/lib/X509/SAN/IPAddress.php | 73 + .../lib/X509/SAN/SubjectAlternativeNames.php | 96 + .../vendor/league/uri-interfaces/LICENSE | 20 + .../league/uri-interfaces/composer.json | 68 + .../src/Contracts/AuthorityInterface.php | 87 + .../src/Contracts/DataPathInterface.php | 92 + .../src/Contracts/DomainHostInterface.php | 107 + .../src/Contracts/FragmentInterface.php | 22 + .../src/Contracts/HostInterface.php | 51 + .../src/Contracts/IpHostInterface.php | 48 + .../src/Contracts/PathInterface.php | 90 + .../src/Contracts/PortInterface.php | 22 + .../src/Contracts/QueryInterface.php | 227 ++ .../src/Contracts/SegmentedPathInterface.php | 147 + .../src/Contracts/UriComponentInterface.php | 88 + .../src/Contracts/UriException.php | 20 + .../src/Contracts/UriInterface.php | 292 ++ .../src/Contracts/UserInfoInterface.php | 40 + .../src/Exceptions/FileinfoSupportMissing.php | 20 + .../src/Exceptions/IdnSupportMissing.php | 20 + .../src/Exceptions/IdnaConversionFailed.php | 46 + .../src/Exceptions/SyntaxError.php | 20 + .../league/uri-interfaces/src/Idna/Idna.php | 212 ++ .../uri-interfaces/src/Idna/IdnaInfo.php | 113 + .../vendor/league/uri/.php-cs-fixer.php | 58 + .../wp-webauthn/vendor/league/uri/LICENSE | 20 + .../vendor/league/uri/composer.json | 104 + .../Exceptions/TemplateCanNotBeExpanded.php | 29 + .../vendor/league/uri/src/Http.php | 335 ++ .../vendor/league/uri/src/HttpFactory.php | 25 + .../wp-webauthn/vendor/league/uri/src/Uri.php | 1397 ++++++++ .../vendor/league/uri/src/UriInfo.php | 205 ++ .../vendor/league/uri/src/UriResolver.php | 375 ++ .../vendor/league/uri/src/UriString.php | 466 +++ .../vendor/league/uri/src/UriTemplate.php | 140 + .../league/uri/src/UriTemplate/Expression.php | 353 ++ .../league/uri/src/UriTemplate/Template.php | 134 + .../uri/src/UriTemplate/VarSpecifier.php | 107 + .../uri/src/UriTemplate/VariableBag.php | 116 + .../league/uri/test_files/hello-world.txt | 1 + .../vendor/league/uri/test_files/john-doe.vcf | 25 + .../vendor/league/uri/test_files/red-nose.gif | Bin 0 -> 119 bytes .../nyholm/psr7-server/.github/FUNDING.yml | 3 + .../vendor/nyholm/psr7-server/CHANGELOG.md | 54 + .../vendor/nyholm/psr7-server/LICENSE | 21 + .../vendor/nyholm/psr7-server/README.md | 38 + .../vendor/nyholm/psr7-server/composer.json | 41 + .../psr7-server/src/ServerRequestCreator.php | 282 ++ .../src/ServerRequestCreatorInterface.php | 56 + .../vendor/nyholm/psr7/CHANGELOG.md | 132 + .../wp-webauthn/vendor/nyholm/psr7/LICENSE | 21 + .../wp-webauthn/vendor/nyholm/psr7/README.md | 110 + .../vendor/nyholm/psr7/composer.json | 48 + .../psr7/src/Factory/HttplugFactory.php | 45 + .../nyholm/psr7/src/Factory/Psr17Factory.php | 78 + .../vendor/nyholm/psr7/src/MessageTrait.php | 207 ++ .../vendor/nyholm/psr7/src/Request.php | 47 + .../vendor/nyholm/psr7/src/RequestTrait.php | 113 + .../vendor/nyholm/psr7/src/Response.php | 90 + .../vendor/nyholm/psr7/src/ServerRequest.php | 167 + .../vendor/nyholm/psr7/src/Stream.php | 306 ++ .../vendor/nyholm/psr7/src/UploadedFile.php | 179 + .../vendor/nyholm/psr7/src/Uri.php | 312 ++ .../php-http/message-factory/CHANGELOG.md | 65 + .../vendor/php-http/message-factory/LICENSE | 19 + .../vendor/php-http/message-factory/README.md | 36 + .../php-http/message-factory/composer.json | 27 + .../vendor/php-http/message-factory/puli.json | 43 + .../message-factory/src/MessageFactory.php | 12 + .../message-factory/src/RequestFactory.php | 34 + .../message-factory/src/ResponseFactory.php | 35 + .../message-factory/src/StreamFactory.php | 25 + .../message-factory/src/UriFactory.php | 24 + .../vendor/psr/http-client/CHANGELOG.md | 23 + .../vendor/psr/http-client/LICENSE | 19 + .../vendor/psr/http-client/README.md | 12 + .../vendor/psr/http-client/composer.json | 27 + .../src/ClientExceptionInterface.php | 10 + .../psr/http-client/src/ClientInterface.php | 20 + .../src/NetworkExceptionInterface.php | 24 + .../src/RequestExceptionInterface.php | 24 + .../vendor/psr/http-factory/.gitignore | 2 + .../vendor/psr/http-factory/.pullapprove.yml | 7 + .../vendor/psr/http-factory/LICENSE | 21 + .../vendor/psr/http-factory/README.md | 10 + .../vendor/psr/http-factory/composer.json | 35 + .../src/RequestFactoryInterface.php | 18 + .../src/ResponseFactoryInterface.php | 18 + .../src/ServerRequestFactoryInterface.php | 24 + .../src/StreamFactoryInterface.php | 45 + .../src/UploadedFileFactoryInterface.php | 34 + .../http-factory/src/UriFactoryInterface.php | 17 + .../vendor/psr/http-message/CHANGELOG.md | 36 + .../vendor/psr/http-message/LICENSE | 19 + .../vendor/psr/http-message/README.md | 13 + .../vendor/psr/http-message/composer.json | 26 + .../psr/http-message/src/MessageInterface.php | 187 + .../psr/http-message/src/RequestInterface.php | 129 + .../http-message/src/ResponseInterface.php | 68 + .../src/ServerRequestInterface.php | 261 ++ .../psr/http-message/src/StreamInterface.php | 158 + .../src/UploadedFileInterface.php | 123 + .../psr/http-message/src/UriInterface.php | 323 ++ .../wp-webauthn/vendor/psr/log/LICENSE | 19 + .../vendor/psr/log/Psr/Log/AbstractLogger.php | 128 + .../log/Psr/Log/InvalidArgumentException.php | 7 + .../vendor/psr/log/Psr/Log/LogLevel.php | 18 + .../psr/log/Psr/Log/LoggerAwareInterface.php | 18 + .../psr/log/Psr/Log/LoggerAwareTrait.php | 26 + .../psr/log/Psr/Log/LoggerInterface.php | 125 + .../vendor/psr/log/Psr/Log/LoggerTrait.php | 142 + .../vendor/psr/log/Psr/Log/NullLogger.php | 30 + .../vendor/psr/log/Psr/Log/Test/DummyTest.php | 18 + .../log/Psr/Log/Test/LoggerInterfaceTest.php | 138 + .../psr/log/Psr/Log/Test/TestLogger.php | 147 + .../wp-webauthn/vendor/psr/log/README.md | 58 + .../wp-webauthn/vendor/psr/log/composer.json | 26 + .../vendor/ramsey/collection/LICENSE | 19 + .../vendor/ramsey/collection/README.md | 82 + .../vendor/ramsey/collection/SECURITY.md | 113 + .../vendor/ramsey/collection/composer.json | 102 + .../ramsey/collection/src/AbstractArray.php | 209 ++ .../collection/src/AbstractCollection.php | 318 ++ .../ramsey/collection/src/AbstractSet.php | 50 + .../ramsey/collection/src/ArrayInterface.php | 51 + .../ramsey/collection/src/Collection.php | 106 + .../collection/src/CollectionInterface.php | 205 ++ .../collection/src/DoubleEndedQueue.php | 187 + .../src/DoubleEndedQueueInterface.php | 316 ++ .../Exception/CollectionMismatchException.php | 22 + .../Exception/InvalidArgumentException.php | 22 + .../Exception/InvalidSortOrderException.php | 22 + .../src/Exception/NoSuchElementException.php | 22 + .../src/Exception/OutOfBoundsException.php | 22 + .../UnsupportedOperationException.php | 22 + .../Exception/ValueExtractionException.php | 22 + .../ramsey/collection/src/GenericArray.php | 24 + .../ramsey/collection/src/Map/AbstractMap.php | 162 + .../collection/src/Map/AbstractTypedMap.php | 69 + .../src/Map/AssociativeArrayMap.php | 25 + .../collection/src/Map/MapInterface.php | 149 + .../collection/src/Map/NamedParameterMap.php | 120 + .../ramsey/collection/src/Map/TypedMap.php | 137 + .../collection/src/Map/TypedMapInterface.php | 35 + .../vendor/ramsey/collection/src/Queue.php | 169 + .../ramsey/collection/src/QueueInterface.php | 203 ++ .../vendor/ramsey/collection/src/Set.php | 69 + .../ramsey/collection/src/Tool/TypeTrait.php | 73 + .../src/Tool/ValueExtractorTrait.php | 58 + .../src/Tool/ValueToStringTrait.php | 94 + .../wp-webauthn/vendor/ramsey/uuid/LICENSE | 19 + .../wp-webauthn/vendor/ramsey/uuid/README.md | 83 + .../vendor/ramsey/uuid/composer.json | 107 + .../vendor/ramsey/uuid/src/BinaryUtils.php | 63 + .../uuid/src/Builder/BuilderCollection.php | 80 + .../uuid/src/Builder/DefaultUuidBuilder.php | 26 + .../uuid/src/Builder/DegradedUuidBuilder.php | 76 + .../uuid/src/Builder/FallbackBuilder.php | 74 + .../uuid/src/Builder/UuidBuilderInterface.php | 39 + .../ramsey/uuid/src/Codec/CodecInterface.php | 71 + .../ramsey/uuid/src/Codec/GuidStringCodec.php | 55 + .../uuid/src/Codec/OrderedTimeCodec.php | 113 + .../ramsey/uuid/src/Codec/StringCodec.php | 138 + .../src/Codec/TimestampFirstCombCodec.php | 113 + .../uuid/src/Codec/TimestampLastCombCodec.php | 51 + .../Converter/Number/BigNumberConverter.php | 57 + .../Number/DegradedNumberConverter.php | 25 + .../Number/GenericNumberConverter.php | 63 + .../Converter/NumberConverterInterface.php | 57 + .../Converter/Time/BigNumberTimeConverter.php | 51 + .../Converter/Time/DegradedTimeConverter.php | 25 + .../Converter/Time/GenericTimeConverter.php | 124 + .../src/Converter/Time/PhpTimeConverter.php | 183 + .../src/Converter/TimeConverterInterface.php | 58 + .../vendor/ramsey/uuid/src/DegradedUuid.php | 25 + .../uuid/src/DeprecatedUuidInterface.php | 147 + .../uuid/src/DeprecatedUuidMethodsTrait.php | 370 ++ .../Exception/BuilderNotFoundException.php | 24 + .../uuid/src/Exception/DateTimeException.php | 24 + .../src/Exception/DceSecurityException.php | 25 + .../Exception/InvalidArgumentException.php | 24 + .../src/Exception/InvalidBytesException.php | 24 + .../Exception/InvalidUuidStringException.php | 25 + .../uuid/src/Exception/NameException.php | 25 + .../uuid/src/Exception/NodeException.php | 24 + .../src/Exception/RandomSourceException.php | 27 + .../src/Exception/TimeSourceException.php | 24 + .../Exception/UnableToBuildUuidException.php | 24 + .../UnsupportedOperationException.php | 24 + .../src/Exception/UuidExceptionInterface.php | 21 + .../vendor/ramsey/uuid/src/FeatureSet.php | 449 +++ .../uuid/src/Fields/FieldsInterface.php | 32 + .../src/Fields/SerializableFieldsTrait.php | 86 + .../uuid/src/Generator/CombGenerator.php | 127 + .../src/Generator/DceSecurityGenerator.php | 160 + .../DceSecurityGeneratorInterface.php | 53 + .../src/Generator/DefaultNameGenerator.php | 48 + .../src/Generator/DefaultTimeGenerator.php | 147 + .../src/Generator/NameGeneratorFactory.php | 30 + .../src/Generator/NameGeneratorInterface.php | 38 + .../src/Generator/PeclUuidNameGenerator.php | 54 + .../src/Generator/PeclUuidRandomGenerator.php | 35 + .../src/Generator/PeclUuidTimeGenerator.php | 39 + .../src/Generator/RandomBytesGenerator.php | 45 + .../src/Generator/RandomGeneratorFactory.php | 30 + .../Generator/RandomGeneratorInterface.php | 30 + .../uuid/src/Generator/RandomLibAdapter.php | 55 + .../src/Generator/TimeGeneratorFactory.php | 63 + .../src/Generator/TimeGeneratorInterface.php | 38 + .../vendor/ramsey/uuid/src/Guid/Fields.php | 194 + .../vendor/ramsey/uuid/src/Guid/Guid.php | 61 + .../ramsey/uuid/src/Guid/GuidBuilder.php | 89 + .../uuid/src/Lazy/LazyUuidFromString.php | 575 +++ .../uuid/src/Math/BrickMathCalculator.php | 144 + .../uuid/src/Math/CalculatorInterface.php | 106 + .../ramsey/uuid/src/Math/RoundingMode.php | 146 + .../ramsey/uuid/src/Nonstandard/Fields.php | 133 + .../ramsey/uuid/src/Nonstandard/Uuid.php | 37 + .../uuid/src/Nonstandard/UuidBuilder.php | 88 + .../ramsey/uuid/src/Nonstandard/UuidV6.php | 133 + .../Dce/SystemDceSecurityProvider.php | 234 ++ .../Provider/DceSecurityProviderInterface.php | 41 + .../Provider/Node/FallbackNodeProvider.php | 60 + .../Provider/Node/NodeProviderCollection.php | 61 + .../src/Provider/Node/RandomNodeProvider.php | 69 + .../src/Provider/Node/StaticNodeProvider.php | 76 + .../src/Provider/Node/SystemNodeProvider.php | 173 + .../src/Provider/NodeProviderInterface.php | 30 + .../src/Provider/Time/FixedTimeProvider.php | 63 + .../src/Provider/Time/SystemTimeProvider.php | 33 + .../src/Provider/TimeProviderInterface.php | 28 + .../vendor/ramsey/uuid/src/Rfc4122/Fields.php | 194 + .../uuid/src/Rfc4122/FieldsInterface.php | 126 + .../ramsey/uuid/src/Rfc4122/NilTrait.php | 41 + .../ramsey/uuid/src/Rfc4122/NilUuid.php | 27 + .../ramsey/uuid/src/Rfc4122/UuidBuilder.php | 111 + .../ramsey/uuid/src/Rfc4122/UuidInterface.php | 36 + .../vendor/ramsey/uuid/src/Rfc4122/UuidV1.php | 92 + .../vendor/ramsey/uuid/src/Rfc4122/UuidV2.php | 143 + .../vendor/ramsey/uuid/src/Rfc4122/UuidV3.php | 58 + .../vendor/ramsey/uuid/src/Rfc4122/UuidV4.php | 58 + .../vendor/ramsey/uuid/src/Rfc4122/UuidV5.php | 58 + .../ramsey/uuid/src/Rfc4122/Validator.php | 49 + .../ramsey/uuid/src/Rfc4122/VariantTrait.php | 90 + .../ramsey/uuid/src/Rfc4122/VersionTrait.php | 57 + .../vendor/ramsey/uuid/src/Type/Decimal.php | 137 + .../ramsey/uuid/src/Type/Hexadecimal.php | 116 + .../vendor/ramsey/uuid/src/Type/Integer.php | 153 + .../ramsey/uuid/src/Type/NumberInterface.php | 28 + .../vendor/ramsey/uuid/src/Type/Time.php | 139 + .../ramsey/uuid/src/Type/TypeInterface.php | 30 + .../vendor/ramsey/uuid/src/Uuid.php | 664 ++++ .../vendor/ramsey/uuid/src/UuidFactory.php | 493 +++ .../ramsey/uuid/src/UuidFactoryInterface.php | 182 + .../vendor/ramsey/uuid/src/UuidInterface.php | 99 + .../uuid/src/Validator/GenericValidator.php | 50 + .../uuid/src/Validator/ValidatorInterface.php | 41 + .../vendor/ramsey/uuid/src/functions.php | 123 + .../spomky-labs/base64url/.github/FUNDING.yml | 2 + .../vendor/spomky-labs/base64url/LICENSE | 22 + .../spomky-labs/base64url/composer.json | 35 + .../spomky-labs/base64url/src/Base64Url.php | 56 + .../vendor/spomky-labs/cbor-php/LICENSE | 21 + .../vendor/spomky-labs/cbor-php/composer.json | 53 + .../cbor-php/src/AbstractCBORObject.php | 50 + .../cbor-php/src/ByteStringObject.php | 76 + .../src/ByteStringWithChunkObject.php | 21 + .../spomky-labs/cbor-php/src/CBORObject.php | 110 + .../spomky-labs/cbor-php/src/Decoder.php | 268 ++ .../cbor-php/src/DecoderInterface.php | 19 + .../src/IndefiniteLengthByteStringObject.php | 106 + .../src/IndefiniteLengthListObject.php | 167 + .../src/IndefiniteLengthMapObject.php | 201 ++ .../src/IndefiniteLengthTextStringObject.php | 106 + .../cbor-php/src/InfiniteListObject.php | 21 + .../cbor-php/src/InfiniteMapObject.php | 21 + .../cbor-php/src/LengthCalculator.php | 77 + .../spomky-labs/cbor-php/src/ListObject.php | 187 + .../spomky-labs/cbor-php/src/MapItem.php | 48 + .../spomky-labs/cbor-php/src/MapObject.php | 217 ++ .../cbor-php/src/NegativeIntegerObject.php | 136 + .../spomky-labs/cbor-php/src/Normalizable.php | 22 + .../spomky-labs/cbor-php/src/OtherObject.php | 52 + .../cbor-php/src/OtherObject/BreakObject.php | 47 + .../DoublePrecisionFloatObject.php | 97 + .../cbor-php/src/OtherObject/FalseObject.php | 53 + .../src/OtherObject/GenericObject.php | 43 + .../OtherObject/HalfPrecisionFloatObject.php | 97 + .../cbor-php/src/OtherObject/NullObject.php | 53 + .../src/OtherObject/OtherObjectManager.php | 59 + .../OtherObjectManagerInterface.php | 21 + .../cbor-php/src/OtherObject/SimpleObject.php | 79 + .../SinglePrecisionFloatObject.php | 96 + .../cbor-php/src/OtherObject/TrueObject.php | 53 + .../src/OtherObject/UndefinedObject.php | 49 + .../cbor-php/src/SignedIntegerObject.php | 21 + .../spomky-labs/cbor-php/src/Stream.php | 19 + .../spomky-labs/cbor-php/src/StringStream.php | 85 + .../vendor/spomky-labs/cbor-php/src/Tag.php | 99 + .../cbor-php/src/Tag/Base16EncodingTag.php | 57 + .../cbor-php/src/Tag/Base64EncodingTag.php | 63 + .../cbor-php/src/Tag/Base64Tag.php | 57 + .../cbor-php/src/Tag/Base64UrlEncodingTag.php | 58 + .../cbor-php/src/Tag/Base64UrlTag.php | 57 + .../cbor-php/src/Tag/BigFloatTag.php | 108 + .../cbor-php/src/Tag/CBOREncodingTag.php | 57 + .../spomky-labs/cbor-php/src/Tag/CBORTag.php | 54 + .../cbor-php/src/Tag/DatetimeTag.php | 84 + .../cbor-php/src/Tag/DecimalFractionTag.php | 114 + .../spomky-labs/cbor-php/src/Tag/EpochTag.php | 21 + .../cbor-php/src/Tag/GenericTag.php | 38 + .../spomky-labs/cbor-php/src/Tag/MimeTag.php | 66 + .../src/Tag/NegativeBigIntegerTag.php | 83 + .../src/Tag/PositiveBigIntegerTag.php | 21 + .../cbor-php/src/Tag/TagManager.php | 64 + .../cbor-php/src/Tag/TagManagerInterface.php | 22 + .../cbor-php/src/Tag/TagObjectManager.php | 21 + .../cbor-php/src/Tag/TimestampTag.php | 111 + .../src/Tag/UnsignedBigIntegerTag.php | 78 + .../spomky-labs/cbor-php/src/Tag/UriTag.php | 66 + .../spomky-labs/cbor-php/src/TagObject.php | 21 + .../cbor-php/src/TextStringObject.php | 76 + .../src/TextStringWithChunkObject.php | 21 + .../cbor-php/src/UnsignedIntegerObject.php | 139 + .../vendor/spomky-labs/cbor-php/src/Utils.php | 69 + .../vendor/symfony/polyfill-ctype/Ctype.php | 232 ++ .../vendor/symfony/polyfill-ctype/LICENSE | 19 + .../vendor/symfony/polyfill-ctype/README.md | 12 + .../symfony/polyfill-ctype/bootstrap.php | 50 + .../symfony/polyfill-ctype/bootstrap80.php | 46 + .../symfony/polyfill-ctype/composer.json | 41 + .../vendor/symfony/polyfill-php80/LICENSE | 19 + .../vendor/symfony/polyfill-php80/Php80.php | 115 + .../symfony/polyfill-php80/PhpToken.php | 103 + .../vendor/symfony/polyfill-php80/README.md | 24 + .../Resources/stubs/Attribute.php | 22 + .../Resources/stubs/PhpToken.php | 7 + .../Resources/stubs/Stringable.php | 11 + .../Resources/stubs/UnhandledMatchError.php | 7 + .../Resources/stubs/ValueError.php | 7 + .../symfony/polyfill-php80/bootstrap.php | 42 + .../symfony/polyfill-php80/composer.json | 40 + .../vendor/symfony/polyfill-php81/LICENSE | 19 + .../vendor/symfony/polyfill-php81/Php81.php | 37 + .../vendor/symfony/polyfill-php81/README.md | 16 + .../Resources/stubs/ReturnTypeWillChange.php | 11 + .../symfony/polyfill-php81/bootstrap.php | 28 + .../symfony/polyfill-php81/composer.json | 36 + .../vendor/symfony/process/CHANGELOG.md | 116 + .../process/Exception/ExceptionInterface.php | 21 + .../Exception/InvalidArgumentException.php | 21 + .../process/Exception/LogicException.php | 21 + .../Exception/ProcessFailedException.php | 54 + .../Exception/ProcessSignaledException.php | 41 + .../Exception/ProcessTimedOutException.php | 69 + .../process/Exception/RuntimeException.php | 21 + .../symfony/process/ExecutableFinder.php | 86 + .../vendor/symfony/process/InputStream.php | 96 + .../vendor/symfony/process/LICENSE | 19 + .../symfony/process/PhpExecutableFinder.php | 103 + .../vendor/symfony/process/PhpProcess.php | 72 + .../symfony/process/Pipes/AbstractPipes.php | 180 + .../symfony/process/Pipes/PipesInterface.php | 61 + .../symfony/process/Pipes/UnixPipes.php | 163 + .../symfony/process/Pipes/WindowsPipes.php | 204 ++ .../vendor/symfony/process/Process.php | 1652 +++++++++ .../vendor/symfony/process/ProcessUtils.php | 69 + .../vendor/symfony/process/README.md | 28 + .../vendor/symfony/process/composer.json | 29 + .../vendor/thecodingmachine/safe/LICENSE | 21 + .../vendor/thecodingmachine/safe/README.md | 178 + .../thecodingmachine/safe/composer.json | 123 + .../deprecated/Exceptions/ApcException.php | 11 + .../Exceptions/LibeventException.php | 11 + .../deprecated/Exceptions/MssqlException.php | 11 + .../deprecated/Exceptions/StatsException.php | 11 + .../thecodingmachine/safe/deprecated/apc.php | 238 ++ .../safe/deprecated/functionsList.php | 56 + .../safe/deprecated/libevent.php | 496 +++ .../safe/deprecated/mssql.php | 426 +++ .../safe/deprecated/stats.php | 108 + .../safe/generated/Exceptions/.gitkeep | 0 .../generated/Exceptions/ApacheException.php | 11 + .../generated/Exceptions/ApcuException.php | 11 + .../generated/Exceptions/ArrayException.php | 11 + .../generated/Exceptions/Bzip2Exception.php | 11 + .../Exceptions/CalendarException.php | 11 + .../Exceptions/ClassobjException.php | 11 + .../generated/Exceptions/ComException.php | 11 + .../generated/Exceptions/CubridException.php | 11 + .../Exceptions/DatetimeException.php | 11 + .../generated/Exceptions/DirException.php | 11 + .../generated/Exceptions/EioException.php | 11 + .../Exceptions/ErrorfuncException.php | 11 + .../generated/Exceptions/ExecException.php | 11 + .../Exceptions/FileinfoException.php | 11 + .../Exceptions/FilesystemException.php | 11 + .../generated/Exceptions/FilterException.php | 11 + .../generated/Exceptions/FpmException.php | 11 + .../generated/Exceptions/FtpException.php | 11 + .../Exceptions/FunchandException.php | 11 + .../generated/Exceptions/GmpException.php | 11 + .../generated/Exceptions/GnupgException.php | 11 + .../generated/Exceptions/HashException.php | 11 + .../generated/Exceptions/IbaseException.php | 11 + .../generated/Exceptions/IbmDb2Exception.php | 11 + .../generated/Exceptions/IconvException.php | 11 + .../generated/Exceptions/ImageException.php | 11 + .../generated/Exceptions/ImapException.php | 11 + .../generated/Exceptions/InfoException.php | 11 + .../Exceptions/IngresiiException.php | 11 + .../generated/Exceptions/InotifyException.php | 11 + .../generated/Exceptions/LdapException.php | 11 + .../generated/Exceptions/LibxmlException.php | 11 + .../generated/Exceptions/LzfException.php | 11 + .../Exceptions/MailparseException.php | 11 + .../Exceptions/MbstringException.php | 11 + .../generated/Exceptions/MiscException.php | 11 + .../generated/Exceptions/MsqlException.php | 11 + .../generated/Exceptions/MysqlException.php | 11 + .../generated/Exceptions/MysqliException.php | 11 + .../Exceptions/MysqlndMsException.php | 11 + .../Exceptions/MysqlndQcException.php | 11 + .../generated/Exceptions/NetworkException.php | 11 + .../generated/Exceptions/Oci8Exception.php | 11 + .../generated/Exceptions/OpcacheException.php | 11 + .../Exceptions/OutcontrolException.php | 11 + .../Exceptions/PasswordException.php | 11 + .../generated/Exceptions/PcntlException.php | 11 + .../generated/Exceptions/PdfException.php | 11 + .../generated/Exceptions/PgsqlException.php | 11 + .../generated/Exceptions/PosixException.php | 11 + .../safe/generated/Exceptions/PsException.php | 11 + .../generated/Exceptions/PspellException.php | 11 + .../Exceptions/ReadlineException.php | 11 + .../generated/Exceptions/RpminfoException.php | 11 + .../generated/Exceptions/RrdException.php | 11 + .../generated/Exceptions/SemException.php | 11 + .../generated/Exceptions/SessionException.php | 11 + .../generated/Exceptions/ShmopException.php | 11 + .../Exceptions/SimplexmlException.php | 11 + .../generated/Exceptions/SocketsException.php | 11 + .../generated/Exceptions/SodiumException.php | 11 + .../generated/Exceptions/SolrException.php | 11 + .../generated/Exceptions/SplException.php | 11 + .../generated/Exceptions/SqlsrvException.php | 11 + .../generated/Exceptions/SsdeepException.php | 11 + .../generated/Exceptions/Ssh2Exception.php | 11 + .../generated/Exceptions/StreamException.php | 11 + .../generated/Exceptions/StringsException.php | 11 + .../generated/Exceptions/SwooleException.php | 11 + .../generated/Exceptions/UodbcException.php | 11 + .../generated/Exceptions/UopzException.php | 11 + .../generated/Exceptions/UrlException.php | 11 + .../generated/Exceptions/VarException.php | 11 + .../generated/Exceptions/XdiffException.php | 11 + .../generated/Exceptions/XmlException.php | 11 + .../generated/Exceptions/XmlrpcException.php | 11 + .../generated/Exceptions/YamlException.php | 11 + .../generated/Exceptions/YazException.php | 11 + .../generated/Exceptions/ZipException.php | 11 + .../generated/Exceptions/ZlibException.php | 11 + .../safe/generated/apache.php | 177 + .../thecodingmachine/safe/generated/apcu.php | 112 + .../thecodingmachine/safe/generated/array.php | 464 +++ .../thecodingmachine/safe/generated/bzip2.php | 96 + .../safe/generated/calendar.php | 27 + .../safe/generated/classobj.php | 25 + .../thecodingmachine/safe/generated/com.php | 127 + .../safe/generated/cubrid.php | 395 +++ .../thecodingmachine/safe/generated/curl.php | 3156 +++++++++++++++++ .../safe/generated/datetime.php | 631 ++++ .../thecodingmachine/safe/generated/dir.php | 157 + .../thecodingmachine/safe/generated/eio.php | 2071 +++++++++++ .../safe/generated/errorfunc.php | 82 + .../thecodingmachine/safe/generated/exec.php | 159 + .../safe/generated/fileinfo.php | 75 + .../safe/generated/filesystem.php | 1488 ++++++++ .../safe/generated/filter.php | 93 + .../thecodingmachine/safe/generated/fpm.php | 22 + .../thecodingmachine/safe/generated/ftp.php | 496 +++ .../safe/generated/funchand.php | 47 + .../safe/generated/functionsList.php | 1070 ++++++ .../thecodingmachine/safe/generated/gmp.php | 87 + .../thecodingmachine/safe/generated/gnupg.php | 168 + .../thecodingmachine/safe/generated/hash.php | 61 + .../thecodingmachine/safe/generated/ibase.php | 633 ++++ .../safe/generated/ibmDb2.php | 1221 +++++++ .../thecodingmachine/safe/generated/iconv.php | 96 + .../thecodingmachine/safe/generated/image.php | 2704 ++++++++++++++ .../thecodingmachine/safe/generated/imap.php | 1481 ++++++++ .../thecodingmachine/safe/generated/info.php | 511 +++ .../safe/generated/ingres-ii.php | 720 ++++ .../safe/generated/inotify.php | 44 + .../thecodingmachine/safe/generated/json.php | 73 + .../thecodingmachine/safe/generated/ldap.php | 1603 +++++++++ .../safe/generated/libxml.php | 43 + .../thecodingmachine/safe/generated/lzf.php | 44 + .../safe/generated/mailparse.php | 127 + .../safe/generated/mbstring.php | 526 +++ .../thecodingmachine/safe/generated/misc.php | 464 +++ .../thecodingmachine/safe/generated/msql.php | 443 +++ .../thecodingmachine/safe/generated/mysql.php | 938 +++++ .../safe/generated/mysqli.php | 42 + .../safe/generated/mysqlndMs.php | 119 + .../safe/generated/mysqlndQc.php | 103 + .../safe/generated/network.php | 639 ++++ .../thecodingmachine/safe/generated/oci8.php | 1721 +++++++++ .../safe/generated/opcache.php | 42 + .../safe/generated/openssl.php | 1088 ++++++ .../safe/generated/outcontrol.php | 100 + .../safe/generated/password.php | 126 + .../thecodingmachine/safe/generated/pcntl.php | 166 + .../thecodingmachine/safe/generated/pcre.php | 659 ++++ .../thecodingmachine/safe/generated/pdf.php | 1553 ++++++++ .../thecodingmachine/safe/generated/pgsql.php | 1878 ++++++++++ .../thecodingmachine/safe/generated/posix.php | 329 ++ .../thecodingmachine/safe/generated/ps.php | 1812 ++++++++++ .../safe/generated/pspell.php | 451 +++ .../safe/generated/readline.php | 157 + .../safe/generated/rpminfo.php | 21 + .../thecodingmachine/safe/generated/rrd.php | 23 + .../thecodingmachine/safe/generated/sem.php | 367 ++ .../safe/generated/session.php | 153 + .../thecodingmachine/safe/generated/shmop.php | 68 + .../safe/generated/simplexml.php | 94 + .../safe/generated/sockets.php | 813 +++++ .../safe/generated/sodium.php | 58 + .../thecodingmachine/safe/generated/solr.php | 22 + .../thecodingmachine/safe/generated/spl.php | 139 + .../safe/generated/sqlsrv.php | 429 +++ .../safe/generated/ssdeep.php | 70 + .../thecodingmachine/safe/generated/ssh2.php | 641 ++++ .../safe/generated/stream.php | 609 ++++ .../safe/generated/strings.php | 846 +++++ .../safe/generated/swoole.php | 108 + .../thecodingmachine/safe/generated/uodbc.php | 1009 ++++++ .../thecodingmachine/safe/generated/uopz.php | 40 + .../thecodingmachine/safe/generated/url.php | 144 + .../thecodingmachine/safe/generated/var.php | 60 + .../thecodingmachine/safe/generated/xdiff.php | 236 ++ .../thecodingmachine/safe/generated/xml.php | 95 + .../safe/generated/xmlrpc.php | 22 + .../thecodingmachine/safe/generated/yaml.php | 97 + .../thecodingmachine/safe/generated/yaz.php | 438 +++ .../thecodingmachine/safe/generated/zip.php | 71 + .../thecodingmachine/safe/generated/zlib.php | 611 ++++ .../thecodingmachine/safe/lib/DateTime.php | 81 + .../safe/lib/DateTimeImmutable.php | 262 ++ .../safe/lib/Exceptions/CurlException.php | 15 + .../safe/lib/Exceptions/JsonException.php | 12 + .../safe/lib/Exceptions/OpensslException.php | 12 + .../safe/lib/Exceptions/PcreException.php | 21 + .../lib/Exceptions/SafeExceptionInterface.php | 9 + .../safe/lib/special_cases.php | 241 ++ .../safe/rector-migrate-0.7.php | 1081 ++++++ .../vendor/web-auth/cose-lib/LICENSE | 21 + .../vendor/web-auth/cose-lib/composer.json | 31 + .../cose-lib/src/Algorithm/Algorithm.php | 19 + .../cose-lib/src/Algorithm/Mac/HS256.php | 34 + .../src/Algorithm/Mac/HS256Truncated64.php | 34 + .../cose-lib/src/Algorithm/Mac/HS384.php | 34 + .../cose-lib/src/Algorithm/Mac/HS512.php | 34 + .../cose-lib/src/Algorithm/Mac/Hmac.php | 43 + .../cose-lib/src/Algorithm/Mac/Mac.php | 24 + .../cose-lib/src/Algorithm/Manager.php | 56 + .../cose-lib/src/Algorithm/ManagerFactory.php | 50 + .../src/Algorithm/Signature/ECDSA/ECDSA.php | 53 + .../Algorithm/Signature/ECDSA/ECSignature.php | 144 + .../src/Algorithm/Signature/ECDSA/ES256.php | 41 + .../src/Algorithm/Signature/ECDSA/ES256K.php | 41 + .../src/Algorithm/Signature/ECDSA/ES384.php | 41 + .../src/Algorithm/Signature/ECDSA/ES512.php | 41 + .../src/Algorithm/Signature/EdDSA/ED256.php | 40 + .../src/Algorithm/Signature/EdDSA/ED512.php | 40 + .../src/Algorithm/Signature/EdDSA/Ed25519.php | 24 + .../src/Algorithm/Signature/EdDSA/EdDSA.php | 65 + .../src/Algorithm/Signature/RSA/PS256.php | 31 + .../src/Algorithm/Signature/RSA/PS384.php | 31 + .../src/Algorithm/Signature/RSA/PS512.php | 31 + .../src/Algorithm/Signature/RSA/PSSRSA.php | 181 + .../src/Algorithm/Signature/RSA/RS1.php | 29 + .../src/Algorithm/Signature/RSA/RS256.php | 29 + .../src/Algorithm/Signature/RSA/RS384.php | 29 + .../src/Algorithm/Signature/RSA/RS512.php | 29 + .../src/Algorithm/Signature/RSA/RSA.php | 49 + .../src/Algorithm/Signature/Signature.php | 24 + .../web-auth/cose-lib/src/Algorithms.php | 123 + .../web-auth/cose-lib/src/BigInteger.php | 154 + .../vendor/web-auth/cose-lib/src/Hash.php | 103 + .../web-auth/cose-lib/src/Key/Ec2Key.php | 145 + .../vendor/web-auth/cose-lib/src/Key/Key.php | 91 + .../web-auth/cose-lib/src/Key/OkpKey.php | 67 + .../web-auth/cose-lib/src/Key/RsaKey.php | 207 ++ .../cose-lib/src/Key/SymmetricKey.php | 33 + .../vendor/web-auth/cose-lib/src/Verifier.php | 18 + .../vendor/web-auth/metadata-service/LICENSE | 21 + .../web-auth/metadata-service/composer.json | 39 + .../src/AbstractDescriptor.php | 49 + .../src/AuthenticatorStatus.php | 58 + .../src/BiometricAccuracyDescriptor.php | 108 + .../src/BiometricStatusReport.php | 118 + .../src/CodeAccuracyDescriptor.php | 73 + .../DisplayPNGCharacteristicsDescriptor.php | 172 + .../src/DistantSingleMetadata.php | 82 + .../metadata-service/src/EcdaaTrustAnchor.php | 123 + .../src/ExtensionDescriptor.php | 106 + .../metadata-service/src/MetadataService.php | 283 ++ .../src/MetadataStatement.php | 602 ++++ .../src/MetadataStatementFetcher.php | 85 + .../src/MetadataStatementRepository.php | 26 + .../src/MetadataTOCPayload.php | 142 + .../src/MetadataTOCPayloadEntry.php | 188 + .../src/PatternAccuracyDescriptor.php | 66 + .../metadata-service/src/RgbPaletteEntry.php | 84 + .../metadata-service/src/RogueListEntry.php | 67 + .../metadata-service/src/SingleMetadata.php | 53 + .../metadata-service/src/StatusReport.php | 166 + .../web-auth/metadata-service/src/Utils.php | 35 + .../src/VerificationMethodANDCombinations.php | 59 + .../src/VerificationMethodDescriptor.php | 168 + .../web-auth/metadata-service/src/Version.php | 80 + .../vendor/web-auth/webauthn-lib/LICENSE | 21 + .../web-auth/webauthn-lib/composer.json | 49 + .../AndroidKeyAttestationStatementSupport.php | 147 + ...idSafetyNetAttestationStatementSupport.php | 292 ++ .../AppleAttestationStatementSupport.php | 119 + .../AttestationObject.php | 81 + .../AttestationObjectLoader.php | 148 + .../AttestationStatement.php | 175 + .../AttestationStatementSupport.php | 28 + .../AttestationStatementSupportManager.php | 43 + .../FidoU2FAttestationStatementSupport.php | 118 + .../NoneAttestationStatementSupport.php | 42 + .../PackedAttestationStatementSupport.php | 194 + .../TPMAttestationStatementSupport.php | 309 ++ .../src/AttestedCredentialData.php | 113 + .../AuthenticationExtension.php | 59 + .../AuthenticationExtensionsClientInputs.php | 88 + .../AuthenticationExtensionsClientOutputs.php | 97 + ...nticationExtensionsClientOutputsLoader.php | 34 + .../ExtensionOutputChecker.php | 22 + .../ExtensionOutputCheckerHandler.php | 37 + .../ExtensionOutputError.php | 36 + .../src/AuthenticatorAssertionResponse.php | 64 + ...uthenticatorAssertionResponseValidator.php | 272 ++ .../src/AuthenticatorAttestationResponse.php | 38 + ...henticatorAttestationResponseValidator.php | 384 ++ .../webauthn-lib/src/AuthenticatorData.php | 124 + .../src/AuthenticatorResponse.php | 35 + .../src/AuthenticatorSelectionCriteria.php | 167 + .../CertificateChainChecker.php | 23 + .../OpenSSLCertificateChainChecker.php | 239 ++ .../webauthn-lib/src/CertificateToolbox.php | 223 ++ .../webauthn-lib/src/CollectedClientData.php | 145 + .../src/Counter/CounterChecker.php | 21 + .../src/Counter/ThrowExceptionIfInvalid.php | 46 + .../web-auth/webauthn-lib/src/Credential.php | 46 + .../webauthn-lib/src/PublicKeyCredential.php | 62 + .../PublicKeyCredentialCreationOptions.php | 261 ++ .../src/PublicKeyCredentialDescriptor.php | 112 + ...ublicKeyCredentialDescriptorCollection.php | 95 + .../src/PublicKeyCredentialEntity.php | 60 + .../src/PublicKeyCredentialLoader.php | 181 + .../src/PublicKeyCredentialOptions.php | 104 + .../src/PublicKeyCredentialParameters.php | 82 + .../src/PublicKeyCredentialRequestOptions.php | 194 + .../src/PublicKeyCredentialRpEntity.php | 62 + .../src/PublicKeyCredentialSource.php | 240 ++ .../PublicKeyCredentialSourceRepository.php | 26 + .../src/PublicKeyCredentialUserEntity.php | 87 + .../web-auth/webauthn-lib/src/Server.php | 351 ++ .../webauthn-lib/src/StringStream.php | 73 + .../IgnoreTokenBindingHandler.php | 24 + .../TokenBinding/SecTokenBindingHandler.php | 33 + .../src/TokenBinding/TokenBinding.php | 82 + .../src/TokenBinding/TokenBindingHandler.php | 21 + .../TokenBindingNotSupportedHandler.php | 25 + .../src/TrustPath/CertificateTrustPath.php | 61 + .../src/TrustPath/EcdaaKeyIdTrustPath.php | 55 + .../src/TrustPath/EmptyTrustPath.php | 35 + .../webauthn-lib/src/TrustPath/TrustPath.php | 24 + .../src/TrustPath/TrustPathLoader.php | 58 + .../webauthn-lib/src/U2FPublicKey.php | 46 + .../src/Util/CoseSignatureFixer.php | 54 + .../jwt-core/.github/CONTRIBUTING.md | 4 + .../web-token/jwt-core/.github/FUNDING.yml | 1 + .../jwt-core/.github/PULL_REQUEST_TEMPLATE.md | 3 + .../vendor/web-token/jwt-core/Algorithm.php | 29 + .../web-token/jwt-core/AlgorithmManager.php | 80 + .../jwt-core/AlgorithmManagerFactory.php | 80 + .../vendor/web-token/jwt-core/JWK.php | 146 + .../vendor/web-token/jwt-core/JWKSet.php | 340 ++ .../vendor/web-token/jwt-core/JWT.php | 23 + .../vendor/web-token/jwt-core/LICENSE | 21 + .../vendor/web-token/jwt-core/README.md | 15 + .../web-token/jwt-core/Util/BigInteger.php | 231 ++ .../vendor/web-token/jwt-core/Util/ECKey.php | 366 ++ .../web-token/jwt-core/Util/ECSignature.php | 143 + .../vendor/web-token/jwt-core/Util/Hash.php | 103 + .../web-token/jwt-core/Util/JsonConverter.php | 55 + .../web-token/jwt-core/Util/KeyChecker.php | 121 + .../vendor/web-token/jwt-core/Util/RSAKey.php | 315 ++ .../vendor/web-token/jwt-core/composer.json | 33 + .../jwt-key-mgmt/.github/CONTRIBUTING.md | 4 + .../jwt-key-mgmt/.github/FUNDING.yml | 1 + .../.github/PULL_REQUEST_TEMPLATE.md | 3 + .../Analyzer/AlgorithmAnalyzer.php | 26 + .../Analyzer/ES256KeyAnalyzer.php | 61 + .../Analyzer/ES384KeyAnalyzer.php | 61 + .../Analyzer/ES512KeyAnalyzer.php | 61 + .../Analyzer/HS256KeyAnalyzer.php | 35 + .../Analyzer/HS384KeyAnalyzer.php | 35 + .../Analyzer/HS512KeyAnalyzer.php | 35 + .../jwt-key-mgmt/Analyzer/KeyAnalyzer.php | 24 + .../Analyzer/KeyAnalyzerManager.php | 46 + .../Analyzer/KeyIdentifierAnalyzer.php | 26 + .../jwt-key-mgmt/Analyzer/KeysetAnalyzer.php | 24 + .../Analyzer/KeysetAnalyzerManager.php | 46 + .../jwt-key-mgmt/Analyzer/Message.php | 97 + .../jwt-key-mgmt/Analyzer/MessageBag.php | 71 + .../jwt-key-mgmt/Analyzer/MixedKeyTypes.php | 49 + .../Analyzer/MixedPublicAndPrivateKeys.php | 48 + .../jwt-key-mgmt/Analyzer/NoneAnalyzer.php | 28 + .../jwt-key-mgmt/Analyzer/OctAnalyzer.php | 32 + .../jwt-key-mgmt/Analyzer/RsaAnalyzer.php | 54 + .../jwt-key-mgmt/Analyzer/UsageAnalyzer.php | 32 + .../Analyzer/ZxcvbnKeyAnalyzer.php | 48 + .../web-token/jwt-key-mgmt/JKUFactory.php | 39 + .../web-token/jwt-key-mgmt/JWKFactory.php | 328 ++ .../jwt-key-mgmt/KeyConverter/ECKey.php | 307 ++ .../KeyConverter/KeyConverter.php | 272 ++ .../jwt-key-mgmt/KeyConverter/RSAKey.php | 263 ++ .../vendor/web-token/jwt-key-mgmt/LICENSE | 21 + .../vendor/web-token/jwt-key-mgmt/README.md | 15 + .../jwt-key-mgmt/UrlKeySetFactory.php | 58 + .../web-token/jwt-key-mgmt/X5UFactory.php | 56 + .../web-token/jwt-key-mgmt/composer.json | 34 + .../.github/CONTRIBUTING.md | 4 + .../.github/FUNDING.yml | 1 + .../.github/PULL_REQUEST_TEMPLATE.md | 3 + .../jwt-signature-algorithm-ecdsa/ECDSA.php | 80 + .../jwt-signature-algorithm-ecdsa/ES256.php | 32 + .../jwt-signature-algorithm-ecdsa/ES384.php | 32 + .../jwt-signature-algorithm-ecdsa/ES512.php | 32 + .../jwt-signature-algorithm-ecdsa/LICENSE | 21 + .../jwt-signature-algorithm-ecdsa/README.md | 15 + .../composer.json | 26 + .../.github/CONTRIBUTING.md | 4 + .../.github/FUNDING.yml | 1 + .../.github/PULL_REQUEST_TEMPLATE.md | 3 + .../jwt-signature-algorithm-eddsa/EdDSA.php | 107 + .../jwt-signature-algorithm-eddsa/LICENSE | 21 + .../jwt-signature-algorithm-eddsa/README.md | 15 + .../composer.json | 26 + .../.github/CONTRIBUTING.md | 4 + .../.github/FUNDING.yml | 1 + .../.github/PULL_REQUEST_TEMPLATE.md | 3 + .../jwt-signature-algorithm-rsa/LICENSE | 21 + .../jwt-signature-algorithm-rsa/PS256.php | 27 + .../jwt-signature-algorithm-rsa/PS384.php | 27 + .../jwt-signature-algorithm-rsa/PS512.php | 27 + .../jwt-signature-algorithm-rsa/README.md | 15 + .../jwt-signature-algorithm-rsa/RS256.php | 27 + .../jwt-signature-algorithm-rsa/RS384.php | 27 + .../jwt-signature-algorithm-rsa/RS512.php | 27 + .../jwt-signature-algorithm-rsa/RSA.php | 74 + .../jwt-signature-algorithm-rsa/RSAPKCS1.php | 75 + .../jwt-signature-algorithm-rsa/RSAPSS.php | 69 + .../jwt-signature-algorithm-rsa/Util/RSA.php | 251 ++ .../jwt-signature-algorithm-rsa/composer.json | 31 + .../jwt-signature/.github/CONTRIBUTING.md | 4 + .../jwt-signature/.github/FUNDING.yml | 1 + .../.github/PULL_REQUEST_TEMPLATE.md | 3 + .../jwt-signature/Algorithm/MacAlgorithm.php | 37 + .../Algorithm/SignatureAlgorithm.php | 37 + .../vendor/web-token/jwt-signature/JWS.php | 150 + .../web-token/jwt-signature/JWSBuilder.php | 235 ++ .../jwt-signature/JWSBuilderFactory.php | 41 + .../web-token/jwt-signature/JWSLoader.php | 124 + .../jwt-signature/JWSLoaderFactory.php | 59 + .../jwt-signature/JWSTokenSupport.php | 42 + .../web-token/jwt-signature/JWSVerifier.php | 170 + .../jwt-signature/JWSVerifierFactory.php | 41 + .../vendor/web-token/jwt-signature/LICENSE | 21 + .../vendor/web-token/jwt-signature/README.md | 15 + .../Serializer/CompactSerializer.php | 96 + .../Serializer/JSONFlattenedSerializer.php | 110 + .../Serializer/JSONGeneralSerializer.php | 167 + .../Serializer/JWSSerializer.php | 38 + .../Serializer/JWSSerializerManager.php | 86 + .../JWSSerializerManagerFactory.php | 63 + .../jwt-signature/Serializer/Serializer.php | 24 + .../web-token/jwt-signature/Signature.php | 134 + .../web-token/jwt-signature/composer.json | 33 + .../plugins/wp-webauthn/wp-webauthn.php | 83 + .../plugins/wp-webauthn/wwa-admin-content.php | 263 ++ wp-content/plugins/wp-webauthn/wwa-ajax.php | 1243 +++++++ .../plugins/wp-webauthn/wwa-compatibility.php | 6 + .../plugins/wp-webauthn/wwa-functions.php | 332 ++ wp-content/plugins/wp-webauthn/wwa-menus.php | 50 + .../wp-webauthn/wwa-profile-content.php | 148 + .../plugins/wp-webauthn/wwa-shortcodes.php | 181 + .../plugins/wp-webauthn/wwa-version.php | 6 + 923 files changed, 124568 insertions(+) create mode 100644 wp-content/plugins/wp-webauthn/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/blocks/blocks.build.js create mode 100644 wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-tr_TR-wwa_block_js.json create mode 100644 wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_CN-wwa_block_js.json create mode 100644 wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_HK-wwa_block_js.json create mode 100644 wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_TW-wwa_block_js.json create mode 100644 wp-content/plugins/wp-webauthn/css/admin.css create mode 100644 wp-content/plugins/wp-webauthn/css/frontend.css create mode 100644 wp-content/plugins/wp-webauthn/css/login.css create mode 100644 wp-content/plugins/wp-webauthn/js/admin.js create mode 100644 wp-content/plugins/wp-webauthn/js/default_wa.js create mode 100644 wp-content/plugins/wp-webauthn/js/frontend.js create mode 100644 wp-content/plugins/wp-webauthn/js/login.js create mode 100644 wp-content/plugins/wp-webauthn/js/profile.js create mode 100644 wp-content/plugins/wp-webauthn/languages/template.pot create mode 100644 wp-content/plugins/wp-webauthn/languages/wp-webauthn-fr_FR.mo create mode 100644 wp-content/plugins/wp-webauthn/languages/wp-webauthn-fr_FR.po create mode 100644 wp-content/plugins/wp-webauthn/languages/wp-webauthn-tr_TR.mo create mode 100644 wp-content/plugins/wp-webauthn/languages/wp-webauthn-tr_TR.po create mode 100644 wp-content/plugins/wp-webauthn/readme.txt create mode 100644 wp-content/plugins/wp-webauthn/vendor/autoload.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/.github/workflows/ci.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assert.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assertion.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionChain.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionFailedException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/InvalidArgumentException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertion.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertionException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/functions.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/SECURITY.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigDecimal.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigInteger.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigNumber.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigRational.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/DivisionByZeroException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/IntegerOverflowException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/MathException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/NegativeNumberException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/NumberFormatException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/RoundingNecessaryException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/brick/math/src/RoundingMode.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/ClassLoader.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/InstalledVersions.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/autoload_classmap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/autoload_files.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/autoload_namespaces.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/autoload_psr4.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/autoload_real.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/autoload_static.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/installed.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/composer/installed.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/.github/workflows/phpunit.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/OID.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigInteger.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerBcmath.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerGmp.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/HostInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PathInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PortInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/QueryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/Idna.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/IdnaInfo.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/.php-cs-fixer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/Exceptions/TemplateCanNotBeExpanded.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/Http.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/HttpFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/Uri.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriInfo.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriResolver.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Expression.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Template.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VarSpecifier.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VariableBag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/hello-world.txt create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/john-doe.vcf create mode 100644 wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/red-nose.gif create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreatorInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/HttplugFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/Psr17Factory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/MessageTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Request.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/RequestTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Response.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/ServerRequest.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Stream.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/UploadedFile.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Uri.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/puli.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/MessageFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/RequestFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/ResponseFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/StreamFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/UriFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/src/ClientExceptionInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/src/ClientInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/src/NetworkExceptionInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-client/src/RequestExceptionInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/.gitignore create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/.pullapprove.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/RequestFactoryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/ResponseFactoryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/StreamFactoryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/UriFactoryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/MessageInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/RequestInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/ResponseInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/ServerRequestInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/StreamInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/UploadedFileInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/UriInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/AbstractLogger.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/InvalidArgumentException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LogLevel.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LoggerAwareInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LoggerAwareTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LoggerInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LoggerTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/NullLogger.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/DummyTest.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/TestLogger.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/psr/log/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/SECURITY.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractArray.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractCollection.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractSet.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/ArrayInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Collection.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/CollectionInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueue.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/NoSuchElementException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/ValueExtractionException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/GenericArray.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractMap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractTypedMap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/MapInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/NamedParameterMap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMapInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Queue.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/QueueInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Set.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/TypeTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/BinaryUtils.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/BuilderCollection.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/CodecInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/StringCodec.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DegradedUuid.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/BuilderNotFoundException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DateTimeException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DceSecurityException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidArgumentException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidBytesException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NameException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NodeException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/RandomSourceException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/TimeSourceException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnableToBuildUuidException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnsupportedOperationException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UuidExceptionInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/FeatureSet.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/FieldsInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/CombGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Fields.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Guid.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/GuidBuilder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/CalculatorInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/RoundingMode.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Fields.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Uuid.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/NodeProviderInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/TimeProviderInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Fields.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Validator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Decimal.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Hexadecimal.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Integer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/NumberInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Time.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/TypeInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Uuid.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactoryInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/GenericValidator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/functions.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/src/Base64Url.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/AbstractCBORObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringWithChunkObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/CBORObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Decoder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/DecoderInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/InfiniteListObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/InfiniteMapObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/LengthCalculator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ListObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapItem.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/NegativeIntegerObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Normalizable.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/BreakObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/FalseObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/GenericObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/NullObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/TrueObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/SignedIntegerObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Stream.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/StringStream.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64Tag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/BigFloatTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBORTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DatetimeTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/EpochTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/GenericTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/MimeTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/PositiveBigIntegerTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/TagManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/TagObjectManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/TimestampTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UriTag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TagObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TextStringObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TextStringWithChunkObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/UnsignedIntegerObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Utils.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/Ctype.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap80.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Php80.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/PhpToken.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/bootstrap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Php81.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/bootstrap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/CHANGELOG.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ExceptionInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/InvalidArgumentException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/LogicException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessFailedException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessSignaledException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessTimedOutException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/RuntimeException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/ExecutableFinder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/InputStream.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpExecutableFinder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpProcess.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/AbstractPipes.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/PipesInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/UnixPipes.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/WindowsPipes.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/Process.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/ProcessUtils.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/symfony/process/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/Exceptions/ApcException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/Exceptions/LibeventException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/Exceptions/MssqlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/Exceptions/StatsException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/apc.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/functionsList.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/libevent.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/mssql.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/stats.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/.gitkeep create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ApacheException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ApcuException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ArrayException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/Bzip2Exception.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/CalendarException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ClassobjException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ComException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/CubridException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/DatetimeException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/DirException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/EioException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ErrorfuncException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ExecException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/FileinfoException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/FilesystemException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/FilterException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/FpmException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/FtpException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/FunchandException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/GmpException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/GnupgException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/HashException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/IbaseException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/IbmDb2Exception.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/IconvException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ImageException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ImapException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/InfoException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/IngresiiException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/InotifyException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/LdapException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/LibxmlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/LzfException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MailparseException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MbstringException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MiscException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MsqlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MysqlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MysqliException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MysqlndMsException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/MysqlndQcException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/NetworkException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/Oci8Exception.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/OpcacheException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/OutcontrolException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/PasswordException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/PcntlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/PdfException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/PgsqlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/PosixException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/PsException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/PspellException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ReadlineException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/RpminfoException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/RrdException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SemException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SessionException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ShmopException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SimplexmlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SocketsException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SodiumException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SolrException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SplException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SqlsrvException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SsdeepException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/Ssh2Exception.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/StreamException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/StringsException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/SwooleException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/UodbcException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/UopzException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/UrlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/VarException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/XdiffException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/XmlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/XmlrpcException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/YamlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/YazException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ZipException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/Exceptions/ZlibException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/apache.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/apcu.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/array.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/bzip2.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/calendar.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/classobj.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/com.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/cubrid.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/curl.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/datetime.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/dir.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/eio.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/errorfunc.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/exec.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/fileinfo.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/filesystem.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/filter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/fpm.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ftp.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/funchand.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/functionsList.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/gmp.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/gnupg.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/hash.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ibase.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ibmDb2.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/iconv.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/image.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/imap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/info.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ingres-ii.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/inotify.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/json.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ldap.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/libxml.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/lzf.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/mailparse.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/mbstring.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/misc.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/msql.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/mysql.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/mysqli.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/mysqlndMs.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/mysqlndQc.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/network.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/oci8.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/opcache.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/openssl.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/outcontrol.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/password.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pcntl.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pcre.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pdf.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pgsql.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/posix.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ps.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pspell.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/readline.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/rpminfo.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/rrd.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/sem.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/session.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/shmop.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/simplexml.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/sockets.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/sodium.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/solr.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/spl.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/sqlsrv.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ssdeep.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/ssh2.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/stream.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/strings.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/swoole.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/uodbc.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/uopz.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/url.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/var.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/xdiff.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/xml.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/xmlrpc.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/yaml.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/yaz.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/zip.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/zlib.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/DateTime.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/DateTimeImmutable.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/CurlException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/JsonException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/OpensslException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/PcreException.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/SafeExceptionInterface.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/special_cases.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/rector-migrate-0.7.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Algorithm.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/HS256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/HS384.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/HS512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/Mac.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Manager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/ManagerFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/Signature.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithms.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/BigInteger.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Hash.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Ec2Key.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Key.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/OkpKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/RsaKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/SymmetricKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Verifier.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AbstractDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AuthenticatorStatus.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/BiometricAccuracyDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/BiometricStatusReport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/CodeAccuracyDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DisplayPNGCharacteristicsDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DistantSingleMetadata.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/EcdaaTrustAnchor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/ExtensionDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataService.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatement.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementFetcher.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementRepository.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataTOCPayload.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataTOCPayloadEntry.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/PatternAccuracyDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RgbPaletteEntry.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RogueListEntry.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/SingleMetadata.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/StatusReport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Utils.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/VerificationMethodANDCombinations.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/VerificationMethodDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Version.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestedCredentialData.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorData.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorResponse.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateChainChecker/OpenSSLCertificateChainChecker.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateToolbox.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CollectedClientData.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Counter/CounterChecker.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Credential.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredential.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Server.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/StringStream.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/TrustPath.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/U2FPublicKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/.github/CONTRIBUTING.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Algorithm.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/AlgorithmManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/AlgorithmManagerFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWK.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWKSet.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWT.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/BigInteger.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECSignature.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/Hash.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/JsonConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/KeyChecker.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/RSAKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/CONTRIBUTING.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/AlgorithmAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES256KeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES384KeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES512KeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS256KeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS384KeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS512KeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzerManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyIdentifierAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzerManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/Message.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MessageBag.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedKeyTypes.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedPublicAndPrivateKeys.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/NoneAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/OctAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/RsaAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/UsageAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ZxcvbnKeyAnalyzer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JKUFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JWKFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/ECKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/KeyConverter.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/RSAKey.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/UrlKeySetFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/X5UFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/CONTRIBUTING.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ECDSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ES256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ES384.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ES512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/.github/CONTRIBUTING.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/EdDSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/CONTRIBUTING.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/PS256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/PS384.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/PS512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RS256.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RS384.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RS512.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPKCS1.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPSS.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/Util/RSA.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/composer.json create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/CONTRIBUTING.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/FUNDING.yml create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Algorithm/MacAlgorithm.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Algorithm/SignatureAlgorithm.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWS.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilder.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilderFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoader.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoaderFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSTokenSupport.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifier.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifierFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/LICENSE create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/README.md create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/CompactSerializer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializerManager.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/Serializer.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Signature.php create mode 100644 wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/composer.json create mode 100644 wp-content/plugins/wp-webauthn/wp-webauthn.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-admin-content.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-ajax.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-compatibility.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-functions.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-menus.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-profile-content.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-shortcodes.php create mode 100644 wp-content/plugins/wp-webauthn/wwa-version.php diff --git a/wp-content/plugins/wp-webauthn/LICENSE b/wp-content/plugins/wp-webauthn/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/wp-content/plugins/wp-webauthn/blocks/blocks.build.js b/wp-content/plugins/wp-webauthn/blocks/blocks.build.js new file mode 100644 index 00000000..e2b2005c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/blocks/blocks.build.js @@ -0,0 +1 @@ +!function(e){function t(a){if(n[a])return n[a].exports;var o=n[a]={i:a,l:!1,exports:{}};return e[a].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,a){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:a})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});n(1)},function(e,t,n){"use strict";var a=n(2),o=(n.n(a),wp.i18n.__),r=wp.blocks.registerBlockType;r("wp-webauthn/login",{title:o("WebAuthn Login Form","wp-webauthn"),icon:"admin-network",category:"widgets",keywords:["WebAuthn",o("Login Form","wp-webauthn")],attributes:{traditional:{type:"boolean",default:!0},username:{type:"string"},autoHide:{type:"boolean",default:!0},to:{type:"string"}},edit:function(e){var t=e.attributes,n=e.setAttributes,r=e.className;return wp.element.createElement("div",{className:r,style:{padding:"20px",boxSizing:"border-box",backgroundColor:"#F4F4F4",borderRadius:"3px"}},wp.element.createElement("span",{style:{fontSize:"15px",marginBottom:"20px",opacity:".5"}},o("WebAuthn Login Form","wp-webauthn")),wp.element.createElement(a.TextControl,{label:o("Default username","wp-webauthn"),value:t.username,onChange:function(e){n({username:e})}}),wp.element.createElement(a.TextControl,{label:o("Redirect to","wp-webauthn"),value:t.to,onChange:function(e){n({to:e})}}),wp.element.createElement(a.CheckboxControl,{label:o("Show password form as well","wp-webauthn"),checked:t.traditional,onChange:function(e){n({traditional:e})}}),wp.element.createElement(a.CheckboxControl,{label:o("Hide for logged-in users","wp-webauthn"),checked:t.autoHide,onChange:function(e){n({autoHide:e})}}))},save:function(e){var t=e.attributes;return'[wwa_login_form traditional="'+t.traditional+'" username="'+t.username+'" auto_hide="'+t.autoHide+'" to="'+t.to+'"]'}}),r("wp-webauthn/register",{title:o("WebAuthn Register Form","wp-webauthn"),icon:"plus-alt",category:"widgets",keywords:["WebAuthn",o("Register Form","wp-webauthn")],attributes:{display:{type:"boolean",default:!0}},edit:function(e){var t=e.attributes,n=e.setAttributes,r=e.className;return wp.element.createElement("div",{className:r,style:{padding:"20px",boxSizing:"border-box",backgroundColor:"#F4F4F4",borderRadius:"3px"}},wp.element.createElement("span",{style:{fontSize:"15px",marginBottom:"20px",opacity:".5"}},o("WebAuthn Register Form","wp-webauthn")),wp.element.createElement("div",{className:r,style:{height:"150px",display:"flex",justifyContent:"center",alignItems:"center"}},wp.element.createElement(a.CheckboxControl,{label:o("Show a message for users who doesn't logged-in","wp-webauthn"),checked:t.display,onChange:function(e){n({display:e})}})))},save:function(e){return'[wwa_register_form display="'+e.attributes.display+'"]'}}),r("wp-webauthn/verify",{title:o("WebAuthn Verify Buttons","wp-webauthn"),icon:"sos",category:"widgets",keywords:["WebAuthn",o("Verify Buttons","wp-webauthn")],attributes:{display:{type:"boolean",default:!0}},edit:function(e){var t=e.attributes,n=e.setAttributes,r=e.className;return wp.element.createElement("div",{className:r,style:{padding:"20px",boxSizing:"border-box",backgroundColor:"#F4F4F4",borderRadius:"3px"}},wp.element.createElement("span",{style:{fontSize:"15px",marginBottom:"20px",opacity:".5"}},o("WebAuthn Verify Buttons","wp-webauthn")),wp.element.createElement("div",{className:r,style:{height:"50px",display:"flex",justifyContent:"center",alignItems:"center"}},wp.element.createElement(a.CheckboxControl,{label:o("Show a message for users who doesn't logged-in","wp-webauthn"),checked:t.display,onChange:function(e){n({display:e})}})))},save:function(e){return'[wwa_verify_button display="'+e.attributes.display+'"]'}}),r("wp-webauthn/list",{title:o("WebAuthn Authenticator List","wp-webauthn"),icon:"menu",category:"widgets",keywords:["WebAuthn",o("Authenticator List","wp-webauthn")],attributes:{display:{type:"boolean",default:!0}},edit:function(e){var t=e.attributes,n=e.setAttributes,r=e.className;return wp.element.createElement("div",{className:r,style:{padding:"20px",boxSizing:"border-box",backgroundColor:"#F4F4F4",borderRadius:"3px"}},wp.element.createElement("span",{style:{fontSize:"15px",marginBottom:"20px",opacity:".5"}},o("WebAuthn Authenticator List","wp-webauthn")),wp.element.createElement("div",{className:r,style:{height:"150px",display:"flex",justifyContent:"center",alignItems:"center"}},wp.element.createElement(a.CheckboxControl,{label:o("Show a message for users who doesn't logged-in","wp-webauthn"),checked:t.display,onChange:function(e){n({display:e})}})))},save:function(e){return'[wwa_list display="'+e.attributes.display+'"]'}})},function(e,t){e.exports=wp.components}]); \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-tr_TR-wwa_block_js.json b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-tr_TR-wwa_block_js.json new file mode 100644 index 00000000..319ee248 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-tr_TR-wwa_block_js.json @@ -0,0 +1 @@ +{"translation-revision-date":"2021-04-23 19:43+0300","generator":"WP-CLI\/2.4.0","source":"wp-webauthn.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"tr_TR","plural-forms":"nplurals=2; plural=(n != 1);"},"WebAuthn Login Form":["WebAuthn Giri\u015f Formu"],"Login Form":["Giri\u015f Formu"],"Default username":["Varsay\u0131lan kullan\u0131c\u0131 ad\u0131"],"Redirect to":["\u015euraya y\u00f6nlendir"],"Show password form as well":["\u015eifre formunu da g\u00f6ster"],"Hide for logged-in users":["Giri\u015f yapm\u0131\u015f kullan\u0131c\u0131lar i\u00e7in gizle"],"WebAuthn Register Form":["WebAuthn Kay\u0131t Formu"],"Register Form":["Kay\u0131t Formu"],"Show a message for users who doesn't logged-in":["Giri\u015f yapmayan kullan\u0131c\u0131lar i\u00e7in bir mesaj g\u00f6ster"],"WebAuthn Verify Buttons":["WebAuthn Butonlar\u0131 Do\u011frula"],"Verify Buttons":["Butonlar\u0131 Do\u011frula"],"WebAuthn Authenticator List":["WebAuthn Kimlik Do\u011frulay\u0131c\u0131 Listesi"],"Authenticator List":["Kimlik Do\u011frulay\u0131c\u0131 Listesi"]}}} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_CN-wwa_block_js.json b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_CN-wwa_block_js.json new file mode 100644 index 00000000..059a1a62 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_CN-wwa_block_js.json @@ -0,0 +1 @@ +{"translation-revision-date":"YEAR-MO-DA HO:MI+ZONE","generator":"WP-CLI\/2.4.0","source":"wp-webauthn.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"WebAuthn Login Form":["WebAuthn \u767b\u5f55\u8868\u5355"],"Login Form":["\u767b\u5f55\u8868\u5355"],"Default username":["\u9ed8\u8ba4\u7528\u6237\u540d"],"Redirect to":["\u91cd\u5b9a\u5411\u5230"],"Show password form as well":["\u5305\u542b\u5bc6\u7801\u767b\u5f55\u8868\u5355"],"Hide for logged-in users":["\u5bf9\u5df2\u767b\u5f55\u7528\u6237\u9690\u85cf"],"WebAuthn Register Form":["WebAuthn \u7ed1\u5b9a\u8868\u5355"],"Register Form":["\u7ed1\u5b9a\u8868\u5355"],"Show a message for users who doesn't logged-in":["\u5411\u672a\u767b\u5f55\u7528\u6237\u663e\u793a\u4e00\u6761\u63d0\u793a"],"WebAuthn Verify Buttons":["WebAuthn \u6d4b\u8bd5\u6309\u94ae"],"Verify Buttons":["\u6d4b\u8bd5\u6309\u94ae"],"WebAuthn Authenticator List":["WebAuthn \u8ba4\u8bc1\u5668\u5217\u8868"],"Authenticator List":["\u8ba4\u8bc1\u5668\u5217\u8868"]}}} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_HK-wwa_block_js.json b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_HK-wwa_block_js.json new file mode 100644 index 00000000..27512220 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_HK-wwa_block_js.json @@ -0,0 +1 @@ +{"translation-revision-date":"YEAR-MO-DA HO:MI+ZONE","generator":"WP-CLI\/2.4.0","source":"wp-webauthn.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"WebAuthn Login Form":["WebAuthn \u767b\u5165\u8868\u55ae"],"Login Form":["\u767b\u5165\u8868\u55ae"],"Default username":["\u9810\u8a2d\u4f7f\u7528\u8005\u540d\u7a31"],"Redirect to":["\u91cd\u5b9a\u5411\u5230"],"Show password form as well":["\u5305\u542b\u5bc6\u78bc\u767b\u9304\u8868\u55ae"],"Hide for logged-in users":["\u5c0d\u5df2\u767b\u5165\u7684\u4f7f\u7528\u8005\u96b1\u85cf"],"WebAuthn Register Form":["WebAuthn \u7d81\u5b9a\u8868\u55ae"],"Register Form":["\u7d81\u5b9a\u8868\u55ae"],"Show a message for users who doesn't logged-in":["\u5411\u672a\u767b\u5165\u7684\u4f7f\u7528\u8005\u986f\u793a\u4e00\u689d\u63d0\u793a"],"WebAuthn Verify Buttons":["WebAuthn \u6e2c\u8a66\u6309\u9215"],"Verify Buttons":["\u6e2c\u8a66\u6309\u9215"],"WebAuthn Authenticator List":["WebAuthn \u8a8d\u8b49\u5668\u5217\u8868"],"Authenticator List":["\u8a8d\u8b49\u5668\u5217\u8868"]}}} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_TW-wwa_block_js.json b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_TW-wwa_block_js.json new file mode 100644 index 00000000..3de719e9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/blocks/languages/wp-webauthn-zh_TW-wwa_block_js.json @@ -0,0 +1 @@ +{"translation-revision-date":"YEAR-MO-DA HO:MI+ZONE","generator":"WP-CLI\/2.4.0","source":"wp-webauthn.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"WebAuthn Login Form":["WebAuthn \u767b\u5165\u8868\u55ae"],"Login Form":["\u767b\u5165\u8868\u55ae"],"Default username":["\u9810\u8a2d\u4f7f\u7528\u8005\u540d\u7a31"],"Redirect to":["\u91cd\u5b9a\u5411\u5230"],"Show password form as well":["\u5305\u542b\u5bc6\u78bc\u767b\u9304\u8868\u55ae"],"Hide for logged-in users":["\u5c0d\u5df2\u767b\u5165\u7684\u4f7f\u7528\u8005\u96b1\u85cf"],"WebAuthn Register Form":["WebAuthn \u8a3b\u518a\u8868\u55ae"],"Register Form":["\u8a3b\u518a\u8868\u55ae"],"Show a message for users who doesn't logged-in":["\u5411\u672a\u767b\u5165\u7684\u4f7f\u7528\u8005\u986f\u793a\u4e00\u689d\u63d0\u793a"],"WebAuthn Verify Buttons":["WebAuthn \u6e2c\u8a66\u6309\u9215"],"Verify Buttons":["\u6e2c\u8a66\u6309\u9215"],"WebAuthn Authenticator List":["WebAuthn \u9a57\u8b49\u5668\u5217\u8868"],"Authenticator List":["\u9a57\u8b49\u5668\u5217\u8868"]}}} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/css/admin.css b/wp-content/plugins/wp-webauthn/css/admin.css new file mode 100644 index 00000000..73f3bc3b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/css/admin.css @@ -0,0 +1,54 @@ +.wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column) { + display: table-cell; +} +#wwa-show-progress .wwa-success, #wwa-show-test .wwa-success, #wwa-show-test-usernameless .wwa-success { + color: #2C8D46; +} +#wwa-show-progress .wwa-failed, #wwa-show-test .wwa-failed, #wwa-show-test-usernameless .wwa-failed { + color: #CA4A1F; +} +#wwa-show-progress, #wwa-show-test, #wwa-show-test-usernameless { + vertical-align: sub; +} +#wwa_log { + max-width: 100%; + font-family: Consolas,"Source Code Pro","Liberation Mono","Courier New",Courier,"Noto Sans", "Helvetica Neue", Helvetica, "Nimbus Sans L", Arial, "Liberation Sans", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Source Han Sans SC", "Source Han Sans CN", "Microsoft YaHei",monospace; + white-space: pre; +} +#clear_log { + margin-top: 3px; +} +.wwa-table { + overflow-x: auto; +} +.wwa-table table { + min-width: 650px; +} +.wwa-table td a:nth-child(2) { + color: #a00; +} +.wwa-usernameless-th, .wwa-usernameless-td { + display: none; +} +#wwa-add-new-btn, #wwa-verify-btn, #wwa-test { + margin-top: 10px; +} +#wwa-show-test { + margin-top: 15px; + display: inline-block; +} +#wwa-new-block, #wwa-verify-block { + display: none; + padding: 0 20px 20px; + border: 1px solid #CCD0D4; + margin-top: 15px; + border-radius: 3px; + background-color: #ececec; +} +.wwa-cancel { + margin-top: 20px!important; + float: right; +} +#wp-webauthn-uv-warning { + margin: 15px 0 0; +} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/css/frontend.css b/wp-content/plugins/wp-webauthn/css/frontend.css new file mode 100644 index 00000000..f8f3b9f3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/css/frontend.css @@ -0,0 +1,260 @@ +.wwa-list-table { + table-layout: fixed; + border: 1px solid rgba(204, 208, 212, 0.7); + box-shadow: 0 1px 1px rgba(0,0,0,.04); + border-spacing: 0; + width: 100%; + clear: both; + margin: 0!important; + min-width: 700px; +} +.wwa-list-table * { + word-wrap: break-word; +} +.wwa-list-table td, .wwa-list-table th { + padding: 8px 10px; +} +.wwa-list-table tfoot td, .wwa-list-table tfoot th, .wwa-list-table thead td, .wwa-list-table thead th{ + line-height: 1.4em; +} +.wwa-list-table thead td, .wwa-list-table thead th { + border-bottom: 1px solid rgba(204, 208, 212, 0.7); +} +.wwa-list-table tfoot td, .wwa-list-table tfoot th { + border-top: 1px solid rgba(204, 208, 212, 0.7); + border-bottom: none; +} +.wwa-list-table tfoot td, .wwa-list-table th, .wwa-list-table thead td { + font-weight: 400; +} +.wwa-list-table tfoot td, .wwa-list-table th, .wwa-list-table thead td { + text-align: left; + line-height: 1.3em; + font-size: 14px; +} +.wwa-list-table > tbody > :nth-child(odd) { + background-color: rgba(127, 127, 127, .15); +} +.wwa-list-table td { + font-size: 13px; + line-height: 1.5em; +} +.wwa-list-table td { + vertical-align: top; +} +.wwa-bind-name-description, .wwa-bind-name-description, .wwa-bind-usernameless-description, .wwa-authenticator-list-usernameless-tip, .wwa-authenticator-list-type-tip { + opacity: .7; + font-size: 14px; +} +.wwa-authenticator-type, .wwa-authenticator-name { + margin-left: 15px; +} +.wwa-login-form { + max-width: 350px; + margin: 0 auto; + padding: 20px; + padding-bottom: 40px; +} +.wwa-login-form form p, .wwa-login-form-webauthn p { + margin-bottom: 0; + line-height: 1.5; +} +.wwa-login-form * { + margin: 0; + padding: 0; +} +.wwa-login-form label { + font-size: 14px; + line-height: 1.5; + display: inline-block; + margin-bottom: 3px; + vertical-align: middle; + cursor: pointer; +} +.wwa-login-form form .input, .wwa-login-form input[type="password"], .wwa-login-form input[type="text"] { + font-size: 24px; + line-height: 1.33333333; + width: 100%; + border-width: .0625rem; + padding: .1875rem .3125rem; + margin: 0 6px 16px 0; + min-height: 40px; + max-height: none; +} +.wwa-login-form input[type="password"], .wwa-login-form input[type="text"] { + padding: 0 8px; + line-height: 2; + height: 30px; + box-sizing: border-box; +} +.wwa-login-form input[type="password"], .wwa-login-form input[type="text"], .wwa-login-form select, .wwa-login-form textarea { + box-shadow: 0 0 0 transparent; + border-radius: 4px; + border: 1px solid rgba(126, 137, 147, 0.7); + color: #32373c; +} +.wwa-login-form form .login-remember { + font-weight: 400; + float: left; + display: block; + margin-bottom: 0; +} +.wwa-login-form input[type="checkbox"] { + border: 1px solid #7e8993; + border-radius: 4px; + background: #fff; + color: #555; + clear: none; + cursor: pointer; + display: inline-block; + line-height: 0; + height: 1rem; + margin: -.25rem .25rem 0 0; + outline: 0; + padding: 0 !important; + text-align: center; + vertical-align: middle; + width: 1rem; + min-width: 1rem; + -webkit-appearance: none; + box-shadow: inset 0 1px 2px rgba(0,0,0,.1); + transition: .05s border-color ease-in-out; +} +.wwa-login-form input[type="checkbox"]:checked::before { + content: url(data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.83%204.89l1.34.94-5.81%208.38H9.02L5.78%209.67l1.34-1.25%202.57%202.4z%27%20fill%3D%27%231e8cbe%27%2F%3E%3C%2Fsvg%3E); + margin: -.1875rem 0 0 -.25rem; + height: 1.3125rem; + width: 1.3125rem; + float: left; +} +.wwa-login-form .button-primary { + border-width: 0; + border-style: none; + padding: 0; + min-height: 32px; + line-height: 2.30769231; + padding: 0 12px; + vertical-align: baseline; + float: right; + background: #007cba; + border-color: #007cba; + color: #fff; + text-decoration: none; + text-shadow: none; +} +.wwa-login-form .button-primary, .wwa-login-form .button-secondary { + display: inline-block; + text-decoration: none; + font-size: 13px; + line-height: 2.15384615; + height: 30px; + margin: 0; + padding: 0 10px; + cursor: pointer; + border-width: 1px; + border-style: solid; + -webkit-appearance: none; + border-radius: 3px; + white-space: nowrap; + box-sizing: border-box; + margin-left: 5px; +} +.wwa-login-form .button-primary:focus, .wwa-login-form .button-primary:hover { + background: #0071a1; + border-color: #0071a1; + color: #fff; + outline: 2px solid transparent; + outline-offset: 0; +} +.wwa-login-form .button-primary:focus { + box-shadow: 0 0 0 1px #fff,0 0 0 3px #007cba; +} +.wwa-login-form .button-primary:active { + background: #00669b; + border-color: #00669b; + box-shadow: none; + color: #fff; +} +.wwa-login-form .button-primary:disabled, .wwa-login-form .button-primary[disabled] { + color: #66c6e4 !important; + background: #008ec2 !important; + border-color: #008ec2 !important; + box-shadow: none !important; + text-shadow: none !important; + cursor: default; +} +.wwa-show-test .success, .wwa-show-test-usernameless .success, .wwa-show-progress .success, .wwa-login-form .wwa-success { + color: #2C8D46; +} +.wwa-show-test .failed, .wwa-show-test-usernameless .failed, .wwa-show-progress .failed, .wwa-login-form .wwa-failed { + color: #CA4A1F; +} +.wwa-hide-form { + display: none; +} +.wwa-login-form-webauthn .wp-webauthn-notice { + text-align: center; + color: #72777c; + font-size: 18px; + padding-bottom: 20px; + justify-content: center; + align-items: center; + flex-direction: column; + display: flex; + line-height: 1; +} +.wp-webauthn-notice span { + line-height: 1; +} +.wp-webauthn-notice { + pointer-events: none; +} +.wwa-login-form-webauthn { + margin-bottom: 30px; +} +.wwa-t2w { + font-size: 14px; + color: #00719F; + text-decoration: underline; +} +.wwa-t2w > span { + cursor: pointer; +} +.wwa-w2t { + font-size: 14px; + float: left; + color: #00719F; + text-decoration: underline; + cursor: pointer; +} +.wwa-try-username { + margin-top: 3px; + font-size: 14px; + opacity: .7; + color: black; + pointer-events: none; +} +.wwa-table-container { + width: 100%; + overflow-y: auto; +} +.wwa-usernameless-th, .wwa-usernameless-td { + display: none; +} +#wwa-rememberme { + vertical-align: text-bottom; +} +.wwa-remember-label { + margin-bottom: 10px!important; + margin-top: 2px!important; +} +@media(max-width: 720px){ + .wwa-login-form .button-primary, .wwa-login-form .button-secondary { + padding: 0 14px; + line-height: 2.71428571; + font-size: 14px; + vertical-align: middle; + min-height: 40px; + margin-bottom: 4px; + } +} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/css/login.css b/wp-content/plugins/wp-webauthn/css/login.css new file mode 100644 index 00000000..bb1f8895 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/css/login.css @@ -0,0 +1,54 @@ +#wp-webauthn { + margin-right: 5px; +} +#wp-webauthn span { + line-height: 30px; +} +#wp-webauthn-check { + display: none!important; +} +.wp-webauthn-notice { + font-size: 18px; + text-align: center; + height: 74.25px; + justify-content: center; + align-items: center; + flex-direction: column; + margin-bottom: 10px; + opacity: .8; + display: none; + pointer-events: none; +} +.wp-webauthn-notice .wwa-success { + color: #2C8D46; +} +.wp-webauthn-notice .wwa-failed { + color: #CA4A1F; +} +.wwa-try-username { + margin-top: 3px; + font-size: 12px; + opacity: .7; + color: black; + pointer-events: none; +} +#loginform p.submit { + display: flex; + flex-direction: row-reverse; + width: max-content; + float: right; +} +#loginform .login .button-primary { + float: none; +} +#loginform .forgetmenot { + margin-bottom: 8px; +} +#loginform.wwa-webauthn-only { + padding-bottom: 30px; +} +@media(max-width: 782px){ + #wp-webauthn span { + line-height: 38px; + } +} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/js/admin.js b/wp-content/plugins/wp-webauthn/js/admin.js new file mode 100644 index 00000000..30418752 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/js/admin.js @@ -0,0 +1,85 @@ +jQuery(() => { + let div = document.getElementById('wwa_log'); + if (div !== null) { + div.scrollTop = div.scrollHeight; + if (jQuery('#wwa-remove-log').length === 0) { + setInterval(() => { + updateLog(); + }, 5000); + } + } + + jQuery('input[name=user_verification]').on('change', () => { + if (jQuery('input[name=user_verification]:checked').val() === 'false') { + jQuery('#wwa-uv-field').after(``); + } else { + jQuery('#wp-webauthn-uv-warning').remove(); + } + }); + + setTimeout(() => { + if (jQuery('input[name=user_verification]:checked').val() === 'false') { + jQuery('#wwa-uv-field').after(``); + } + }, 0); +}) + +// Update log +function updateLog() { + if (jQuery('#wwa_log').length === 0) { + return; + } + jQuery.ajax({ + url: php_vars.ajax_url, + type: 'GET', + data: { + action: 'wwa_get_log' + }, + success: function (data) { + if (typeof data === 'string') { + console.warn(data); + jQuery('#wwa_log').text(php_vars.i18n_3); + return; + } + if (data.length === 0) { + document.getElementById('clear_log').disabled = true; + jQuery('#wwa_log').text(''); + jQuery('#wwa-remove-log').remove(); + jQuery('#log-count').text(php_vars.i18n_2 + '0'); + return; + } + document.getElementById('clear_log').disabled = false; + let data_str = data.join('\n'); + if (data_str !== jQuery('#wwa_log').text()) { + jQuery('#wwa_log').text(data_str); + jQuery('#log-count').text(php_vars.i18n_2 + data.length); + let div = document.getElementById('wwa_log'); + div.scrollTop = div.scrollHeight; + } + }, + error: function () { + jQuery('#wwa_log').text(php_vars.i18n_3); + } + }) +} + +// Clear log +jQuery('#clear_log').click((e) => { + e.preventDefault(); + document.getElementById('clear_log').disabled = true; + jQuery.ajax({ + url: php_vars.ajax_url, + type: 'GET', + data: { + action: 'wwa_clear_log' + }, + success: function () { + updateLog(); + }, + error: function (data) { + document.getElementById('clear_log').disabled = false; + alert(`Error: ${data}`); + updateLog(); + } + }) +}) \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/js/default_wa.js b/wp-content/plugins/wp-webauthn/js/default_wa.js new file mode 100644 index 00000000..b9dff0b2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/js/default_wa.js @@ -0,0 +1,70 @@ +'use strict'; + +document.addEventListener('DOMContentLoaded', () => { + if (document.querySelectorAll('#lostpasswordform, #registerform, .admin-email-confirm-form').length > 0) { + return; + } + window.onload = () => { + if (php_vars.webauthn_only === 'true') { + if ((window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function')) { + // Not support, show a message + if (document.querySelectorAll('#login > h1').length > 0) { + let dom = document.createElement('p'); + dom.className = 'message'; + dom.innerHTML = php_vars.i18n_8; + document.querySelectorAll('#login > h1')[0].parentNode.insertBefore(dom, document.querySelectorAll('#login > h1')[0].nextElementSibling) + } + } + wwa_dom('#loginform', (dom) => { dom.classList.add('wwa-webauthn-only') }); + if (document.getElementsByClassName('user-pass-wrap').length > 0) { + wwa_dom('.user-pass-wrap, #wp-submit', (dom) => { dom.parentNode.removeChild(dom) }); + if (php_vars.remember_me === 'false' ) { + wwa_dom('.forgetmenot', (dom) => { dom.parentNode.removeChild(dom) }); + } + } else { + // WordPress 5.2- + wwa_dom('#wp-submit', (dom) => { dom.parentNode.removeChild(dom) }); + if (php_vars.remember_me === 'false' ) { + wwa_dom('.forgetmenot', (dom) => { dom.parentNode.removeChild(dom) }); + } + const targetDOM = document.getElementById('loginform').getElementsByTagName('p')[1]; + targetDOM.parentNode.removeChild(targetDOM); + } + } + if (!(window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') || php_vars.webauthn_only === 'true') { + // If supported, toggle + if (php_vars.webauthn_only !== 'true') { + if (document.getElementsByClassName('user-pass-wrap').length > 0) { + wwa_dom('.user-pass-wrap, #wp-submit', (dom) => { dom.style.display = 'none' }); + if (php_vars.remember_me === 'false' ) { + wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' }); + } + } else { + // WordPress 5.2- + wwa_dom('#wp-submit', (dom) => { dom.style.display = 'none' }); + if (php_vars.remember_me === 'false' ) { + wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' }); + } + document.getElementById('loginform').getElementsByTagName('p')[1].style.display = 'none'; + } + } + wwa_dom('wp-webauthn-notice', (dom) => { dom.style.display = 'flex' }, 'class'); + wwa_dom('wp-webauthn-check', (dom) => { dom.style.cssText = `${dom.style.cssText}display: block !important` }, 'id'); + wwa_dom('user_login', (dom) => { dom.focus() }, 'id'); + wwa_dom('wp-submit', (dom) => { dom.disabled = true }, 'id'); + } + if (document.querySelectorAll('#lostpasswordform, #registerform').length > 0) { + return; + } + wwa_dom('user_pass', (dom) => { dom.disabled = false }, 'id'); + let dom = document.querySelectorAll('#loginform label'); + if (dom.length > 0) { + if (dom[0].getElementsByTagName('input').length > 0) { + // WordPress 5.2- + dom[0].innerHTML = `${php_vars.i18n_9}${dom[0].innerHTML.split('
')[1]}`; + } else { + dom[0].innerText = php_vars.i18n_9; + } + } + } +}) \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/js/frontend.js b/wp-content/plugins/wp-webauthn/js/frontend.js new file mode 100644 index 00000000..5cd61d97 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/js/frontend.js @@ -0,0 +1,635 @@ +'use strict'; + +// Send an AJAX request and get the response +const wwa_ajax = function () { + let xmlHttpReq = new XMLHttpRequest(); + return { + /** Send an AJAX GET request and get the response + * + * @param {string} url URL + * @param {string} data Attached data + * @param {object} callback Callback function + */ + get: (url, data = '', callback = () => { }) => { + xmlHttpReq.open('GET', url + data, true); + xmlHttpReq.send(); + xmlHttpReq.onreadystatechange = () => { + if (xmlHttpReq.readyState === 4 && xmlHttpReq.status === 200) { + callback(xmlHttpReq.responseText, true); + } else if (xmlHttpReq.readyState === 4) { + callback('Network Error.', false); + } + } + }, + /** Send an AJAX POST request and get the response + * + * @param {string} url URL + * @param {string} data Attached data + * @param {object} callback Callback function + */ + post: (url, data = '', callback = () => { }) => { + xmlHttpReq.open('POST', url, true); + xmlHttpReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xmlHttpReq.send(data); + xmlHttpReq.onreadystatechange = () => { + if (xmlHttpReq.readyState === 4 && xmlHttpReq.status === 200) { + callback(xmlHttpReq.responseText, true); + } else if (xmlHttpReq.readyState === 4) { + callback('Network Error.', false); + } + } + } + } +}; + +/** Operate selected DOMs + * + * @param {string} selector DOM selector + * @param {object} callback Callbck function + * @param {string} method Selecte method + */ +const wwa_dom = (selector, callback = () => { }, method = 'query') => { + let dom_list = []; + if (method === 'id') { + let dom = document.getElementById(selector); + if (dom) { + callback(dom); + } + return; + } else if (method === 'class') { + dom_list = document.getElementsByClassName(selector); + } else if (method === 'tag') { + dom_list = document.getElementsByTagName(selector); + } else { + dom_list = document.querySelectorAll(selector); + } + for (let dom of dom_list) { + callback(dom); + } + return; +} + +/** Code Base64URL into Base64 + * + * @param {string} input Base64URL coded string + */ +function base64url2base64(input) { + input = input.replace(/=/g, '').replace(/-/g, '+').replace(/_/g, '/'); + const pad = input.length % 4; + if (pad) { + if (pad === 1) { + throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); + } + input += new Array(5 - pad).join('='); + } + return input; +} + +/** Code Uint8Array into Base64 string + * + * @param {Uint8Array} a The Uint8Array needed to be coded into Base64 string + */ +function arrayToBase64String(a) { + return btoa(String.fromCharCode(...a)); +} + +// Disable all WP-Webauthn buttons +function wwa_disable_buttons() { + wwa_dom('wwa-test-submit', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wwa-test-usernameless-submit', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wwa-bind-submit', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wwa-login-submit', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wp-submit', (dom) => { dom.disabled = true }, 'id'); +} + +// Enable all WP-Webauthn buttons +function wwa_enable_buttons() { + wwa_dom('wwa-test-submit', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-test-usernameless-submit', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-bind-submit', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-login-submit', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wp-submit', (dom) => { dom.disabled = false }, 'id'); +} + +document.addEventListener('DOMContentLoaded', () => { + wwa_dom('wwa-login-submit', (dom) => { dom.addEventListener('click', wwa_auth, false) }, 'class'); + // If traditional form exists + if (document.getElementsByClassName('wwa-login-form-traditional').length > 0) { + wwa_dom('.wwa-login-form-traditional .login-password', (dom) => { + let height = dom.clientHeight; + wwa_dom('.wwa-login-form-webauthn .wp-webauthn-notice', (ele) => { + ele.style.height = height - 40.4 + 'px'; + }); + }); + wwa_dom('wwa-w2t', (dom) => { dom.addEventListener('click', wwa_toggle, false) }, 'class'); + wwa_dom('wwa-t2w', (dom) => { dom.addEventListener('click', wwa_toggle, false) }, 'class'); + } else { + wwa_dom('.wwa-login-form-webauthn .wp-webauthn-notice', (ele) => { + ele.style.height = '40.6px'; + }); + wwa_dom('wwa-w2t', (dom) => { dom.parentNode.removeChild(document.getElementsByClassName('wwa-w2t')[0]) }, 'class'); + } + // If not support + if (window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') { + wwa_dom('wwa-test-submit', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wwa-test-usernameless-submit', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wwa-bind-submit', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wwa-show-test', (dom) => { dom.innerText = wwa_php_vars.i18n_31 }, 'class'); + wwa_dom('wwa-show-progress', (dom) => { dom.innerText = wwa_php_vars.i18n_31 }, 'class'); + if (document.getElementsByClassName('wwa-login-form-traditional').length > 0) { + wwa_dom('wwa-login-form-webauthn', (dom) => { dom.classList.add('wwa-hide-form') }, 'class'); + } + return; + } + wwa_dom('wwa-login-form-traditional', (dom) => { dom.classList.add('wwa-hide-form') }, 'class'); + wwa_dom('wwa-bind-submit', (dom) => { dom.addEventListener('click', wwa_bind, false) }, 'class'); + wwa_dom('wwa-test-submit', (dom) => { dom.addEventListener('click', wwa_verify, false) }, 'class'); + wwa_dom('wwa-test-usernameless-submit', (dom) => { dom.addEventListener('click', wwa_verify, false) }, 'class'); + updateList(); +}); + +// Toggle form +function wwa_toggle(e) { + e.preventDefault(); + if (document.getElementsByClassName('wwa-login-form-traditional').length > 0) { + // Disable buttons if it is not shown + if (document.getElementsByClassName('wwa-login-form-traditional')[0].className.indexOf('wwa-hide-form') !== -1) { + wwa_dom('wp-submit', (dom) => { dom.disabled = false }, 'id'); + wwa_dom('wwa-login-submit', (dom) => { dom.disabled = true }, 'class'); + setTimeout(() => { + wwa_dom('user_login', (dom) => { dom.focus() }, 'id'); + }, 0); + } else { + wwa_dom('wp-submit', (dom) => { dom.disabled = true }, 'id'); + wwa_dom('wwa-login-submit', (dom) => { dom.disabled = false }, 'class'); + setTimeout(() => { + wwa_dom('wwa-user-name', (dom) => { dom.focus() }, 'id'); + }, 0); + } + document.getElementsByClassName('wwa-login-form-traditional')[0].classList.toggle('wwa-hide-form'); + document.getElementsByClassName('wwa-login-form-webauthn')[0].classList.toggle('wwa-hide-form'); + } +} + +// Auth +function wwa_auth() { + if (window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') { + alert(wwa_php_vars.i18n_31); + return; + } + let wwa_username = this.parentNode.previousElementSibling.previousElementSibling.getElementsByClassName('wwa-user-name')[0].value; + if (wwa_username === '' && wwa_php_vars.usernameless !== 'true') { + alert(wwa_php_vars.i18n_11); + return; + } + wwa_dom('wwa-user-name', (dom) => { dom.readOnly = true }, 'class'); + wwa_disable_buttons(); + let button_dom = this; + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_3; + let request = wwa_ajax(); + request.get(wwa_php_vars.ajax_url, `?action=wwa_auth_start&user=${encodeURIComponent(wwa_username)}&type=auth`, (rawData, status) => { + if (status) { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_4; + let data = rawData; + try { + data = JSON.parse(rawData); + } catch (e) { + console.warn(rawData); + wwa_enable_buttons(); + if (wwa_php_vars.usernameless === 'true' && wwa_username === '') { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7 + wwa_php_vars.i18n_33; + } else { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7; + } + wwa_dom('wwa-user-name', (dom) => { dom.readOnly = false }, 'class'); + return; + } + data.challenge = Uint8Array.from(window.atob(base64url2base64(data.challenge)), (c) => c.charCodeAt(0)); + + if (data.allowCredentials) { + data.allowCredentials = data.allowCredentials.map((item) => { + item.id = Uint8Array.from(window.atob(base64url2base64(item.id)), (c) => c.charCodeAt(0)); + return item; + }); + } + + // Save client ID + const clientID = data.clientID; + delete data.clientID; + + navigator.credentials.get({ 'publicKey': data }).then((credentialInfo) => { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_5; + return credentialInfo; + }).then((data) => { + const publicKeyCredential = { + id: data.id, + type: data.type, + rawId: arrayToBase64String(new Uint8Array(data.rawId)), + response: { + authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)), + clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), + signature: arrayToBase64String(new Uint8Array(data.response.signature)), + userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null + } + }; + return publicKeyCredential; + }).then(JSON.stringify).then((AuthenticatorResponse) => { + let response = wwa_ajax(); + response.post(`${wwa_php_vars.ajax_url}?action=wwa_auth`, `data=${encodeURIComponent(window.btoa(AuthenticatorResponse))}&type=auth&clientid=${clientID}&user=${encodeURIComponent(wwa_username)}&remember=${wwa_php_vars.remember_me === 'false' ? 'false' : (document.getElementById('wwa-rememberme') ? (document.getElementById('wwa-rememberme').checked ? 'true' : 'false') : 'false')}`, (data, status) => { + if (status) { + if (data === 'true') { + wwa_enable_buttons(); + wwa_dom('wwa-user-name', (dom) => { dom.readOnly = false }, 'class'); + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_6; + if (document.querySelectorAll('p.login-submit input[name="redirect_to"]').length > 0) { + setTimeout(() => { + window.location.href = document.querySelectorAll('p.login-submit input[name="redirect_to"]')[0].value; + }, 200); + } else { + if (document.getElementsByClassName('wwa-redirect-to').length > 0) { + setTimeout(() => { + window.location.href = document.getElementsByClassName('wwa-redirect-to')[0].value; + }, 200); + } else { + setTimeout(() => { + window.location.reload(); + }, 200); + } + } + } else { + wwa_enable_buttons(); + if (wwa_php_vars.usernameless === 'true' && wwa_username === '') { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7 + wwa_php_vars.i18n_33; + } else { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7; + } + wwa_dom('wwa-user-name', (dom) => { dom.readOnly = false }, 'class'); + } + } else { + wwa_enable_buttons(); + if (wwa_php_vars.usernameless === 'true' && wwa_username === '') { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7 + wwa_php_vars.i18n_33; + } else { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7; + } + wwa_dom('wwa-user-name', (dom) => { dom.readOnly = false }, 'class'); + } + }) + }).catch((error) => { + console.warn(error); + wwa_enable_buttons(); + if (wwa_php_vars.usernameless === 'true' && wwa_username === '') { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7 + wwa_php_vars.i18n_33; + } else { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7; + } + wwa_dom('wwa-user-name', (dom) => { dom.readOnly = false }, 'class'); + }) + } else { + wwa_enable_buttons(); + if (wwa_php_vars.usernameless === 'true' && wwa_username === '') { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7 + wwa_php_vars.i18n_33; + } else { + button_dom.parentNode.previousElementSibling.innerHTML = wwa_php_vars.i18n_7; + } + wwa_dom('wwa-user-name', (dom) => { dom.readOnly = false }, 'class'); + } + }) +} + +// Bind +function wwa_bind() { + let button_dom = this; + let wwa_name = this.parentNode.parentNode.getElementsByClassName('wwa-authenticator-name')[0].value; + if (wwa_name === '') { + alert(wwa_php_vars.i18n_12); + return; + } + let wwa_type = this.parentNode.parentNode.getElementsByClassName('wwa-authenticator-type')[0].value; + let wwa_usernameless = this.parentNode.parentNode.querySelectorAll('.wwa-authenticator-usernameless:checked')[0] ? this.parentNode.parentNode.querySelectorAll('.wwa-authenticator-usernameless:checked')[0].value : 'false'; + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_3; + wwa_disable_buttons(); + // Lock options + wwa_dom('wwa-authenticator-name', (dom) => { dom.readOnly = true }, 'class'); + wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = true }, 'class'); + wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = true }, 'class'); + let request = wwa_ajax(); + request.get(wwa_php_vars.ajax_url, `?action=wwa_create&name=${encodeURIComponent(wwa_name)}&type=${encodeURIComponent(wwa_type)}&usernameless=${wwa_usernameless}`, (rawData, status) => { + if (status) { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_28; + let data = rawData; + try { + data = JSON.parse(rawData); + } catch (e) { + console.warn(rawData); + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_30; + wwa_enable_buttons(); + wwa_dom('wwa-authenticator-name', (dom) => { dom.readOnly = false }, 'class'); + wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = false }, 'class'); + updateList(); + return; + } + let challenge = new Uint8Array(32); + let user_id = new Uint8Array(32); + challenge = Uint8Array.from(window.atob(base64url2base64(data.challenge)), (c) => c.charCodeAt(0)); + user_id = Uint8Array.from(window.atob(base64url2base64(data.user.id)), (c) => c.charCodeAt(0)); + + let public_key = { + challenge: challenge, + rp: { + id: data.rp.id, + name: data.rp.name + }, + user: { + id: user_id, + name: data.user.name, + displayName: data.user.displayName + }, + pubKeyCredParams: data.pubKeyCredParams, + authenticatorSelection: data.authenticatorSelection, + timeout: data.timeout + } + + // If some authenticators are already registered, exclude + if (data.excludeCredentials) { + public_key.excludeCredentials = data.excludeCredentials.map((item) => { + item.id = Uint8Array.from(window.atob(base64url2base64(item.id)), (c) => c.charCodeAt(0)); + return item; + }) + } + + // Save client ID + const clientID = data.clientID; + delete data.clientID; + + // Create, a pop-up window should appear + navigator.credentials.create({ 'publicKey': public_key }).then((newCredentialInfo) => { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_32; + return newCredentialInfo; + }).then((data) => { + // Code Uint8Array into string for transmission + const publicKeyCredential = { + id: data.id, + type: data.type, + rawId: arrayToBase64String(new Uint8Array(data.rawId)), + response: { + clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), + attestationObject: arrayToBase64String(new Uint8Array(data.response.attestationObject)) + } + }; + return publicKeyCredential; + }).then(JSON.stringify).then((AuthenticatorAttestationResponse) => { + let response = wwa_ajax(); + response.post(`${wwa_php_vars.ajax_url}?action=wwa_create_response`, `data=${encodeURIComponent(window.btoa(AuthenticatorAttestationResponse))}&name=${encodeURIComponent(wwa_name)}&type=${encodeURIComponent(wwa_type)}&usernameless=${wwa_usernameless}&clientid=${clientID}`, (rawData, status) => { + if (status) { + if (rawData === 'true') { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_29; + wwa_enable_buttons(); + wwa_dom('wwa-authenticator-name', (dom) => { dom.readOnly = false; dom.value = '' }, 'class'); + wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = false }, 'class'); + updateList(); + } else { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_30; + wwa_enable_buttons(); + wwa_dom('wwa-authenticator-name', (dom) => { dom.readOnly = false }, 'class'); + wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = false }, 'class'); + updateList(); + } + } else { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_30; + wwa_enable_buttons(); + wwa_dom('wwa-authenticator-name', (dom) => { dom.readOnly = false }, 'class'); + wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = false }, 'class'); + updateList(); + } + }) + }).catch((error) => { + console.warn(error); + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_30; + wwa_enable_buttons(); + wwa_dom('wwa-authenticator-name', (dom) => { dom.readOnly = false }, 'class'); + wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = false }, 'class'); + updateList(); + }) + } else { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_30; + wwa_enable_buttons(); + wwa_dom('wwa-authenticator-name', (dom) => { dom.readOnly = false }, 'class'); + wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = false }, 'class'); + wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = false }, 'class'); + updateList(); + } + }) +} + +// Verify +function wwa_verify() { + let button_dom = this; + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_3; + let usernameless = this.className.indexOf('wwa-test-usernameless-submit') === -1 ? false : true; + wwa_disable_buttons(); + let request = wwa_ajax(); + request.get(wwa_php_vars.ajax_url, `?action=wwa_auth_start&type=test&usernameless=${usernameless ? 'true' : 'false'}`, (rawData, status) => { + if (status) { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_4; + if (rawData === 'User not inited.') { + wwa_enable_buttons(); + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_15; + return; + } + let data = rawData; + try { + data = JSON.parse(rawData); + } catch (e) { + console.warn(rawData); + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_15; + wwa_enable_buttons(); + return; + } + data.challenge = Uint8Array.from(window.atob(base64url2base64(data.challenge)), (c) => c.charCodeAt(0)); + + if (data.allowCredentials) { + data.allowCredentials = data.allowCredentials.map((item) => { + item.id = Uint8Array.from(window.atob(base64url2base64(item.id)), (c) => c.charCodeAt(0)); + return item; + }); + } + + if (data.allowCredentials && wwa_php_vars.allow_authenticator_type && wwa_php_vars.allow_authenticator_type !== 'none') { + for (let credential of data.allowCredentials) { + if (wwa_php_vars.allow_authenticator_type === 'cross-platform') { + credential.transports = ['usb', 'nfc', 'ble']; + } else if (wwa_php_vars.allow_authenticator_type === 'platform') { + credential.transports = ['internal']; + } + } + } + + // Save client ID + const clientID = data.clientID; + delete data.clientID; + + navigator.credentials.get({ 'publicKey': data }).then((credentialInfo) => { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_13; + return credentialInfo; + }).then((data) => { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_14; + const publicKeyCredential = { + id: data.id, + type: data.type, + rawId: arrayToBase64String(new Uint8Array(data.rawId)), + response: { + authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)), + clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), + signature: arrayToBase64String(new Uint8Array(data.response.signature)), + userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null + } + }; + return publicKeyCredential; + }).then(JSON.stringify).then((AuthenticatorResponse) => { + let response = wwa_ajax(); + response.post(`${wwa_php_vars.ajax_url}?action=wwa_auth`, `data=${encodeURIComponent(window.btoa(AuthenticatorResponse))}&type=test&remember=false&clientid=${clientID}`, (rawData, status) => { + if (status) { + if (rawData === 'true') { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_16; + wwa_enable_buttons(); + updateList(); + } else { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_15; + wwa_enable_buttons(); + } + } else { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_15; + wwa_enable_buttons(); + } + }) + }).catch((error) => { + console.warn(error); + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_15; + wwa_enable_buttons(); + }) + } else { + button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_15; + wwa_enable_buttons(); + } + }) +} + +// Update authenticator list +function updateList() { + if (document.getElementsByClassName('wwa-authenticator-list').length === 0) { + return; + } + let request = wwa_ajax(); + request.get(wwa_php_vars.ajax_url, '?action=wwa_authenticator_list', (rawData, status) => { + if (status) { + let data = rawData; + try { + data = JSON.parse(rawData); + } catch (e) { + console.warn(rawData); + wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `${wwa_php_vars.i18n_17}` }, 'class'); + return; + } + if (data.length === 0) { + if (wwa_php_vars.usernameless === 'true') { + wwa_dom('.wwa-usernameless-th, .wwa-usernameless-td', (dom) => { dom.style.display = 'table-cell' }); + } else { + wwa_dom('.wwa-usernameless-th, .wwa-usernameless-td', (dom) => { dom.style.display = 'none' }); + } + wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `${wwa_php_vars.i18n_23}` }, 'class'); + wwa_dom('wwa-authenticator-list-usernameless-tip', (dom) => { dom.innerText = '' }, 'class'); + wwa_dom('wwa-authenticator-list-type-tip', (dom) => { dom.innerText = '' }, 'class'); + return; + } + let htmlStr = ''; + let has_usernameless = false; + let has_disabled_type = false; + for (let item of data) { + let item_type_disabled = false; + if (item.usernameless) { + has_usernameless = true; + } + if (wwa_php_vars.allow_authenticator_type !== 'none') { + if (wwa_php_vars.allow_authenticator_type !== item.type) { + has_disabled_type = true; + item_type_disabled = true; + } + } + htmlStr += `${item.name}${item.type === 'none' ? wwa_php_vars.i18n_24 : (item.type === 'platform' ? wwa_php_vars.i18n_25 : wwa_php_vars.i18n_26)}${item_type_disabled ? wwa_php_vars.i18n_35 : ''}${item.added}${item.last_used}${item.usernameless ? wwa_php_vars.i18n_1 + (wwa_php_vars.usernameless === 'true' ? '' : wwa_php_vars.i18n_9) : wwa_php_vars.i18n_8}${wwa_php_vars.i18n_20} | ${wwa_php_vars.i18n_27}`; + } + wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = htmlStr }, 'class'); + if (has_usernameless || wwa_php_vars.usernameless === 'true') { + wwa_dom('.wwa-usernameless-th, .wwa-usernameless-td', (dom) => { dom.style.display = 'table-cell' }); + } else { + wwa_dom('.wwa-usernameless-th, .wwa-usernameless-td', (dom) => { dom.style.display = 'none' }); + } + if (has_usernameless && wwa_php_vars.usernameless !== 'true') { + wwa_dom('wwa-authenticator-list-usernameless-tip', (dom) => { dom.innerText = wwa_php_vars.i18n_10 }, 'class'); + wwa_dom('wwa-authenticator-list-usernameless-tip', (dom) => { dom.style.display = 'block'; }, 'class'); + } else { + wwa_dom('wwa-authenticator-list-usernameless-tip', (dom) => { dom.innerText = ''; dom.style.display = 'none' }, 'class'); + } + if (has_disabled_type && wwa_php_vars.allow_authenticator_type !== 'none') { + if (wwa_php_vars.allow_authenticator_type === 'platform') { + wwa_dom('wwa-authenticator-list-type-tip', (dom) => { dom.innerText = wwa_php_vars.i18n_36 }, 'class'); + } else { + wwa_dom('wwa-authenticator-list-type-tip', (dom) => { dom.innerText = wwa_php_vars.i18n_37 }, 'class'); + } + wwa_dom('wwa-authenticator-list-type-tip', (dom) => { dom.style.display = 'block'; }, 'class'); + } else { + wwa_dom('wwa-authenticator-list-type-tip', (dom) => { dom.innerText = ''; dom.style.display = 'none' }, 'class'); + } + } else { + wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `${wwa_php_vars.i18n_17}` }, 'class'); + } + }) +} + +/** Rename an authenticator + * + * @param {string} id Authenticator ID + * @param {string} name Current authenticator name + */ +function renameAuthenticator(id, name) { + let new_name = prompt(wwa_php_vars.i18n_21, name); + if (new_name === '') { + alert(wwa_php_vars.i18n_12); + } else if (new_name !== null && new_name !== name) { + let request = wwa_ajax(); + wwa_dom(`wwa-key-${id}`, (dom) => { dom.innerText = wwa_php_vars.i18n_22 }, 'class'); + request.get(wwa_php_vars.ajax_url, `?action=wwa_modify_authenticator&id=${encodeURIComponent(id)}&name=${encodeURIComponent(new_name)}&target=rename`, (data, status) => { + if (status) { + updateList(); + } else { + alert(`Error: ${data}`); + updateList(); + } + }) + } +} + +/** Remove an authenticator + * + * @param {string} id Authenticator ID + * @param {string} name Authenticator name + */ +function removeAuthenticator(id, name) { + if (confirm(wwa_php_vars.i18n_18 + name + (document.getElementsByClassName('wwa-authenticator-list')[0].children.length === 1 ? '\n' + wwa_php_vars.i18n_34 : ''))) { + wwa_dom(`wwa-key-${id}`, (dom) => { dom.innerText = wwa_php_vars.i18n_19 }, 'class'); + let request = wwa_ajax(); + request.get(wwa_php_vars.ajax_url, `?action=wwa_modify_authenticator&id=${encodeURIComponent(id)}&target=remove`, (data, status) => { + if (status) { + updateList(); + } else { + alert(`Error: ${data}`); + updateList(); + } + }) + } +} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/js/login.js b/wp-content/plugins/wp-webauthn/js/login.js new file mode 100644 index 00000000..9c5e69f9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/js/login.js @@ -0,0 +1,400 @@ +'use strict'; + +// Send an AJAX request and get the response +const wwa_ajax = function () { + let xmlHttpReq = new XMLHttpRequest(); + return { + /** Send an AJAX GET request and get the response + * + * @param {string} url URL + * @param {string} data Attached data + * @param {object} callback Callback function + */ + get: (url, data = '', callback = () => { }) => { + xmlHttpReq.open('GET', url + data, true); + xmlHttpReq.send(); + xmlHttpReq.onreadystatechange = () => { + if (xmlHttpReq.readyState === 4 && xmlHttpReq.status === 200) { + callback(xmlHttpReq.responseText, true); + } else if (xmlHttpReq.readyState === 4) { + callback('Network Error.', false); + } + } + }, + /** Send an AJAX POST request and get the response + * + * @param {string} url URL + * @param {string} data Attached data + * @param {object} callback Callback function + */ + post: (url, data = '', callback = () => { }) => { + xmlHttpReq.open('POST', url, true); + xmlHttpReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xmlHttpReq.send(data); + xmlHttpReq.onreadystatechange = () => { + if (xmlHttpReq.readyState === 4 && xmlHttpReq.status === 200) { + callback(xmlHttpReq.responseText, true); + } else if (xmlHttpReq.readyState === 4) { + callback('Network Error.', false); + } + } + } + } +}; + +/** Operate selected DOMs + * + * @param {string} selector DOM selector + * @param {object} callback Callbck function + * @param {string} method Selecte method + */ +const wwa_dom = (selector, callback = () => { }, method = 'query') => { + let dom_list = []; + if (method === 'id') { + let dom = document.getElementById(selector); + if (dom) { + callback(dom); + } + return; + } else if (method === 'class') { + dom_list = document.getElementsByClassName(selector); + } else if (method === 'tag') { + dom_list = document.getElementsByTagName(selector); + } else { + dom_list = document.querySelectorAll(selector); + } + for (let dom of dom_list) { + callback(dom); + } + return; +} + +let wwaSupported = true; +document.addEventListener('DOMContentLoaded', () => { + if (document.querySelectorAll('#lostpasswordform, #registerform, .admin-email-confirm-form').length > 0) { + return; + } + let button_check = document.createElement('button'); + button_check.id = 'wp-webauthn-check'; + button_check.type = 'button'; + button_check.className = 'button button-large button-primary'; + button_check.innerHTML = php_vars.i18n_1; + let button_toggle = document.createElement('button'); + if (php_vars.webauthn_only !== 'true') { + button_toggle.id = 'wp-webauthn'; + button_toggle.type = 'button'; + button_toggle.className = 'button button-large'; + button_toggle.innerHTML = ''; + } + let submit = document.getElementById('wp-submit'); + if (submit) { + if (php_vars.webauthn_only !== 'true') { + submit.parentNode.insertBefore(button_toggle, submit.nextElementSibling); + } + submit.parentNode.insertBefore(button_check, submit.nextElementSibling); + } + let notice = document.createElement('div'); + notice.className = 'wp-webauthn-notice'; + notice.innerHTML = ` ${php_vars.i18n_2}`; + let forgetmenot = document.getElementsByClassName('forgetmenot'); + if (forgetmenot.length > 0) { + forgetmenot[0].parentNode.insertBefore(notice, forgetmenot[0]); + } + wwa_dom('wp-webauthn-notice', (dom) => { + const passwordInput = document.getElementsByClassName('user-pass-wrap'); + if (passwordInput.length > 0) { + dom.style.height = (passwordInput[0].offsetHeight - 10) + 'px'; + } else { + // WordPress 5.2- + const legacyPasswordInput = document.getElementById('loginform').getElementsByTagName('p')[1]; + dom.style.height = (legacyPasswordInput.offsetHeight - 10) + 'px'; + } + }, 'class'); + let btnWidth = document.getElementById('wp-submit') ? document.getElementById('wp-submit').clientWidth : 0; + if (btnWidth < 20 || btnWidth === undefined) { + wwa_dom('wp-webauthn-check', (dom) => { dom.style.width = 'auto' }, 'id'); + } else { + wwa_dom('wp-webauthn-check', (dom) => { dom.style.width = btnWidth }, 'id'); + } + if (window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') { + wwaSupported = false; + wwa_dom('wp-webauthn', (dom) => { dom.style.display = 'none' }, 'id'); + } + wwa_dom('wp-webauthn-check', (dom) => { dom.addEventListener('click', check, false) }, 'id'); + wwa_dom('wp-webauthn', (dom) => { dom.addEventListener('click', toggle, false) }, 'id'); +}) + +window.onresize = function () { + if (document.querySelectorAll('#lostpasswordform, #registerform').length > 0) { + return; + } + let btnWidth = document.getElementById('wp-submit').clientWidth; + if (btnWidth < 20 || btnWidth === undefined) { + wwa_dom('wp-webauthn-check', (dom) => { dom.style.width = 'auto' }, 'id'); + } else { + wwa_dom('wp-webauthn-check', (dom) => { dom.style.width = btnWidth }, 'id'); + } +} + +document.addEventListener('keydown', parseKey, false); + +function parseKey(event) { + if (wwaSupported && document.getElementById('wp-webauthn-check').style.display === 'block') { + if (event.keyCode === 13) { + event.preventDefault(); + wwa_dom('wp-webauthn-check', (dom) => { dom.click() }, 'id'); + } + } +} + +function base64url2base64(input) { + input = input.replace(/=/g, '').replace(/-/g, '+').replace(/_/g, '/'); + const pad = input.length % 4; + if (pad) { + if (pad === 1) { + throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); + } + input += new Array(5 - pad).join('='); + } + return input; +} + + +function arrayToBase64String(a) { + return btoa(String.fromCharCode(...a)); +} + +function getQueryString(name) { + let reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i'); + let reg_rewrite = new RegExp(`(^|/)${name}/([^/]*)(/|$)`, 'i'); + let r = window.location.search.substr(1).match(reg); + let q = window.location.pathname.substr(1).match(reg_rewrite); + if (r != null) { + return unescape(r[2]); + } else if (q != null) { + return unescape(q[2]); + } else { + return null; + } +} + +function toggle() { + if (document.querySelectorAll('#lostpasswordform, #registerform').length > 0) { + return; + } + if (wwaSupported) { + if (document.getElementsByClassName('wp-webauthn-notice')[0].style.display === 'flex') { + if (document.getElementsByClassName('user-pass-wrap').length > 0) { + wwa_dom('.user-pass-wrap, .forgetmenot, #wp-submit', (dom) => { dom.style.display = 'block' }); + } else { + // WordPress 5.2- + wwa_dom('.forgetmenot, #wp-submit', (dom) => { dom.style.display = 'block' }); + document.getElementById('loginform').getElementsByTagName('p')[1].style.display = 'block'; + } + wwa_dom('wp-webauthn-notice', (dom) => { dom.style.display = 'none' }, 'class'); + wwa_dom('wp-webauthn-check', (dom) => { dom.style.cssText = `${dom.style.cssText.split('display: block !important')[0]}display: none !important` }, 'id'); + wwa_dom('user_pass', (dom) => { dom.disabled = false }, 'id'); + wwa_dom('user_login', (dom) => { dom.focus() }, 'id'); + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = ` ${php_vars.i18n_2}` }, 'class'); + wwa_dom('wp-submit', (dom) => { dom.disabled = false }, 'id'); + let inputDom = document.querySelectorAll('#loginform label') + if (inputDom.length > 0) { + if (document.getElementById('wwa-username-label')) { + // WordPress 5.2- + document.getElementById('wwa-username-label').innerText = php_vars.i18n_10; + } else { + inputDom[0].innerText = php_vars.i18n_10; + } + } + } else { + if (document.getElementsByClassName('user-pass-wrap').length > 0) { + wwa_dom('.user-pass-wrap, #wp-submit', (dom) => { dom.style.display = 'none' }); + if (php_vars.remember_me === 'false' ) { + wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' }); + } + } else { + // WordPress 5.2- + wwa_dom('#wp-submit', (dom) => { dom.style.display = 'none' }); + if (php_vars.remember_me === 'false' ) { + wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' }); + } + document.getElementById('loginform').getElementsByTagName('p')[1].style.display = 'none'; + } + wwa_dom('wp-webauthn-notice', (dom) => { dom.style.display = 'flex' }, 'class'); + wwa_dom('wp-webauthn-check', (dom) => { dom.style.cssText = `${dom.style.cssText.split('display: none !important')[0]}display: block !important` }, 'id'); + wwa_dom('user_login', (dom) => { dom.focus() }, 'id'); + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = ` ${php_vars.i18n_2}` }, 'class'); + wwa_dom('wp-submit', (dom) => { dom.disabled = true }, 'id'); + let inputDom = document.querySelectorAll('#loginform label') + if (inputDom.length > 0) { + if (document.getElementById('wwa-username-label')) { + // WordPress 5.2- + document.getElementById('wwa-username-label').innerText = php_vars.i18n_9; + } else { + inputDom[0].innerText = php_vars.i18n_9; + } + } + } + } +} + +// Shake the login form, code from WordPress +function wwa_shake(id, a, d) { + const c = a.shift(); + document.getElementById(id).style.left = c + 'px'; + if (a.length > 0) { + setTimeout(() => { + wwa_shake(id, a, d); + }, d); + } else { + try { + document.getElementById(id).style.position = 'static'; + wwa_dom('user_login', (dom) => { dom.focus() }, 'id'); + } catch (e) { } + } +} + +function check() { + if (document.querySelectorAll('#lostpasswordform, #registerform').length > 0) { + return; + } + if (wwaSupported) { + if (document.getElementById('user_login').value === '' && php_vars.usernameless !== 'true') { + wwa_dom('login_error', (dom) => { dom.remove() }, 'id'); + wwa_dom('p.message', (dom) => { dom.remove() }); + if (document.querySelectorAll('#login > h1').length > 0) { + let dom = document.createElement('div'); + dom.id = 'login_error'; + dom.innerHTML = php_vars.i18n_11; + document.querySelectorAll('#login > h1')[0].parentNode.insertBefore(dom, document.querySelectorAll('#login > h1')[0].nextElementSibling) + } + // Shake the login form, code from WordPress + let shake = new Array(15, 30, 15, 0, -15, -30, -15, 0); + shake = shake.concat(shake.concat(shake)); + var form = document.forms[0].id; + document.getElementById(form).style.position = 'relative'; + wwa_shake(form, shake, 20); + return; + } + wwa_dom('user_login', (dom) => { dom.readOnly = true }, 'id'); + wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = true }); + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_3 }, 'class'); + let request = wwa_ajax(); + request.get(php_vars.ajax_url, `?action=wwa_auth_start&user=${encodeURIComponent(document.getElementById('user_login').value)}&type=auth`, (rawData, status) => { + if (status) { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_4 }, 'class'); + let data = rawData; + try { + data = JSON.parse(rawData); + } catch (e) { + console.warn(rawData); + if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class'); + } else { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class'); + } + wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id'); + wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false }); + return; + } + data.challenge = Uint8Array.from(window.atob(base64url2base64(data.challenge)), (c) => c.charCodeAt(0)); + + if (data.allowCredentials) { + data.allowCredentials = data.allowCredentials.map((item) => { + item.id = Uint8Array.from(window.atob(base64url2base64(item.id)), (c) => c.charCodeAt(0)); + return item; + }); + } + + if (data.allowCredentials && php_vars.allow_authenticator_type && php_vars.allow_authenticator_type !== 'none') { + for (let credential of data.allowCredentials) { + if (php_vars.allow_authenticator_type === 'cross-platform') { + credential.transports = ['usb', 'nfc', 'ble']; + } else if (php_vars.allow_authenticator_type === 'platform') { + credential.transports = ['internal']; + } + } + } + + // Save client ID + const clientID = data.clientID; + delete data.clientID; + + navigator.credentials.get({ 'publicKey': data }).then((credentialInfo) => { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_5 }, 'class'); + return credentialInfo; + }).then((data) => { + const publicKeyCredential = { + id: data.id, + type: data.type, + rawId: arrayToBase64String(new Uint8Array(data.rawId)), + response: { + authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)), + clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), + signature: arrayToBase64String(new Uint8Array(data.response.signature)), + userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null + } + }; + return publicKeyCredential; + }).then(JSON.stringify).then((AuthenticatorResponse) => { + let response = wwa_ajax(); + response.post(`${php_vars.ajax_url}?action=wwa_auth`, `data=${encodeURIComponent(window.btoa(AuthenticatorResponse))}&type=auth&clientid=${clientID}&user=${encodeURIComponent(document.getElementById('user_login').value)}&remember=${php_vars.remember_me === 'false' ? 'false' : (document.getElementById('rememberme') ? (document.getElementById('rememberme').checked ? 'true' : 'false') : 'false')}`, (data, status) => { + if (status) { + if (data === 'true') { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_6 }, 'class'); + if (document.querySelectorAll('p.submit input[name="redirect_to"]').length > 0) { + setTimeout(() => { + window.location.href = document.querySelectorAll('p.submit input[name="redirect_to"]')[0].value; + }, 200); + } else { + if (getQueryString('redirect_to')) { + setTimeout(() => { + window.location.href = getQueryString('redirect_to'); + }, 200); + } else { + setTimeout(() => { + window.location.href = php_vars.admin_url + }, 200); + } + } + } else { + if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class'); + } else { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class'); + } + wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id'); + wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false }); + } + } else { + if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class'); + } else { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class'); + } + wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id'); + wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false }); + } + }) + }).catch((error) => { + console.warn(error); + if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class'); + } else { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class'); + } + wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id'); + wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false }); + }) + } else { + if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class'); + } else { + wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class'); + } + wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id'); + wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false }); + } + }) + } +} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/js/profile.js b/wp-content/plugins/wp-webauthn/js/profile.js new file mode 100644 index 00000000..9bc5f3a9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/js/profile.js @@ -0,0 +1,466 @@ +// Whether the broswer supports WebAuthn +if (window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') { + jQuery('#wwa-bind, #wwa-test').attr('disabled', 'disabled'); + jQuery('#wwa-show-progress').html(php_vars.i18n_5); +} + +jQuery(() => { + updateList(); +}) + +window.addEventListener('load', () => { + if (document.getElementById('wp-webauthn-error-container')) { + document.getElementById('wp-webauthn-error-container').insertBefore(document.getElementById('wp-webauthn-error'), null); + } +}) + +// Update authenticator list +function updateList() { + jQuery.ajax({ + url: php_vars.ajax_url, + type: 'GET', + data: { + action: 'wwa_authenticator_list', + user_id: php_vars.user_id + }, + success: function (data) { + if (typeof data === 'string') { + console.warn(data); + jQuery('#wwa-authenticator-list').html(`${php_vars.i18n_8}`); + return; + } + if (data.length === 0) { + if (configs.usernameless === 'true') { + jQuery('.wwa-usernameless-th, .wwa-usernameless-td').show(); + } else { + jQuery('.wwa-usernameless-th, .wwa-usernameless-td').hide(); + } + jQuery('#wwa-authenticator-list').html(`${php_vars.i18n_17}`); + jQuery('#wwa_usernameless_tip').text(''); + jQuery('#wwa_usernameless_tip').hide(); + jQuery('#wwa_type_tip').text(''); + jQuery('#wwa_type_tip').hide(); + return; + } + let htmlStr = ''; + let has_usernameless = false; + let has_disabled_type = false; + for (item of data) { + let item_type_disabled = false; + if (item.usernameless) { + has_usernameless = true; + } + if (configs.allow_authenticator_type !== 'none') { + if (configs.allow_authenticator_type !== item.type) { + has_disabled_type = true; + item_type_disabled = true; + } + } + htmlStr += `${item.name}${item.type === 'none' ? php_vars.i18n_9 : (item.type === 'platform' ? php_vars.i18n_10 : php_vars.i18n_11)}${item_type_disabled ? php_vars.i18n_29 : ''}${item.added}${item.last_used}${item.usernameless ? php_vars.i18n_24 + (configs.usernameless === 'true' ? '' : php_vars.i18n_26) : php_vars.i18n_25}${php_vars.i18n_20} | ${php_vars.i18n_12}`; + } + jQuery('#wwa-authenticator-list').html(htmlStr); + if (has_usernameless || configs.usernameless === 'true') { + jQuery('.wwa-usernameless-th, .wwa-usernameless-td').show(); + } else { + jQuery('.wwa-usernameless-th, .wwa-usernameless-td').hide(); + } + if (has_usernameless && configs.usernameless !== 'true') { + jQuery('#wwa_usernameless_tip').text(php_vars.i18n_27); + jQuery('#wwa_usernameless_tip').show(); + } else { + jQuery('#wwa_usernameless_tip').text(''); + jQuery('#wwa_usernameless_tip').hide(); + } + if (has_disabled_type && configs.allow_authenticator_type !== 'none') { + if (configs.allow_authenticator_type === 'platform') { + jQuery('#wwa_type_tip').text(php_vars.i18n_30); + } else { + jQuery('#wwa_type_tip').text(php_vars.i18n_31); + } + jQuery('#wwa_type_tip').show(); + } else { + jQuery('#wwa_type_tip').text(''); + jQuery('#wwa_type_tip').hide(); + } + }, + error: function () { + jQuery('#wwa-authenticator-list').html(`${php_vars.i18n_8}`); + } + }) +} + +/** Code Base64URL into Base64 + * + * @param {string} input Base64URL coded string + */ +function base64url2base64(input) { + input = input.replace(/=/g, '').replace(/-/g, '+').replace(/_/g, '/'); + const pad = input.length % 4; + if (pad) { + if (pad === 1) { + throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); + } + input += new Array(5 - pad).join('='); + } + return input; +} + +/** Code Uint8Array into Base64 string + * + * @param {Uint8Array} a The Uint8Array needed to be coded into Base64 string + */ +function arrayToBase64String(a) { + return btoa(String.fromCharCode(...a)); +} + +jQuery('#wwa-add-new-btn').click((e) => { + e.preventDefault(); + jQuery('#wwa-new-block').show(); + jQuery('#wwa-verify-block').hide(); + setTimeout(() => { + jQuery('#wwa-new-block').focus(); + }, 0); +}) + +jQuery('#wwa-verify-btn').click((e) => { + e.preventDefault(); + jQuery('#wwa-new-block').hide(); + jQuery('#wwa-verify-block').show(); + setTimeout(() => { + jQuery('#wwa-verify-block').focus(); + }, 0); +}) + +jQuery('.wwa-cancel').click((e) => { + e.preventDefault(); + jQuery('#wwa-new-block').hide(); + jQuery('#wwa-verify-block').hide(); +}) + +jQuery('#wwa_authenticator_name').keydown((e) => { + if (e.keyCode === 13) { + jQuery('#wwa-bind').trigger('click'); + e.preventDefault(); + } + }); + +// Bind an authenticator +jQuery('#wwa-bind').click((e) => { + e.preventDefault(); + if (jQuery('#wwa_authenticator_name').val() === '') { + alert(php_vars.i18n_7); + return; + } + + // Disable inputs to avoid changing in process + jQuery('#wwa-show-progress').html(php_vars.i18n_1); + jQuery('#wwa-bind').attr('disabled', 'disabled'); + jQuery('#wwa_authenticator_name').attr('disabled', 'disabled'); + jQuery('.wwa_authenticator_usernameless').attr('disabled', 'disabled'); + jQuery('#wwa_authenticator_type').attr('disabled', 'disabled'); + jQuery.ajax({ + url: php_vars.ajax_url, + type: 'GET', + data: { + action: 'wwa_create', + name: jQuery('#wwa_authenticator_name').val(), + type: jQuery('#wwa_authenticator_type').val(), + usernameless: jQuery('.wwa_authenticator_usernameless:checked').val() ? jQuery('.wwa_authenticator_usernameless:checked').val() : 'false', + user_id: php_vars.user_id + }, + success: function (data) { + if (typeof data === 'string') { + console.warn(data); + jQuery('#wwa-show-progress').html(`${php_vars.i18n_4}: ${data}`); + jQuery('#wwa-bind').removeAttr('disabled'); + jQuery('#wwa_authenticator_name').removeAttr('disabled'); + jQuery('.wwa_authenticator_usernameless').removeAttr('disabled'); + jQuery('#wwa_authenticator_type').removeAttr('disabled'); + updateList(); + return; + } + // Get the args, code string into Uint8Array + jQuery('#wwa-show-progress').text(php_vars.i18n_2); + let challenge = new Uint8Array(32); + let user_id = new Uint8Array(32); + challenge = Uint8Array.from(window.atob(base64url2base64(data.challenge)), (c) => c.charCodeAt(0)); + user_id = Uint8Array.from(window.atob(base64url2base64(data.user.id)), (c) => c.charCodeAt(0)); + + let public_key = { + challenge: challenge, + rp: { + id: data.rp.id, + name: data.rp.name + }, + user: { + id: user_id, + name: data.user.name, + displayName: data.user.displayName + }, + pubKeyCredParams: data.pubKeyCredParams, + authenticatorSelection: data.authenticatorSelection, + timeout: data.timeout + } + + // If some authenticators are already registered, exclude + if (data.excludeCredentials) { + public_key.excludeCredentials = data.excludeCredentials.map((item) => { + item.id = Uint8Array.from(window.atob(base64url2base64(item.id)), (c) => c.charCodeAt(0)); + return item; + }) + } + + // Save client ID + const clientID = data.clientID; + delete data.clientID; + + // Create, a pop-up window should appear + navigator.credentials.create({ 'publicKey': public_key }).then((newCredentialInfo) => { + jQuery('#wwa-show-progress').html(php_vars.i18n_6); + return newCredentialInfo; + }).then((data) => { + // Code Uint8Array into string for transmission + const publicKeyCredential = { + id: data.id, + type: data.type, + rawId: arrayToBase64String(new Uint8Array(data.rawId)), + response: { + clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), + attestationObject: arrayToBase64String(new Uint8Array(data.response.attestationObject)) + } + }; + return publicKeyCredential; + }).then(JSON.stringify).then((AuthenticatorAttestationResponse) => { + // Send attestation back to RP + jQuery.ajax({ + url: `${php_vars.ajax_url}?action=wwa_create_response`, + type: 'POST', + data: { + data: window.btoa(AuthenticatorAttestationResponse), + name: jQuery('#wwa_authenticator_name').val(), + type: jQuery('#wwa_authenticator_type').val(), + usernameless: jQuery('.wwa_authenticator_usernameless:checked').val() ? jQuery('.wwa_authenticator_usernameless:checked').val() : 'false', + clientid: clientID, + user_id: php_vars.user_id + }, + success: function (data) { + if (data === 'true') { + // Registered + jQuery('#wwa-show-progress').html(php_vars.i18n_3); + jQuery('#wwa-bind').removeAttr('disabled'); + jQuery('#wwa_authenticator_name').removeAttr('disabled'); + jQuery('#wwa_authenticator_name').val(''); + jQuery('.wwa_authenticator_usernameless').removeAttr('disabled'); + jQuery('#wwa_authenticator_type').removeAttr('disabled'); + updateList(); + } else { + // Register failed + jQuery('#wwa-show-progress').html(php_vars.i18n_4); + jQuery('#wwa-bind').removeAttr('disabled'); + jQuery('#wwa_authenticator_name').removeAttr('disabled'); + jQuery('.wwa_authenticator_usernameless').removeAttr('disabled'); + jQuery('#wwa_authenticator_type').removeAttr('disabled'); + updateList(); + } + }, + error: function () { + jQuery('#wwa-show-progress').html(php_vars.i18n_4); + jQuery('#wwa-bind').removeAttr('disabled'); + jQuery('#wwa_authenticator_name').removeAttr('disabled'); + jQuery('.wwa_authenticator_usernameless').removeAttr('disabled'); + jQuery('#wwa_authenticator_type').removeAttr('disabled'); + updateList(); + } + }) + }).catch((error) => { + // Creation abort + console.warn(error); + jQuery('#wwa-show-progress').html(`${php_vars.i18n_4}: ${error}`); + jQuery('#wwa-bind').removeAttr('disabled'); + jQuery('#wwa_authenticator_name').removeAttr('disabled'); + jQuery('.wwa_authenticator_usernameless').removeAttr('disabled'); + jQuery('#wwa_authenticator_type').removeAttr('disabled'); + updateList(); + }) + }, + error: function () { + jQuery('#wwa-show-progress').html(php_vars.i18n_4); + jQuery('#wwa-bind').removeAttr('disabled'); + jQuery('#wwa_authenticator_name').removeAttr('disabled'); + jQuery('.wwa_authenticator_usernameless').removeAttr('disabled'); + jQuery('#wwa_authenticator_type').removeAttr('disabled'); + updateList(); + } + }) +}); + +// Test WebAuthn +jQuery('#wwa-test, #wwa-test_usernameless').click((e) => { + jQuery('#wwa-test, #wwa-test_usernameless').attr('disabled', 'disabled'); + let button_id = e.target.id; + let usernameless = 'false'; + let tip_id = '#wwa-show-test'; + if (button_id === 'wwa-test_usernameless') { + usernameless = 'true'; + tip_id = '#wwa-show-test-usernameless'; + } + jQuery(tip_id).text(php_vars.i18n_1); + jQuery.ajax({ + url: php_vars.ajax_url, + type: 'GET', + data: { + action: 'wwa_auth_start', + type: 'test', + usernameless: usernameless, + user_id: php_vars.user_id + }, + success: function (data) { + if (typeof data === 'string') { + console.warn(data); + jQuery(tip_id).html(`${php_vars.i18n_15}: ${data}`); + jQuery('#wwa-test, #wwa-test_usernameless').removeAttr('disabled'); + return; + } + if (data === 'User not inited.') { + jQuery(tip_id).html(`${php_vars.i18n_15}: ${php_vars.i18n_17}`); + jQuery('#wwa-test, #wwa-test_usernameless').removeAttr('disabled'); + return; + } + jQuery(tip_id).text(php_vars.i18n_13); + data.challenge = Uint8Array.from(window.atob(base64url2base64(data.challenge)), (c) => c.charCodeAt(0)); + + if (data.allowCredentials) { + data.allowCredentials = data.allowCredentials.map((item) => { + item.id = Uint8Array.from(window.atob(base64url2base64(item.id)), (c) => c.charCodeAt(0)); + return item; + }); + } + + if (data.allowCredentials && configs.allow_authenticator_type && configs.allow_authenticator_type !== 'none') { + for (let credential of data.allowCredentials) { + if (configs.allow_authenticator_type === 'cross-platform') { + credential.transports = ['usb', 'nfc', 'ble']; + } else if (configs.allow_authenticator_type === 'platform') { + credential.transports = ['internal']; + } + } + } + + // Save client ID + const clientID = data.clientID; + delete data.clientID; + + navigator.credentials.get({ 'publicKey': data }).then((credentialInfo) => { + jQuery(tip_id).html(php_vars.i18n_14); + return credentialInfo; + }).then((data) => { + const publicKeyCredential = { + id: data.id, + type: data.type, + rawId: arrayToBase64String(new Uint8Array(data.rawId)), + response: { + authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)), + clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), + signature: arrayToBase64String(new Uint8Array(data.response.signature)), + userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null + } + }; + return publicKeyCredential; + }).then(JSON.stringify).then((AuthenticatorResponse) => { + jQuery.ajax({ + url: `${php_vars.ajax_url}?action=wwa_auth`, + type: 'POST', + data: { + data: window.btoa(AuthenticatorResponse), + type: 'test', + remember: 'false', + clientid: clientID, + user_id: php_vars.user_id + }, + success: function (data) { + if (data === 'true') { + jQuery(tip_id).html(php_vars.i18n_16); + jQuery('#wwa-test, #wwa-test_usernameless').removeAttr('disabled'); + updateList(); + } else { + jQuery(tip_id).html(php_vars.i18n_15); + jQuery('#wwa-test, #wwa-test_usernameless').removeAttr('disabled'); + } + }, + error: function () { + jQuery(tip_id).html(php_vars.i18n_15); + jQuery('#wwa-test, #wwa-test_usernameless').removeAttr('disabled'); + } + }) + }).catch((error) => { + console.warn(error); + jQuery(tip_id).html(`${php_vars.i18n_15}: ${error}`); + jQuery('#wwa-test, #wwa-test_usernameless').removeAttr('disabled'); + }) + }, + error: function () { + jQuery(tip_id).html(php_vars.i18n_15); + jQuery('#wwa-test, #wwa-test_usernameless').removeAttr('disabled'); + } + }) +}); + +/** + * Rename an authenticator + * @param {string} id Authenticator ID + * @param {string} name Current authenticator name + */ +function renameAuthenticator(id, name) { + let new_name = prompt(php_vars.i18n_21, name); + if (new_name === '') { + alert(php_vars.i18n_7); + } else if (new_name !== null && new_name !== name) { + jQuery(`#${id}`).text(php_vars.i18n_22) + jQuery.ajax({ + url: php_vars.ajax_url, + type: 'GET', + data: { + action: 'wwa_modify_authenticator', + id: id, + name: new_name, + target: 'rename', + user_id: php_vars.user_id + }, + success: function () { + updateList(); + }, + error: function (data) { + alert(`Error: ${data}`); + updateList(); + } + }) + } +} + +/** + * Remove an authenticator + * @param {string} id Authenticator ID + * @param {string} name Authenticator name + */ +function removeAuthenticator(id, name) { + if (confirm(php_vars.i18n_18 + name + (jQuery('#wwa-authenticator-list > tr').length === 1 ? '\n' + php_vars.i18n_28 : ''))) { + jQuery(`#${id}`).text(php_vars.i18n_19) + jQuery.ajax({ + url: php_vars.ajax_url, + type: 'GET', + data: { + action: 'wwa_modify_authenticator', + id: id, + target: 'remove', + user_id: php_vars.user_id + }, + success: function () { + updateList(); + }, + error: function (data) { + alert(`Error: ${data}`); + updateList(); + } + }) + } +} diff --git a/wp-content/plugins/wp-webauthn/languages/template.pot b/wp-content/plugins/wp-webauthn/languages/template.pot new file mode 100644 index 00000000..88a2ce11 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/languages/template.pot @@ -0,0 +1,583 @@ +# Copyright (C) 2021 Axton +# This file is distributed under the same license as the WP-WebAuthn plugin. +msgid "" +msgstr "" +"Project-Id-Version: WP-WebAuthn\n" +"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-webauthn\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Basepath: ..\n" +"X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SearchPathExcluded-0: *.js\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. Plugin Name of the plugin +msgid "WP-WebAuthn" +msgstr "" + +#. Plugin URI of the plugin +msgid "https://flyhigher.top" +msgstr "" + +#. Description of the plugin +msgid "WP-WebAuthn allows you to safely login to your WordPress site without password." +msgstr "" + +#. Author of the plugin +msgid "Axton" +msgstr "" + +#. Author URI of the plugin +msgid "https://axton.cc" +msgstr "" + +#: wwa-admin-content.php:6 +#: wwa-admin-content.php:202 +msgid "Log count: " +msgstr "" + +#: wwa-admin-content.php:14 +msgid "PHP extension gmp doesn't seem to exist, rendering WP-WebAuthn unable to function." +msgstr "" + +#: wwa-admin-content.php:18 +msgid "PHP extension mbstring doesn't seem to exist, rendering WP-WebAuthn unable to function." +msgstr "" + +#: wwa-admin-content.php:22 +msgid "WebAuthn features are restricted to websites in secure contexts. Please make sure your website is served over HTTPS or locally with localhost." +msgstr "" + +#: wwa-admin-content.php:87 +msgid "Settings saved." +msgstr "" + +#: wwa-admin-content.php:89 +msgid "Settings NOT saved." +msgstr "" + +#: wwa-admin-content.php:104 +msgid "Preferred login method" +msgstr "" + +#: wwa-admin-content.php:108 +msgid "Prefer WebAuthn" +msgstr "" + +#: wwa-admin-content.php:109 +msgid "Prefer password" +msgstr "" + +#: wwa-admin-content.php:110 +#: wwa-profile-content.php:56 +msgid "WebAuthn Only" +msgstr "" + +#: wwa-admin-content.php:112 +msgid "When using \"WebAuthn Only\", password login will be completely disabled. Please make sure your browser supports WebAuthn, otherwise you may unable to login.
User that doesn't have any registered authenticator (e.g. new user) will unable to login when using \"WebAuthn Only\".
When the browser does not support WebAuthn, the login method will default to password if password login is not disabled." +msgstr "" + +#: wwa-admin-content.php:116 +msgid "Website identifier" +msgstr "" + +#: wwa-admin-content.php:119 +msgid "This identifier is for identification purpose only and DOES NOT affect the authentication process in anyway." +msgstr "" + +#: wwa-admin-content.php:123 +msgid "Website domain" +msgstr "" + +#: wwa-admin-content.php:126 +msgid "This field MUST be exactly the same with the current domain or parent domain." +msgstr "" + +#: wwa-admin-content.php:130 +msgid "Allow to remember login" +msgstr "" + +#: wwa-admin-content.php:139 +#: wwa-admin-content.php:150 +#: wwa-admin-content.php:183 +#: wwa-admin-content.php:199 +#: wwa-profile-content.php:130 +#: wwa-shortcodes.php:118 +msgid "Enable" +msgstr "" + +#: wwa-admin-content.php:140 +#: wwa-admin-content.php:151 +#: wwa-admin-content.php:184 +#: wwa-admin-content.php:200 +#: wwa-profile-content.php:131 +#: wwa-shortcodes.php:118 +msgid "Disable" +msgstr "" + +#: wwa-admin-content.php:141 +msgid "Show the 'Remember Me' checkbox beside the login form when using WebAuthn." +msgstr "" + +#: wwa-admin-content.php:146 +msgid "Require user verification" +msgstr "" + +#: wwa-admin-content.php:152 +msgid "User verification can improve security, but is not fully supported by mobile devices.
If you cannot register or verify your authenticators, please consider disabling user verification." +msgstr "" + +#: wwa-admin-content.php:157 +msgid "Allow a specific type of authenticator" +msgstr "" + +#: wwa-admin-content.php:166 +#: wwa-profile-content.php:15 +#: wwa-profile-content.php:111 +#: wwa-shortcodes.php:33 +#: wwa-shortcodes.php:118 +msgid "Any" +msgstr "" + +#: wwa-admin-content.php:167 +#: wwa-profile-content.php:112 +#: wwa-shortcodes.php:118 +msgid "Platform (e.g. built-in fingerprint sensors)" +msgstr "" + +#: wwa-admin-content.php:168 +#: wwa-profile-content.php:113 +#: wwa-shortcodes.php:118 +msgid "Roaming (e.g. USB security keys)" +msgstr "" + +#: wwa-admin-content.php:170 +msgid "If a type is selected, the browser will only prompt for authenticators of selected type when authenticating and user can only register authenticators of selected type." +msgstr "" + +#: wwa-admin-content.php:174 +msgid "Allow to login without username" +msgstr "" + +#: wwa-admin-content.php:185 +msgid "Allow users to register authenticator with usernameless authentication feature and login without username.
User verification will be enabled automatically when authenticating with usernameless authentication feature.
Some authenticators and some browsers DO NOT support this feature." +msgstr "" + +#: wwa-admin-content.php:190 +msgid "Logging" +msgstr "" + +#: wwa-admin-content.php:202 +msgid "Clear log" +msgstr "" + +#: wwa-admin-content.php:204 +msgid "For debugging only. Enable only when needed.
Note: Logs may contain sensitive information." +msgstr "" + +#: wwa-admin-content.php:213 +msgid "Log" +msgstr "" + +#: wwa-admin-content.php:215 +msgid "Automatic update every 5 seconds." +msgstr "" + +#: wwa-admin-content.php:219 +msgid "To register a new authenticator or edit your authenticators, please go to your profile." +msgstr "" + +#: wwa-functions.php:148 +#: wwa-shortcodes.php:88 +msgid "Auth" +msgstr "" + +#: wwa-functions.php:149 +#: wwa-shortcodes.php:11 +#: wwa-shortcodes.php:85 +#: wwa-shortcodes.php:88 +msgid "Authenticate with WebAuthn" +msgstr "" + +#: wwa-functions.php:150 +#: wwa-shortcodes.php:12 +msgid "Hold on..." +msgstr "" + +#: wwa-functions.php:151 +#: wwa-shortcodes.php:13 +msgid "Please proceed..." +msgstr "" + +#: wwa-functions.php:152 +#: wwa-shortcodes.php:14 +msgid "Authenticating..." +msgstr "" + +#: wwa-functions.php:153 +#: wwa-shortcodes.php:15 +msgid "Authenticated" +msgstr "" + +#: wwa-functions.php:154 +#: wwa-shortcodes.php:16 +msgid "Auth failed" +msgstr "" + +#: wwa-functions.php:155 +msgid "It looks like your browser doesn't support WebAuthn, which means you may unable to login." +msgstr "" + +#: wwa-functions.php:156 +#: wwa-shortcodes.php:88 +msgid "Username" +msgstr "" + +#: wwa-functions.php:158 +msgid "Error: The username field is empty." +msgstr "" + +#: wwa-functions.php:159 +#: wwa-shortcodes.php:42 +msgid "Try to enter the username" +msgstr "" + +#: wwa-functions.php:176 +msgid "Logging in with password has been disabled by the site manager." +msgstr "" + +#: wwa-functions.php:182 +msgid "Logging in with password has been disabled for this account." +msgstr "" + +#: wwa-functions.php:220 +msgid "Logging in with password has been disabled for %s but you haven't register any WebAuthn authenticator yet. You may unable to login again once you log out. Register" +msgstr "" + +#: wwa-functions.php:220 +#: wwa-functions.php:265 +msgid "the site" +msgstr "" + +#: wwa-functions.php:220 +msgid "your account" +msgstr "" + +#: wwa-functions.php:265 +msgid "Logging in with password has been disabled for %s but this account haven't register any WebAuthn authenticator yet. This user may unable to login." +msgstr "" + +#: wwa-functions.php:265 +msgid "this account" +msgstr "" + +#: wwa-functions.php:293 +msgid "Settings" +msgstr "" + +#: wwa-functions.php:301 +msgid "GitHub" +msgstr "" + +#: wwa-functions.php:302 +msgid "Documentation" +msgstr "" + +#: wwa-profile-content.php:7 +msgid "Initializing..." +msgstr "" + +#: wwa-profile-content.php:8 +#: wwa-shortcodes.php:37 +msgid "Please follow instructions to finish registration..." +msgstr "" + +#: wwa-profile-content.php:9 +#: wwa-shortcodes.php:38 +msgctxt "action" +msgid "Registered" +msgstr "" + +#: wwa-profile-content.php:10 +#: wwa-shortcodes.php:39 +msgid "Registration failed" +msgstr "" + +#: wwa-profile-content.php:11 +#: wwa-shortcodes.php:40 +msgid "Your browser does not support WebAuthn" +msgstr "" + +#: wwa-profile-content.php:12 +#: wwa-shortcodes.php:41 +msgid "Registrating..." +msgstr "" + +#: wwa-profile-content.php:13 +#: wwa-shortcodes.php:21 +msgid "Please enter the authenticator identifier" +msgstr "" + +#: wwa-profile-content.php:14 +#: wwa-shortcodes.php:26 +msgid "Loading failed, maybe try refreshing?" +msgstr "" + +#: wwa-profile-content.php:16 +#: wwa-shortcodes.php:34 +msgid "Platform authenticator" +msgstr "" + +#: wwa-profile-content.php:17 +#: wwa-shortcodes.php:35 +msgid "Roaming authenticator" +msgstr "" + +#: wwa-profile-content.php:18 +#: wwa-shortcodes.php:36 +msgid "Remove" +msgstr "" + +#: wwa-profile-content.php:19 +#: wwa-shortcodes.php:22 +msgid "Please follow instructions to finish verification..." +msgstr "" + +#: wwa-profile-content.php:20 +#: wwa-shortcodes.php:23 +msgid "Verifying..." +msgstr "" + +#: wwa-profile-content.php:21 +#: wwa-shortcodes.php:24 +msgid "Verification failed" +msgstr "" + +#: wwa-profile-content.php:22 +#: wwa-shortcodes.php:25 +msgid "Verification passed! You can now log in through WebAuthn" +msgstr "" + +#: wwa-profile-content.php:23 +#: wwa-shortcodes.php:32 +msgid "No registered authenticators" +msgstr "" + +#: wwa-profile-content.php:24 +#: wwa-shortcodes.php:27 +msgid "Confirm removal of authenticator: " +msgstr "" + +#: wwa-profile-content.php:25 +#: wwa-shortcodes.php:28 +msgid "Removing..." +msgstr "" + +#: wwa-profile-content.php:26 +#: wwa-shortcodes.php:29 +msgid "Rename" +msgstr "" + +#: wwa-profile-content.php:27 +#: wwa-shortcodes.php:30 +msgid "Rename the authenticator" +msgstr "" + +#: wwa-profile-content.php:28 +#: wwa-shortcodes.php:31 +msgid "Renaming..." +msgstr "" + +#: wwa-profile-content.php:29 +#: wwa-shortcodes.php:10 +msgid "Ready" +msgstr "" + +#: wwa-profile-content.php:30 +#: wwa-shortcodes.php:17 +msgid "No" +msgstr "" + +#: wwa-profile-content.php:31 +#: wwa-shortcodes.php:18 +msgid " (Unavailable)" +msgstr "" + +#: wwa-profile-content.php:32 +#: wwa-shortcodes.php:19 +msgid "The site administrator has disabled usernameless login feature." +msgstr "" + +#: wwa-profile-content.php:33 +#: wwa-shortcodes.php:43 +msgid "After removing this authenticator, you will not be able to login with WebAuthn" +msgstr "" + +#: wwa-profile-content.php:34 +#: wwa-shortcodes.php:44 +msgid " (Disabled)" +msgstr "" + +#: wwa-profile-content.php:35 +#: wwa-shortcodes.php:45 +msgid "The site administrator only allow platform authenticators currently." +msgstr "" + +#: wwa-profile-content.php:36 +#: wwa-shortcodes.php:46 +msgid "The site administrator only allow roaming authenticators currently." +msgstr "" + +#: wwa-profile-content.php:50 +msgid "This site is not correctly configured to use WebAuthn. Please contact the site administrator." +msgstr "" + +#: wwa-profile-content.php:60 +msgid "Disable password login for this account" +msgstr "" + +#: wwa-profile-content.php:62 +msgid "When checked, password login will be completely disabled. Please make sure your browser supports WebAuthn and you have a registered authenticator, otherwise you may unable to login." +msgstr "" + +#: wwa-profile-content.php:62 +msgid "The site administrator has disabled password login for the whole site." +msgstr "" + +#: wwa-profile-content.php:66 +msgid "Registered WebAuthn Authenticators" +msgstr "" + +#: wwa-profile-content.php:71 +#: wwa-profile-content.php:86 +#: wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Identifier" +msgstr "" + +#: wwa-profile-content.php:72 +#: wwa-profile-content.php:87 +#: wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Type" +msgstr "" + +#: wwa-profile-content.php:73 +#: wwa-profile-content.php:88 +#: wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgctxt "time" +msgid "Registered" +msgstr "" + +#: wwa-profile-content.php:74 +#: wwa-profile-content.php:89 +msgid "Last used" +msgstr "" + +#: wwa-profile-content.php:75 +#: wwa-profile-content.php:90 +#: wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Usernameless" +msgstr "" + +#: wwa-profile-content.php:76 +#: wwa-profile-content.php:91 +#: wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Action" +msgstr "" + +#: wwa-profile-content.php:81 +#: wwa-shortcodes.php:157 +msgid "Loading..." +msgstr "" + +#: wwa-profile-content.php:98 +#: wwa-profile-content.php:101 +msgid "Register New Authenticator" +msgstr "" + +#: wwa-profile-content.php:98 +#: wwa-profile-content.php:142 +msgid "Verify Authenticator" +msgstr "" + +#: wwa-profile-content.php:102 +msgid "You are about to associate an authenticator with the current account %s.
You can register multiple authenticators for an account." +msgstr "" + +#: wwa-profile-content.php:105 +#: wwa-shortcodes.php:118 +msgid "Type of authenticator" +msgstr "" + +#: wwa-profile-content.php:115 +#: wwa-shortcodes.php:118 +msgid "If a type is selected, the browser will only prompt for authenticators of selected type.
Regardless of the type, you can only log in with the very same authenticators you've registered." +msgstr "" + +#: wwa-profile-content.php:119 +msgid "Authenticator Identifier" +msgstr "" + +#: wwa-profile-content.php:122 +#: wwa-shortcodes.php:118 +msgid "An easily identifiable name for the authenticator. DOES NOT affect the authentication process in anyway." +msgstr "" + +#: wwa-profile-content.php:127 +#: wwa-shortcodes.php:118 +msgid "Login without username" +msgstr "" + +#: wwa-profile-content.php:132 +#: wwa-shortcodes.php:118 +msgid "If registered authenticator with this feature, you can login without enter your username.
Some authenticators like U2F-only authenticators and some browsers DO NOT support this feature.
A record will be stored in the authenticator permanently untill you reset it." +msgstr "" + +#: wwa-profile-content.php:138 +msgid "Start Registration" +msgstr "" + +#: wwa-profile-content.php:143 +msgid "Click Test Login to verify that the registered authenticators are working." +msgstr "" + +#: wwa-profile-content.php:144 +#: wwa-shortcodes.php:144 +msgid "Test Login" +msgstr "" + +#: wwa-profile-content.php:146 +#: wwa-shortcodes.php:144 +msgid "Test Login (usernameless)" +msgstr "" + +#: wwa-shortcodes.php:20 +msgid "Error: The username field is empty." +msgstr "" + +#: wwa-shortcodes.php:88 +msgid "Authenticate with password" +msgstr "" + +#: wwa-shortcodes.php:105 +#: wwa-shortcodes.php:133 +#: wwa-shortcodes.php:166 +msgid "You haven't logged in yet." +msgstr "" + +#: wwa-shortcodes.php:118 +msgid "Authenticator identifier" +msgstr "" + +#: wwa-shortcodes.php:118 +msgid "Start registration" +msgstr "" diff --git a/wp-content/plugins/wp-webauthn/languages/wp-webauthn-fr_FR.mo b/wp-content/plugins/wp-webauthn/languages/wp-webauthn-fr_FR.mo new file mode 100644 index 0000000000000000000000000000000000000000..df03b55dbb29d2adff7298ca07b590c2d3e9be7f GIT binary patch literal 12337 zcmbuFeT-%0UB^$6T3jntN^J{R9w@l8F!%0D!N9OUcXwuC8GKv!9}0qxd?X0AxPRoDAP}j)1Fr`E0sL|BP4EWrUrG#qEC_yr`y0WZ z0uO+n0`CJq3$B86zpmJY7p=jq)9!cuStC_0D17+fo# ze+%R%_?r^n0RNo(?}DFUAJ4<=$GHECkNWlg7QCJNH$lyN2h{%d!Myf$EvWTx0Dl_1 z6}$?(7nEF&g3I6+!AHSA1U2qzg!_5$M(_am1SmQGYKeaaN-qBeYW!6&B{_T=)cwt% z`20D3eH=UqYTu88;wvogN1)`Im(RZfewzE|z)ygG1l|pP8$>n1JD})Y^OK(bP2fw& zWfr`S=ih;;2f=>>e-WJF;V*-~28!;7nJm5E42u43;5WfJQ1t%? z1ykhq$s2><*SUWNV~|`v{xjaLJ_YhBxE1^i_y8z-{smC`dm5BHz5=qf-~~{2^2gxk zz<&m157#qU<8A;?fnD$p@DeEb{62`u1+Rj#({F+^;9r5i2Yw$E|6j(LHSRY-&3gfS z3w#B9fqi_{c=;TGNy%j%ydQiV)V!~OlK+dK{NzCSZO8_U!K2_Spw|B$D7u;?Iot{&l3)gu-<>S62NEKJr$JN~ zJOhfquY;&4cm>Uk715cpVhI z{{}_>e?iIrV;H%f-!5Y}Giz~pA&iFM`p_N-j%In9#2XJRq-l~KJy_n&nbl2eip-{Q zII?CC*$o6aAB$odld)-ZPAC=2^JmSOv#T`$lNIA}lIC7P z<@QlxY;2fCupITJu|edN;}xEyjGkJuYbFaUthAR12Ls#F3avSk);LXi(gNxZExdKg`iMcCcmcHks`uaX*9nr5ryvF|=VSTjDC}o%hzVB^z~i!_{W! zWiuhZOPg3EJ324EgA++Sh|-aFt#D|PL3{X|3Ff0r>I&wQUNM4mXPUu+Gs(a?^LzO4 zNmSgo>%|6+xM7lbxYad&y1Vgq99!GB{gywRNpd@97L$$4jKVF0Ao391W;V{EJi1^} z^dL#)4@o>R;^3huf4Eo=9!>}(yg)UlN~=Q|r`Vs#x5iA)pftpkY=72SQ)%4Z>BOZB ziYR1Qq%D+8VyY%PY8WiOW0vhknD$*LV1!ImOZnK;3uC`sv?mjF5lKUwrZWYiGd0}=#W4I^|X$7PVRfT{xCXk&DxQZ9Vd_}20vh2 zkjRd)pC0bzrB0~J2}ynt(&udq~JGmZym5`M0z zn=Dv*c*)pHxlETxwJ{o-eqytDe~um5ksR1wBFD@^BJPs{VD-_ZPL;4s;k-@521V>r zVt0zKFwEswZSxA2_Izw+Yb)O@y{}2l>?$pnlU(K?`sfMv zV2RLG#va*xGwBD*HtcWlyDS7+!M=PfR(vY(!#rzM(pgsRVj1d77%jC-S|90=ON6^5 z;$PGxpDH2(x5|xHjSws+;YfOK`R3kFy|QM}*4oN(ltU_t@-1`TZj~xpvAOn;1=WR8 zugSs-$Y%1ax{u(3VWhEYVZ574kAtjklBi<;3RaPU3l5+YO4}pj0 z1Xy%f$*^DN2A9tKnsr6Dssh~C>XkN5udOr+K^3i+!k)?;?aZaOI^&fk5TR&wEi3E={PcCJt-Fl`{+V*cTU-X;7!Y|6XeXdWFVxw_Fa}&2b%`G!iX+R4dsGhbg z+D|B>Wg~S4jcWxV4lqudC^!oT3L4(Dxp!iGlwyP&z%j!4hiq1fUcBoV&u`-<#9RuYQU!SH#UV{Op=Hb=V zr4?yln3ShKooJ8tlD>VwJ=#pN{OCb<@0fJ#dk+(TTyp2ify16FkLobmt#w;l>4+E}VT)~&-k-IQr_i?aiy^T9mTDp`cKlo) zXJr=?TQ7~N$Yka2Bvg@i+ubCOsp4YT24W@hY}x$EZ@PMwzIRX#2y>*FtC!2-faBa| zo{zJ+g9k$$+Pb}7{a`TM+Ke{H5Zyc(2YEEI&1p+%@+1e6&Z&L}b5^A|XD*IAScC)+ z?_0JyTz5`q8&SV=yx7P(tI3?%w{&*3b0VeJz=X~`8g$P(%LEb8C?6d;bmVa7&|RIw z_nISz=MEpa^AP{`sY33oreT~>-X$qB7sGg?AUSnbZ8(}UCkf1Cx0#cS>DdGI>p3$> zJ13X-Ee(q_9Cl7pFlKWm9=qG@{v-Dhfb{16*gRkk-?#7dsnZLST^;To+Q-q8dYILT zr*lR=ad12&AKYhpn_)^xfB)L*$<95KapIENtg{ef<*0bh+_N6#`yT5oCcUJyg0gy6 z*WnO)gY+ESJ=R%DEM-9FII(aX=9_b-+nqf9dAlX2&KAjlbLQN+`_5T@F3laDJ<_}H zTr336#Yr+Quid-ZyY%)_{e1Rw+?TU#);kyGc?z-m(oQZLqc-!=upH$s{U~?oM@{(j zdpqI9GH1M89_u`0W9t&PPRYH*RA%SmL6q6XPdTANw0?wR$6qp}C-S>Q*5% zhRxAXgt9^t<6QK04JIU~9uA76wdv+exOXr5#nc8SofQ?yCv2)F40BN>gvcPaxMVng z_o_Gae4`Dg->k04&McUfwWX!A%c~1#R?X6}l{#fiiH2%D%6GP@NMfgnLD-`pa-3Dk z%hladI%1sW)ts={P7H5hz4o!S6KiJ{CJS#AUol-B4A8YO=VbtxhCWIw3Thcw5!S#1Yg1p(JwpuNvra9;`$P zH|j7twz8dVwKFkN7@T#RuRW0!>6~#42pe16Q%P8tqu8S6w)q8Y%IP*sA_7R&+iZm4 z3+T_?P6F^##eNq6C6Lk1%OhagEF>{Ei-DJ0M#9lG(n9SSZnF(r+AG4AVWdnF*ykRs zxhU&G7{;3@lI@YA+|KKu*JgxnlpSWZxl&d$qHgp00|IQ3wl(#KEL3ck`#2|()4J74E}M3sc)y_10Lg8UwerCl2n zVS9Mcv{oCol?98+b9LkPq0>t~+PQu%v4AcoC)W$gN!?b*mij_+L%1qY=&Mx8pOTI4 za*OKe<14;*>jLQqB)!y124Zk$djqwZ8LI2tD(LVr_KKr2Ta<}ohB}WX4j*FCJ7RL* zN{Fj2^V8R`kYr_q)cu4#wGG+w1A$x4v#5a>aYj@v`2MC()k~Af3d&Jj*i@EvdS_ehUZ*z~#9UoSQMx@qtQ1o8hcVHHwe3;z z@s?0usKDCaW?4&A1q9ob5wy*AMO81S!ZdJKW&KMP>*#sg$Cw#l=5T}Za+gmxI8aAI z!^m!${>ZMP5hf}>l_#Z^MsvnK+h#aq z=!k)nN<`rhlkAsjs+3Yy$rLUPMw>K!GHXa!xy*@V%7oiO>8fI+>x#?l;cyDXjUKo> z071KE8RxP}PZ%&<)e+pEQK|!+npLu-dh?WXS2##wur3Xb#*?Gb{Ml2DzPZnTu615o zg!Oe(S!VbRBW%|?m&9qZzyRI6N*a@wDTk++!}SS$9&Jxk;?(+w8Nw2z9bgt4bOUBBHo-5J`>)xqLaSa%y} zgfmxr=Y}w|J&gFUj1ACQp!U$0FBKoOvxxyPc*Ve>FP4>&%J}MYZkrVDDaICq-Jfe8JcO8y+OO0X2RT!u!kqOI`g+OMm z2rdw;^n6*TvVA7ZoEMQd{wB6D#txt zeZDOCGr2$HI7UTC7T=EsgMxW<;lk<@1Chk_P+jVD;r~is8Rp9%R7Fgv)_-fGpwxWs z41nk+b_ucst8t<~5pbox`}6>pyNYr4UguC{N`0Mh&5b(MvEhbkO%zXmjecMxH<=0= zzJO;bcOFHIBHQxbEGafa1l~A}!klD2<@27D>l#tSRA#Ib2_GeD2cI${pIiyA(mBVg zl7YbOBi`?2Y+@9CJYc literal 0 HcmV?d00001 diff --git a/wp-content/plugins/wp-webauthn/languages/wp-webauthn-fr_FR.po b/wp-content/plugins/wp-webauthn/languages/wp-webauthn-fr_FR.po new file mode 100644 index 00000000..77a724e0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/languages/wp-webauthn-fr_FR.po @@ -0,0 +1,524 @@ +msgid "" +msgstr "" +"Project-Id-Version: wp-webauthn\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2021-04-19 21:12+0000\n" +"Last-Translator: \n" +"Language-Team: French (France)\n" +"Language: fr-FR\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Loco-Source-Locale: fr_FR\n" +"X-Poedit-Basepath: ..\n" +"X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:" +"1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;" +"esc_html_x:1,2c\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Loco https://localise.biz/\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SearchPathExcluded-0: *.js\n" +"X-Loco-Parser: loco_parse_po" + +#. Plugin Name of the plugin +msgid "WP-WebAuthn" +msgstr "WP-WebAuthn" + +#. Plugin URI of the plugin +msgid "https://flyhigher.top" +msgstr "https://flyhigher.top" + +#. Description of the plugin +msgid "" +"WP-WebAuthn allows you to safely login to your WordPress site without " +"password." +msgstr "" +"WP-WebAuthn vous permet de vous connecter en toute sécurité à votre site " +"WordPress sans mot de passe." + +#. Author of the plugin +msgid "Axton" +msgstr "Axton" + +#. Author URI of the plugin +msgid "https://axton.cc" +msgstr "https://axton.cc" + +#: wwa-admin-content.php:4 +msgid "Initializing..." +msgstr "Initialisation…" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Please follow instructions to finish registration..." +msgstr "Veuillez suivre les instructions pour finir l’enregistrement" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgctxt "action" +msgid "Registered" +msgstr "Enregistré" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Registration failed" +msgstr "Échec de l’enregistrement" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Your browser does not support WebAuthn" +msgstr "Votre navigateur ne supporte pas Webauthn" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Registrating..." +msgstr "En cours d'enregistrement…" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Please enter the authenticator identifier" +msgstr "Veuiller saisir l’identifiant du périphérique" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Loading failed, maybe try refreshing?" +msgstr "Le chargement a échoué, essayez peut-être d’actualiser ?" + +#: wwa-admin-content.php:4, wwa-admin-content.php:168, wwa-shortcodes.php:4, +#: wwa-shortcodes.php:75 +msgid "Any" +msgstr "TOus" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Platform authenticator" +msgstr "Périphérique intégré (plateforme)" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Roaming authenticator" +msgstr "Périphérique détachable (roaming)" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Remove" +msgstr "Supprimer" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Please follow instructions to finish verification..." +msgstr "Veuillez suivre les instructions pour finir la vérification" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Verifying..." +msgstr "Vérification…" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Verification failed" +msgstr "Échec de la vérification" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Verification passed! You can now log in through WebAuthn" +msgstr "" +"Vérification réussie ! Vous pouvez vous connecter en utilisant Webauthn" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "No registered authenticators" +msgstr "Aucun périphériques enregistrés" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Confirm removal of authenticator: " +msgstr "Confirmez la suppression du périphérique" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Removing..." +msgstr "Suppression en cours…" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Rename" +msgstr "Renommer :" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Rename the authenticator" +msgstr "Renommer le périphérique" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Renaming..." +msgstr "En cours de renommage…" + +#: wwa-admin-content.php:4, wwa-admin-content.php:143 +msgid "Log count: " +msgstr "Compteur :" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "Ready" +msgstr "Prêt" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "No" +msgstr "Non" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid " (Unavailable)" +msgstr "(non disponible)" + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "The site administrator has disabled usernameless login feature." +msgstr "" +"L’administrateur du site a désactivé la fonctionnalité permettant les " +"connexions sans nom d’utilisateur." + +#: wwa-admin-content.php:4, wwa-shortcodes.php:4 +msgid "" +"After removing this authenticator, you will not be able to login with " +"WebAuthn" +msgstr "" +"Après la suppression de ce périphérique, vous ne pourrez plus vous connecter " +"en utilisant Webauthn" + +#: wwa-admin-content.php:10 +msgid "" +"PHP extension gmp doesn't seem to exist, rendering WP-WebAuthn unable to " +"function." +msgstr "" +"L’extension GMP pour PHP est introuvable. WP-WebAuthn risque de ne pas " +"fonctionner." + +#: wwa-admin-content.php:13 +msgid "" +"PHP extension mbstring doesn't seem to exist, rendering WP-WebAuthn unable " +"to function." +msgstr "" +"L’extension MBString pour PHP est introuvable. WP-WebAuthn risque de ne pas " +"fonctionner." + +#: wwa-admin-content.php:16 +msgid "" +"WebAuthn features are restricted to websites in secure contexts. Please make " +"sure your website is served over HTTPS or locally with localhost" +"." +msgstr "" +"Les fonctionnalités de WebAuthn sont limitées aux sites web dans des " +"contextes sécurisés. Veuillez vous assurer que votre site web est diffusé " +"via HTTPS ou localement avec localhost." + +#: wwa-admin-content.php:62 +msgid "Settings saved." +msgstr "Paramètres sauvegardés." + +#: wwa-admin-content.php:64 +msgid "Settings NOT saved." +msgstr "Paramètres NON sauvegardés" + +#: wwa-admin-content.php:79 +msgid "Preferred login method" +msgstr "Méthode de connexion préférée" + +#: wwa-admin-content.php:83 +msgid "WebAuthn" +msgstr "WebAuthn" + +#: wwa-admin-content.php:84 +msgid "Username + Password" +msgstr "Nom d’utilisateur + mot de passe" + +#: wwa-admin-content.php:85 +msgid "" +"Since WebAuthn hasn't been fully supported by all browsers, you can only " +"choose the preferred (default) login method and CANNOT completely " +"disable the traditional Username+Password method
Regardless of " +"the preferred method, you will be able to switch to the other with a switch " +"button at the login page.
When the browser does not support WebAuthn, " +"the login method will default to Username+Password." +msgstr "" +"Comme Webauthn n'est pas entièrement pris en charge par tous les navigateurs," +" vous ne pouvez choisir que la méthode de connexion préférée (par défaut) et " +"NE POUVEZ PAS désactiver complètement la méthode traditionnelle du " +"nom d'utilisateur + mot de passe
Quelle que soit la méthode " +"préférée, vous pourra passer à l'autre avec un bouton de commutation sur la " +"page de connexion.
Lorsque le navigateur ne prend pas en charge Webauthn, " +"la méthode de connexion sera par défaut le nom d’utilisateur + mot de passe." + +#: wwa-admin-content.php:90 +msgid "Website identifier" +msgstr "Identifiant du site web" + +#: wwa-admin-content.php:93 +msgid "" +"This identifier is for identification purpose only and DOES " +"NOT affect the authentication process in anyway." +msgstr "" +"Cet identifiant est utilisé seulement à des fins d'identification et " +"N’A PAS d'incidence sur le processus d’authentification." + +#: wwa-admin-content.php:97 +msgid "Website domain" +msgstr "Domaine du site web" + +#: wwa-admin-content.php:100 +msgid "" +"This field MUST be exactly the same with the current domain " +"or parent domain." +msgstr "" +"Ce champs DOIT être exactement le même que le nom de " +"domaine courant ou le nom de domaine racine." + +#: wwa-admin-content.php:104 +msgid "Require user verification" +msgstr "Vérification de l’utilisateur requise" + +#: wwa-admin-content.php:108, wwa-admin-content.php:124, +#: wwa-admin-content.php:140, wwa-admin-content.php:187, wwa-shortcodes.php:75 +msgid "Enable" +msgstr "Activer" + +#: wwa-admin-content.php:109, wwa-admin-content.php:125, +#: wwa-admin-content.php:141, wwa-admin-content.php:188, wwa-shortcodes.php:75 +msgid "Disable" +msgstr "Désactiver" + +#: wwa-admin-content.php:110 +msgid "" +"User verification can improve security, but is not fully supported by mobile " +"devices.
If you cannot register or verify your authenticators, please " +"consider disabling user verification." +msgstr "" +"La vérification des utilisateurs peut améliorer la sécurité, mais n’est pas " +"entièrement prise en charge par certains périphériques.
Si vous ne " +"parvenez pas à vous connecter, veuillez envisager de désactiver la " +"vérification des utilisateurs." + +#: wwa-admin-content.php:115 +msgid "Allow to login without username" +msgstr "Autoriser les connexion sans nom d’utilisateur" + +#: wwa-admin-content.php:126 +msgid "" +"Allow users to register authenticator with usernameless authentication " +"feature and login without username.
User verification will be " +"enabled automatically when registering authenticator with usernameless " +"authentication feature.
Some authenticators and some browsers " +"DO NOT support this feature." +msgstr "" +"Autoriser les utilisateurs à enregistrer un périphérique avec cette fonction " +"leur permettra de se connecter sans nom d'utilisateur.
La " +"vérification de l'utilisateur sera activée automatiquement lors de " +"l'enregistrement du périphérique.
Certains d’entre eux et " +"certains navigateurs NE SUPPORTENT PAS cette fonctionnalité." + +#: wwa-admin-content.php:131 +msgid "Logging" +msgstr "Enregistrement" + +#: wwa-admin-content.php:143 +msgid "Clear log" +msgstr "Effacer le registre" + +#: wwa-admin-content.php:145 +msgid "" +"For debugging only. Enable only when needed.
Note: Logs may " +"contain sensitive information." +msgstr "" +"Pour le débogage uniquement. Activer lorsque cela est nécessaire.
" +"Remarque : les registres peuvent contenir des informations sensibles." +"" + +#: wwa-admin-content.php:154 +msgid "Log" +msgstr "Registre" + +#: wwa-admin-content.php:156 +msgid "Automatic update every 5 seconds." +msgstr "Réactualiser automatiquement toutes les 5 secondes" + +#: wwa-admin-content.php:161 +msgid "Register Authenticator" +msgstr "Enregistrer un périphérique" + +#: wwa-admin-content.php:162 +msgid "" +"You are about to associate an authenticator with the current " +"account. You can register multiple authenticators for an account. " +"
If you want to register authenticators for other users, please log in " +"using that account." +msgstr "" +"Vous êtes sur le point d’associer un périphérique au compte " +"actuel. Vous pouvez enregistrer plusieurs périphérique pour un même " +"compte.
Si vous souhaitez enregistrer des périphériques pour d'autres " +"utilisateurs, veuillez vous connecter à l'aide de ce compte." + +#: wwa-admin-content.php:165, wwa-shortcodes.php:75 +msgid "Type of authenticator" +msgstr "Type de périphérique" + +#: wwa-admin-content.php:169, wwa-shortcodes.php:75 +msgid "Platform authenticator (e.g. a built-in fingerprint sensor) only" +msgstr "" +"Périphérique intégré seulement (par exemple un lecteur d’empreinte digitale)" + +#: wwa-admin-content.php:170, wwa-shortcodes.php:75 +msgid "Roaming authenticator (e.g., a USB security key) only" +msgstr "Périphérique détachable seulment (clé USB, Bluetooth…) " + +#: wwa-admin-content.php:172, wwa-shortcodes.php:75 +msgid "" +"If a type is selected, the browser will only prompt for authenticators of " +"selected type.
Regardless of the type, you can only log in with the " +"very same authenticators you've registered." +msgstr "" +"Si un type est sélectionné, le navigateur demandera uniquement les " +"périphériques du type sélectionné.
Quel que soit le type, vous ne pouvez " +"vous connecter qu'avec les mêmes périphériques que vous avez enregistrés." + +#: wwa-admin-content.php:176, wwa-shortcodes.php:75 +msgid "Authenticator identifier" +msgstr "ID du périphérique" + +#: wwa-admin-content.php:179, wwa-shortcodes.php:75 +msgid "" +"An easily identifiable name for the authenticator. DOES NOT " +"affect the authentication process in anyway." +msgstr "" +"Un nom facilement identifiable pour le périphérique. Cela n’a " +"AUCUNE incidence sur le processus d'authentification." + +#: wwa-admin-content.php:184, wwa-shortcodes.php:75 +msgid "Login without username" +msgstr "Connexion sur nom d’utilisateur" + +#: wwa-admin-content.php:189, wwa-shortcodes.php:75 +msgid "" +"If registered authenticator with this feature, you can login without enter " +"your username.
Some authenticators like U2F-only authenticators and some " +"browsers DO NOT support this feature.
A record will be " +"stored in the authenticator permanently untill you reset it." +msgstr "" +"Si le périphérique est enregistré avec cette fonctionnalité, vous pouvez " +"vous connecter sans entrer votre nom d’utilisateur.
Certains " +"périphériques tels que les anciens modèles FIDO-U2F et certains navigateurs " +"NE SONT PAS compatible avec cette fonctionnalité.
Un " +"identifiant spécifique sera stocké dans le périphérique de façon permanente " +"jusqu'à ce que vous le réinitialisiez." + +#: wwa-admin-content.php:195, wwa-shortcodes.php:75 +msgid "Start registration" +msgstr "Débuter l’enregistrement" + +#: wwa-admin-content.php:196 +msgid "Authenticators currently registered" +msgstr "Périphériques actuellement enregistrés" + +#: wwa-admin-content.php:201, wwa-admin-content.php:216, +#: wwa-shortcodes.php:113, wwa-shortcodes.php:115 +msgid "Identifier" +msgstr "Identifiant" + +#: wwa-admin-content.php:202, wwa-admin-content.php:217, +#: wwa-shortcodes.php:113, wwa-shortcodes.php:115 +msgid "Type" +msgstr "Type" + +#: wwa-admin-content.php:203, wwa-admin-content.php:218, +#: wwa-shortcodes.php:113, wwa-shortcodes.php:115 +msgctxt "time" +msgid "Registered" +msgstr "Enregistré" + +#: wwa-admin-content.php:204, wwa-admin-content.php:219, +#: wwa-shortcodes.php:113, wwa-shortcodes.php:115 +msgid "Last used" +msgstr "Dernière utilisation" + +#: wwa-admin-content.php:205, wwa-admin-content.php:220, +#: wwa-shortcodes.php:113, wwa-shortcodes.php:115 +msgid "Usernameless" +msgstr "Sans nom d’utilisateur" + +#: wwa-admin-content.php:206, wwa-admin-content.php:221, +#: wwa-shortcodes.php:113, wwa-shortcodes.php:115 +msgid "Action" +msgstr "Action" + +#: wwa-admin-content.php:211, wwa-shortcodes.php:114 +msgid "Loading..." +msgstr "Chargement…" + +#: wwa-admin-content.php:228 +msgid "Verify registration" +msgstr "Vérifier l’enregistrement" + +#: wwa-admin-content.php:229 +msgid "Click verify to verify that the registered authenticators are working." +msgstr "Cliquez pour vérifier que les périphériques enregistrés fonctionnent." + +#: wwa-admin-content.php:230, wwa-shortcodes.php:101 +msgid "Verify" +msgstr "Vérifier" + +#: wwa-admin-content.php:232, wwa-shortcodes.php:101 +msgid "Verify (usernameless)" +msgstr "Vérifier (sans nom d’utilisateur)" + +#: wwa-functions.php:120, wwa-shortcodes.php:46 +msgid "Auth" +msgstr "Connexion" + +#: wwa-functions.php:120, wwa-shortcodes.php:4, wwa-shortcodes.php:43, +#: wwa-shortcodes.php:46 +msgid "Authenticate with WebAuthn" +msgstr "Authentification avec Webauthn" + +#: wwa-functions.php:120, wwa-shortcodes.php:4 +msgid "Hold on..." +msgstr "Un instant…" + +#: wwa-functions.php:120, wwa-shortcodes.php:4 +msgid "Please proceed..." +msgstr "Veuillez continuer…" + +#: wwa-functions.php:120, wwa-shortcodes.php:4 +msgid "Authenticating..." +msgstr "Authentification…" + +#: wwa-functions.php:120, wwa-shortcodes.php:4 +msgid "Authenticated" +msgstr "Authentifié" + +#: wwa-functions.php:120, wwa-shortcodes.php:4 +msgid "Auth failed" +msgstr "Échec d’authentification" + +#: wwa-functions.php:120, wwa-shortcodes.php:46 +msgid "Username" +msgstr "Nom d’utilisateur" + +#: wwa-functions.php:120 +msgid "Username or Email Address" +msgstr "Nom d’utilisateur ou adresse email" + +#: wwa-functions.php:120 +msgid "Error: The username field is empty." +msgstr "Erreur: Le nom d’utilisateur est vide." + +#: wwa-functions.php:120, wwa-shortcodes.php:4 +msgid "Try to enter the username" +msgstr "Essayez de saisir le nom d’utilisateur" + +#: wwa-functions.php:137 +msgid "Settings" +msgstr "Paramètres" + +#: wwa-functions.php:145 +msgid "GitHub" +msgstr "GitHub" + +#: wwa-functions.php:146 +msgid "Documentation" +msgstr "Documentation" + +#: wwa-shortcodes.php:4 +msgid "Error: The username field is empty." +msgstr "Erreur : le nom d’utilisateur est vide" + +#: wwa-shortcodes.php:46 +msgid "Authenticate with password" +msgstr "Authentification avec mot de passe" + +#: wwa-shortcodes.php:63, wwa-shortcodes.php:90 +msgid "You haven't logged in yet." +msgstr "Vous n'êtes pas encore connecté·e." + +#: wwa-shortcodes.php:123 +msgid "You haven't logged in yet" +msgstr "Vous n'êtes pas encore connecté·e." diff --git a/wp-content/plugins/wp-webauthn/languages/wp-webauthn-tr_TR.mo b/wp-content/plugins/wp-webauthn/languages/wp-webauthn-tr_TR.mo new file mode 100644 index 0000000000000000000000000000000000000000..d1155458c44e3f95f1148073c2cd62ae12741be7 GIT binary patch literal 16201 zcmchdZHyduea8m~B)B{$JT?vg7>w<3w@#b@;bI$X-}xc-*~WLq91k(GyZ_xCc6Vl( zne}-ORizTVXr+p_6se-9E=np_3(Zb4Ja5wk> z$WOrvDD=0%w}CMjgTL+0zv$IL01Lq#4(|l7aeNQ>P4HXbJ@EC}*8~B(!4nX<0)7<~ zI$rgpTsL9sUa_bo~VU26)>qTKfJ9#59BNf#cA z2Y(N|4q{rt;xAdgJ_>$~;{^O1cC_oBAov2uU&DDIAvmS1Kea&7*KdHBT5uHr)zaO~cAA?N{=0Dx}$1rlaKL*7fegzage--=y_;v6>@D*_+gw}p8HKu`1>{}{{D9$ECkPis3y2;x21CiL>0jikR^hTIQ%rYhvPp4 zg^urmBHw4g0r(^Ez2FKL$@$NN?*XrYBFBFOh3}t$kRJRO`0LZP~=v_*aQ!PqOa57z2FM? zDEKLG5&RZ-5xfhbFM~bsG4L z4aYCVh=jj4fWpsS@FaK)6gqwr6u$oi6#v}>m%#6Xa^KtMh;86|KskOEd^33aBiJ5z zFZg2o>@_I+OB~;cl0-gFf+DZK0bdS23kp5|0}7q5CTQIT?gGWG?gQnz2SK6ZAP5`A zMu6Zn+hsO+wyY~YB_G5SKvJ;4R%ersJpV&%ACm(WkWV?$kmjgccvE9!mHi)Rq=OEvYxqX2lo5)h^vd1Q$8Me2Zy&!0S zsoNJ2d-x>VsvNk_io-4__9nh1b}S#UTmL!5PR6#A?GoD+w*73o*u-wc*2S)lvmIgk zIGcRL_Rg`@*kU&ERYHY{#p17;t@=5}!NY7HVG}#@pFTVHxPzl$o2|q4PPU6|O|}oP zC2V)I$%oWqYBo&R)Npc6K5t=*%%1%cyA0Hx`6vtPJ>A^P{)ITa97a7k-Wwdq@-&It zhZfQ_Ne}FEM{{bqqt!6eX&m;oYDK!&R8gjMe~^!A!Qn<8C2?@LmFrZcx}RK*;-m*Xt##Dpc7( zH=UMl#F`V$0tlO!wM1wSGi0CnqFdnUjVsh~) z5Hm4fs)haPrrCGKrYDW5v_tpPAk4DWBpttN>XTU9^IdR@bBN@hdFrPGreFSR^Hdru* z8kh)ilfZC{m72OfY~$T+mBhVKP1)Pcfwk^f>!xmwdC8e1*K;C?O!dQ<Gu2@-rQ0 zQ662^SOP?fmn3m%<-zeNKQXKaClaC)KcKscwoVc_YzTp~O!u%g-JCJz=B(ekqEIOo zM`%+bi3yh>{`i~iYSTPa{7M{DHNx0(>Xmo1z??xM*IkYI`mxtrm`vsA|iy-B5O-wcyNa)1Y5FV?i zMI1NwF)fDmqOMjK_8*%yikl$tXAE#6vcvGxAWm58AW&yyGJFsLO@u0pWuURj81k_p zJV!E}q`XvTI#*GScw!7V>_uxXxSY&!x}=*a!-nD5TVpfPS-d+hLa$GZGq_FE=%~I9 z)1Ma5^NIV1&)!bP_hj|7?_;5to9EoQRa_7Nm9f@qPX(@fsXYHvA4A zh!^aO1A8oNqlg=wFe96jshX~?P<07h$SNZGA(61HQ?srK1m3ou=YH|LT`Y<*_>5ue z2^*5i#MB8dYmt&SI>``44KZPVBc0c%WUxQuoYTc-dA$`LD>RCdUoa&r+%$y-6}BbV zC2>O=?cy2=r@(WYU-jaucb0^LzeI=JDP1bJr2dc1Pt@~n|`U(`zuteOX2EryUo}2Y{ zT`}R-Fg7J+ZDPrOoq|+u``Op+g*klp)gE1I*RZpwm(Rj;i`8{H;2}63j3jBcH#p}n z9*ZuVrudPYJ zL^zf+m<;rJDf?sZd+t~w8is}h`a16<&EUKan9VnsQ8H+{o3PKWbP8- z$W~HzHOrx|+0IM5pt;m`4MOpGO5whoGIit@!P*~+B|kZgD1VGYSA`LrPr|;KidFE1 zr6cIGF-)U;q`G>9R{aIzN?p>qkeda5M~YOH5oJhj#W{c6p+gY@cSFBzE*AA})#&I( zx1L-fCT3WHxxxz9n4GB?hM5rOCCAd@!>TGFcPce1utE#U3bC@Q_6YYPEXnJ8gJmCh z!zL2I;kX$WmmpolXRrRTl8-8~lhBY!)UMsqGSvtBrEEjA?fo`Q8%G#S^{Y&wCL#nm z^i~#0ou0?kII)IQ9HwXWxn%LeQl+_(?(0g}kfbfjG?h+K{5WC=IeinBN%Emk=S~QT zEMGdi^u-cU{TbKh4Tk9;AzE1WsSiCV^JjmiM#wzfq*_;$SXc_t-3KL@gXT7e6V3{H{4NY>9Wcr*ACEe z63V%sBrn~WsDD-0Wi8YE8}(_^4pL^I7iY!&kQN}5DU6}Q-6D>N7zx}8-KXlr^76SQ zQCBZT47rFa z4f@EQ&P7x{_HIYEult=PW`(z!F%6uV3KKWDRQ!CPVq0h8jgjF>7MFnFMW^~u7-5j(3)_SxkF(uX%~0k083=D< zY6KJMpX8_X=28ksr!)b#op%K!ZD=RY2ie@deWA?0YK=y5qSYI9qBfRW%acK1GB6&` z4#M&ys66WH>SEY8qZv1!I+rG&Amz=TY|awir1_YuHWoY1YnffnE@thhIeTQ-&SsaB zIpyh*A>crQRxL@}`<%M>4SGYW;eD%vqRrZII*i*xI@#G}9rowcj>VIU3*`eJsNKKg zD1$2U)vP3_Ih7NnScj_N5#mIcG6OhxVfonX!{v1;Ej-ov>_SY~A^y&(hwD+k<3qFO z63MHxM`$nxVcwZjwOV=hlpYDu*=cIKId$pMBbPLPSLPm=+245NQY;8uij!pE_RViI z56Q1rit{rMa_sKXS>sZe=P8R7ySm)1T-C|@J$IGawO5&4dsRv25=v_5qn7nKWqCi> z8>V4z_884qHm73b%wcwL|0C23vU_k(tnNLi9@zWHj&o;c&y#{hp|kUN1Tz27>~S4y zQ_#*SD(r~AQ?A=TvO)pXbkN1NBVl5f=wdt9Efb#r_(OX4(~DU*T}C<(6~ zhJ6)oT!VyB*a*AX=5-cd3y$bsl=dQ3k5bi*`b?K5o}luL^>kxBW|qnJc>h?LQ^?y>`Q{so*J-X00p z#4g4kY7K^EL<)6t1+ApBBRO3kR%O?uy3$>YPLDK2E>8(gO_F){w?1#yRPS!MQMn17k5>{0JGj}43* z<@i@b$2ry8Sl_(5u}(heM{7MDoD${cSlG6v0Edd0z$IAJ=JibimV_Kn8TGPL?^zo_ z4sTq;;<>`i7Z&o}%q$2yCK|;B_x^Uv2@7H#Hb!CZ*11?BiNle-QQkCFLZ&)`PlR0w zb{(CC14qJ*s}VzJ7h}Y1=(;#Y9TI0%-P|N9n@_qM>&%k#FdOmmY@y;ZfyCUKh1!*{ z2hD33GvO*!!Y>?RvBuJCs{GwVpD*)d&s!WSxOnoN~)8T;{y1y&t>(n zYiv>SAhD8cQ!Z{ZhE?m<3{!}LXi?@niFSw|vs~N84R}x`!lF-;nItrgGSYQ5{!8{3 z3*-)-(8v9m@|PLB@+cebR|-Y)dh7XA*N*CB`u~IE;LUn|VQG2c)I@}~M7iKYUYVMQ zoDE6}XSaolhy`Q~q|%goBqm9Uc6qN!#fK_u!4U#Gb(=|?F6JKJcuESCjdk*eYI8tP zDiWK>v8aW1Q$G2$7IC+XcNCsb5w0Y31WaZXuZFrX#`n<&+NM;JM+Qs0wD9`s2P+%v zCQWY5IV`VxIMYbStVkl2m=y!@``ldwcbhkSXbAicksnJ#Gz7=uTt3W)y&<;*H-6s) zL&;?&@#5d|9&NPoRIK^O5DH==38ag^^U`f1-7pnm>G4=`?ld4N!A#td56bo2qD6V4;qKWQYBGT28D|Lphv4l z`X0%PJxIq=`Hw5>S@L4AvTE@fudgpRn0mN{`y1;od}aR%VGqQS!*wcEG~EtEdQ;}C zMP$)9<5$vgRC$*-o>_v^8|!&X3ik05(%SGu5ywfRnpi}NoAGl$q&PMYG`>a2W>(92 z)!z?umtiU12ojR;=UpLbtF9M(yC)XI2>UXDH;Z})Bpfd5v=MdGLhb_qxm`}^Ja9j8 zlhpC06%%D7z(|pa!H}dUwm%>W; z?~&uSzaKkLdpsSs(; zI)!!FQ~GROq!>RXlsQIJ8V(|odns?yW=Pkws_Vv!B>ebO zKB`&K2b)jI^ibz!xM-(4GsK$e{K=Mb&^OK8(0Ms{@F8ftCq)>AomAS=rW+;+-;&>5 z9lmWy61BnM6qfN@2IP?0#Rr*Al{s;;4GDH`Rrb!Jia=jdNc_L^U+C`E85tWqV9eV} zOUm{kDy=aA(;1q7qh2ls5#-PT(ZP&Z898{bs_4G2 z*JOT2L*ggV<&p%MZ4Aw&x~w|I;A&r@tINDk6g!dNL-^) zVnQ!-SmKwT`&8Z^<98&{auDC8{J?qTeT($RMhdceb(D)@#I;+JN+urbids7obn~localhost." +msgstr "" +"WebAuthn özellikleri, güvenli bağlamlardaki web siteleriyle sınırlıdır. " +"Lütfen web sitenizin HTTPS üzerinden veya yerel olarak localhost ile sunulduğundan emin olun." + +#: wwa-admin-content.php:87 +msgid "Settings saved." +msgstr "Ayarlar kaydedildi." + +#: wwa-admin-content.php:89 +msgid "Settings NOT saved." +msgstr "Ayarlar KAYDEDİLMEDİ." + +#: wwa-admin-content.php:104 +msgid "Preferred login method" +msgstr "Tercih edilen oturum açma yöntemi" + +#: wwa-admin-content.php:108 +msgid "Prefer WebAuthn" +msgstr "WebAuthn'u Tercih Et" + +#: wwa-admin-content.php:109 +msgid "Prefer password" +msgstr "Şifre tercih et" + +#: wwa-admin-content.php:110 wwa-profile-content.php:56 +msgid "WebAuthn Only" +msgstr "Yalnızca WebAuthn" + +#: wwa-admin-content.php:112 +msgid "" +"When using \"WebAuthn Only\", password login will be completely disabled. " +"Please make sure your browser supports WebAuthn, otherwise you may unable to " +"login.
User that doesn't have any registered authenticator (e.g. new " +"user) will unable to login when using \"WebAuthn Only\".
When the browser " +"does not support WebAuthn, the login method will default to password if " +"password login is not disabled." +msgstr "" +"\"Yalnızca WebAuthn\" kullanılırken, şifre girişi tamamen devre dışı " +"bırakılacaktır. Lütfen tarayıcınızın WebAuthn'u desteklediğinden emin olun, " +"aksi takdirde oturum açamayabilirsiniz.
Kayıtlı bir kimlik " +"doğrulayıcısı olmayan kullanıcılar (ör. Yeni kullanıcı) \"Yalnızca WebAuthn" +"\" kullanırken oturum açamaz.
Tarayıcı yaptığında WebAuthn'u " +"desteklemezse, parola ile oturum açma devre dışı bırakılmamışsa oturum açma " +"yöntemi varsayılan olarak parola olacaktır." + +#: wwa-admin-content.php:116 +msgid "Website identifier" +msgstr "Web sitesi tanımlayıcı" + +#: wwa-admin-content.php:119 +msgid "" +"This identifier is for identification purpose only and DOES NOT affect the authentication process in anyway." +msgstr "" +"Bu tanımlayıcı yalnızca tanımlama amaçlıdır ve kimlik doğrulama sürecini " +"hiçbir şekilde ETKİLEMEZ." + +#: wwa-admin-content.php:123 +msgid "Website domain" +msgstr "Web sitesi domaini" + +#: wwa-admin-content.php:126 +msgid "" +"This field MUST be exactly the same with the current domain " +"or parent domain." +msgstr "" +"Bu alan, mevcut alan adı veya üst alan adı ile tam olarak aynı " +"OLMALIDIR." + +#: wwa-admin-content.php:130 +msgid "Allow to remember login" +msgstr "Girişin hatırlanmasına izin ver" + +#: wwa-admin-content.php:139 wwa-admin-content.php:150 +#: wwa-admin-content.php:183 wwa-admin-content.php:199 +#: wwa-profile-content.php:130 wwa-shortcodes.php:118 +msgid "Enable" +msgstr "Etkinleştir" + +#: wwa-admin-content.php:140 wwa-admin-content.php:151 +#: wwa-admin-content.php:184 wwa-admin-content.php:200 +#: wwa-profile-content.php:131 wwa-shortcodes.php:118 +msgid "Disable" +msgstr "Devredışı Bırak" + +#: wwa-admin-content.php:141 +msgid "" +"Show the 'Remember Me' checkbox beside the login form when using WebAuthn." +msgstr "" +"WebAuthn'u kullanırken giriş formunun yanında 'Beni Hatırla' onay kutusunu " +"gösterin." + +#: wwa-admin-content.php:146 +msgid "Require user verification" +msgstr "Kullanıcı doğrulaması gerektir" + +#: wwa-admin-content.php:152 +msgid "" +"User verification can improve security, but is not fully supported by mobile " +"devices.
If you cannot register or verify your authenticators, please " +"consider disabling user verification." +msgstr "" +"Kullanıcı doğrulama, güvenliği artırabilir, ancak mobil cihazlar tarafından " +"tam olarak desteklenmemektedir.
Doğrulayıcılarınızı kaydedemiyor veya " +"doğrulayamıyorsanız, lütfen kullanıcı doğrulamasını devre dışı bırakmayı " +"düşünün." + +#: wwa-admin-content.php:157 +msgid "Allow a specific type of authenticator" +msgstr "Belirli bir kimlik doğrulayıcı türüne izin ver" + +#: wwa-admin-content.php:166 wwa-profile-content.php:15 +#: wwa-profile-content.php:111 wwa-shortcodes.php:33 wwa-shortcodes.php:118 +msgid "Any" +msgstr "Herhangi" + +#: wwa-admin-content.php:167 wwa-profile-content.php:112 wwa-shortcodes.php:118 +msgid "Platform (e.g. built-in fingerprint sensors)" +msgstr "Platform (ör. Yerleşik parmak izi sensörleri)" + +#: wwa-admin-content.php:168 wwa-profile-content.php:113 wwa-shortcodes.php:118 +msgid "Roaming (e.g. USB security keys)" +msgstr "Mobil (ör. USB güvenlik anahtarları)" + +#: wwa-admin-content.php:170 +msgid "" +"If a type is selected, the browser will only prompt for authenticators of " +"selected type when authenticating and user can only register authenticators " +"of selected type." +msgstr "" +"Bir tür seçilirse, tarayıcı kimlik doğrulama sırasında yalnızca seçilen " +"türdeki kimlik doğrulayıcıları ister ve kullanıcı yalnızca seçilen türdeki " +"kimlik doğrulayıcıları kaydedebilir." + +#: wwa-admin-content.php:174 +msgid "Allow to login without username" +msgstr "Kullanıcı adı olmadan giriş yapmaya izin ver" + +#: wwa-admin-content.php:185 +msgid "" +"Allow users to register authenticator with usernameless authentication " +"feature and login without username.
User verification will be " +"enabled automatically when authenticating with usernameless authentication " +"feature.
Some authenticators and some browsers DO NOT support this feature." +msgstr "" +"Kullanıcıların, kimlik doğrulayıcısını gereksiz kimlik doğrulama özelliği " +"ile kaydetmesine ve kullanıcı adı olmadan oturum açmasına izin verin.
" +" Kullanılmayan kimlik doğrulama özelliği ile kimlik doğrulaması " +"yapılırken kullanıcı doğrulama otomatik olarak etkinleştirilecektir.
Bazı kimlik doğrulayıcılar ve bazı tarayıcılar bu özelliği " +"desteklemeyebilir." + +#: wwa-admin-content.php:190 +msgid "Logging" +msgstr "Günlük tutuluyor" + +#: wwa-admin-content.php:202 +msgid "Clear log" +msgstr "Günlüğü temizle" + +#: wwa-admin-content.php:204 +msgid "" +"For debugging only. Enable only when needed.
Note: Logs may " +"contain sensitive information." +msgstr "" +"Yalnızca hata ayıklama için. Yalnızca gerektiğinde etkinleştirin. " +"
Not: Günlükler hassas bilgiler içerebilir." + +#: wwa-admin-content.php:213 +msgid "Log" +msgstr "Günlük" + +#: wwa-admin-content.php:215 +msgid "Automatic update every 5 seconds." +msgstr "Her 5 saniyede bir otomatik güncelleme." + +#: wwa-admin-content.php:219 +msgid "" +"To register a new authenticator or edit your authenticators, please go to your profile." +msgstr "" +"Yeni bir kimlik doğrulayıcı kaydettirmek veya kimlik doğrulayıcılarınızı " +"düzenlemek için lütfen profilinize " +"gidin." + +#: wwa-functions.php:148 wwa-shortcodes.php:88 +msgid "Auth" +msgstr "Yetkilendirme" + +#: wwa-functions.php:149 wwa-shortcodes.php:11 wwa-shortcodes.php:85 +#: wwa-shortcodes.php:88 +msgid "Authenticate with WebAuthn" +msgstr "WebAuthn ile kimlik doğrulama" + +#: wwa-functions.php:150 wwa-shortcodes.php:12 +msgid "Hold on..." +msgstr "Bekle..." + +#: wwa-functions.php:151 wwa-shortcodes.php:13 +msgid "Please proceed..." +msgstr "Lütfen devam edin..." + +#: wwa-functions.php:152 wwa-shortcodes.php:14 +msgid "Authenticating..." +msgstr "Kimlik doğrulanıyor..." + +#: wwa-functions.php:153 wwa-shortcodes.php:15 +msgid "Authenticated" +msgstr "Kimliği doğrulandı" + +#: wwa-functions.php:154 wwa-shortcodes.php:16 +msgid "Auth failed" +msgstr "Yetkilendirme başarısız oldu" + +#: wwa-functions.php:155 +msgid "" +"It looks like your browser doesn't support WebAuthn, which means you may " +"unable to login." +msgstr "" +"Görünüşe göre tarayıcınız WebAuthn'u desteklemiyor, bu da oturum " +"açamayabileceğiniz anlamına geliyor." + +#: wwa-functions.php:156 wwa-shortcodes.php:88 +msgid "Username" +msgstr "Kullanıcı adı" + +#: wwa-functions.php:158 +msgid "Error: The username field is empty." +msgstr "Hata: Kullanıcı adı alanı boş." + +#: wwa-functions.php:159 wwa-shortcodes.php:42 +msgid "Try to enter the username" +msgstr "Kullanıcı adını girmeyi deneyin" + +#: wwa-functions.php:176 +msgid "Logging in with password has been disabled by the site manager." +msgstr "Şifre ile oturum açma site yöneticisi tarafından devre dışı bırakıldı." + +#: wwa-functions.php:182 +msgid "Logging in with password has been disabled for this account." +msgstr "Bu hesap için şifre ile giriş devre dışı bırakıldı." + +#: wwa-functions.php:220 +msgid "" +"Logging in with password has been disabled for %s but you haven't register " +"any WebAuthn authenticator yet. You may unable to login again once you log " +"out. Register" +msgstr "" +"Parola ile oturum açma %s için devre dışı bırakıldı, ancak henüz herhangi " +"bir WebAuthn doğrulayıcısı kaydetmediniz. Oturumu kapattıktan sonra tekrar " +"oturum açamayabilirsiniz. Kaydolun " + +#: wwa-functions.php:220 wwa-functions.php:265 +msgid "the site" +msgstr "site" + +#: wwa-functions.php:220 +msgid "your account" +msgstr "hesabınız" + +#: wwa-functions.php:265 +msgid "" +"Logging in with password has been disabled for %s but this account haven't register any WebAuthn authenticator yet. This user may " +"unable to login." +msgstr "" +"Şifre ile giriş %s için devre dışı bırakıldı, ancak bu hesap henüz herhangi bir WebAuthn doğrulayıcısı kaydetmedi. Bu kullanıcı " +"giriş yapamayabilir." + +#: wwa-functions.php:265 +msgid "this account" +msgstr "bu hesap" + +#: wwa-functions.php:293 +msgid "Settings" +msgstr "Ayarlar" + +#: wwa-functions.php:301 +msgid "GitHub" +msgstr "GitHub" + +#: wwa-functions.php:302 +msgid "Documentation" +msgstr "Dokümantasyon" + +#: wwa-profile-content.php:7 +msgid "Initializing..." +msgstr "Başlatılıyor..." + +#: wwa-profile-content.php:8 wwa-shortcodes.php:37 +msgid "Please follow instructions to finish registration..." +msgstr "Kaydı tamamlamak için lütfen talimatları izleyin..." + +#: wwa-profile-content.php:9 wwa-shortcodes.php:38 +msgctxt "action" +msgid "Registered" +msgstr "Kayıtlı" + +#: wwa-profile-content.php:10 wwa-shortcodes.php:39 +msgid "Registration failed" +msgstr "Kayıt başarısız" + +#: wwa-profile-content.php:11 wwa-shortcodes.php:40 +msgid "Your browser does not support WebAuthn" +msgstr "Tarayıcınız WebAuthn'u desteklemiyor" + +#: wwa-profile-content.php:12 wwa-shortcodes.php:41 +msgid "Registrating..." +msgstr "Kaydediliyor..." + +#: wwa-profile-content.php:13 wwa-shortcodes.php:21 +msgid "Please enter the authenticator identifier" +msgstr "Lütfen kimlik doğrulayıcı tanımlayıcıyı girin" + +#: wwa-profile-content.php:14 wwa-shortcodes.php:26 +msgid "Loading failed, maybe try refreshing?" +msgstr "Yükleme başarısız oldu, belki yenilemeyi deneyin?" + +#: wwa-profile-content.php:16 wwa-shortcodes.php:34 +msgid "Platform authenticator" +msgstr "Platform doğrulayıcı" + +#: wwa-profile-content.php:17 wwa-shortcodes.php:35 +msgid "Roaming authenticator" +msgstr "Mobil kimlik doğrulayıcı" + +#: wwa-profile-content.php:18 wwa-shortcodes.php:36 +msgid "Remove" +msgstr "Kaldırmak" + +#: wwa-profile-content.php:19 wwa-shortcodes.php:22 +msgid "Please follow instructions to finish verification..." +msgstr "Doğrulamayı tamamlamak için lütfen talimatları izleyin..." + +#: wwa-profile-content.php:20 wwa-shortcodes.php:23 +msgid "Verifying..." +msgstr "Doğrulanıyor..." + +#: wwa-profile-content.php:21 wwa-shortcodes.php:24 +msgid "Verification failed" +msgstr "Doğrulama başarısız oldu" + +#: wwa-profile-content.php:22 wwa-shortcodes.php:25 +msgid "Verification passed! You can now log in through WebAuthn" +msgstr "Doğrulama geçti! Artık WebAuthn aracılığıyla giriş yapabilirsiniz" + +#: wwa-profile-content.php:23 wwa-shortcodes.php:32 +msgid "No registered authenticators" +msgstr "Kayıtlı kimlik doğrulayıcı yok" + +#: wwa-profile-content.php:24 wwa-shortcodes.php:27 +msgid "Confirm removal of authenticator: " +msgstr "Kimlik doğrulayıcının kaldırılmasını onaylayın: " + +#: wwa-profile-content.php:25 wwa-shortcodes.php:28 +msgid "Removing..." +msgstr "Kaldırılıyor..." + +#: wwa-profile-content.php:26 wwa-shortcodes.php:29 +msgid "Rename" +msgstr "Yeniden adlandır" + +#: wwa-profile-content.php:27 wwa-shortcodes.php:30 +msgid "Rename the authenticator" +msgstr "Doğrulayıcıyı yeniden adlandır" + +#: wwa-profile-content.php:28 wwa-shortcodes.php:31 +msgid "Renaming..." +msgstr "Yeniden adlandırılıyor..." + +#: wwa-profile-content.php:29 wwa-shortcodes.php:10 +msgid "Ready" +msgstr "Hazır" + +#: wwa-profile-content.php:30 wwa-shortcodes.php:17 +msgid "No" +msgstr "Hayır" + +#: wwa-profile-content.php:31 wwa-shortcodes.php:18 +msgid " (Unavailable)" +msgstr " (Kullanılamaz)" + +#: wwa-profile-content.php:32 wwa-shortcodes.php:19 +msgid "The site administrator has disabled usernameless login feature." +msgstr "Site yöneticisi, gereksiz oturum açma özelliğini devre dışı bıraktı." + +#: wwa-profile-content.php:33 wwa-shortcodes.php:43 +msgid "" +"After removing this authenticator, you will not be able to login with " +"WebAuthn" +msgstr "" +"Bu doğrulayıcıyı kaldırdıktan sonra, WebAuthn ile oturum açamayacaksınız" + +#: wwa-profile-content.php:34 wwa-shortcodes.php:44 +msgid " (Disabled)" +msgstr " (Devredışı)" + +#: wwa-profile-content.php:35 wwa-shortcodes.php:45 +msgid "The site administrator only allow platform authenticators currently." +msgstr "" +"Site yöneticisi şu anda yalnızca platform kimlik doğrulayıcılarına izin " +"veriyor." + +#: wwa-profile-content.php:36 wwa-shortcodes.php:46 +msgid "The site administrator only allow roaming authenticators currently." +msgstr "" +"Site yöneticisi şu anda yalnızca mobil kimlik doğrulayıcılarına izin veriyor." + +#: wwa-profile-content.php:50 +msgid "" +"This site is not correctly configured to use WebAuthn. Please contact the " +"site administrator." +msgstr "" +"Bu site, WebAuthn kullanmak için doğru şekilde yapılandırılmamış. Lütfen " +"site yöneticisiyle iletişime geçin." + +#: wwa-profile-content.php:60 +msgid "Disable password login for this account" +msgstr "Bu hesap için şifre girişini devre dışı bırakın" + +#: wwa-profile-content.php:62 +msgid "" +"When checked, password login will be completely disabled. Please make sure " +"your browser supports WebAuthn and you have a registered authenticator, " +"otherwise you may unable to login." +msgstr "" +"İşaretlendiğinde, şifre girişi tamamen devre dışı bırakılacaktır. Lütfen " +"tarayıcınızın WebAuthn'u desteklediğinden ve kayıtlı bir kimlik " +"doğrulayıcınız olduğundan emin olun, aksi takdirde oturum açamayabilirsiniz." + +#: wwa-profile-content.php:62 +msgid "The site administrator has disabled password login for the whole site." +msgstr "Site yöneticisi tüm site için şifre girişini devre dışı bıraktı." + +#: wwa-profile-content.php:66 +msgid "Registered WebAuthn Authenticators" +msgstr "Kayıtlı WebAuthn Kimlik Doğrulayıcıları" + +#: wwa-profile-content.php:71 wwa-profile-content.php:86 wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Identifier" +msgstr "Tanımlayıcı" + +#: wwa-profile-content.php:72 wwa-profile-content.php:87 wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Type" +msgstr "Tip" + +#: wwa-profile-content.php:73 wwa-profile-content.php:88 wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgctxt "time" +msgid "Registered" +msgstr "Kayıtlı" + +#: wwa-profile-content.php:74 wwa-profile-content.php:89 +msgid "Last used" +msgstr "Son kullanım" + +#: wwa-profile-content.php:75 wwa-profile-content.php:90 wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Usernameless" +msgstr "Kullanıcı adsız" + +#: wwa-profile-content.php:76 wwa-profile-content.php:91 wwa-shortcodes.php:156 +#: wwa-shortcodes.php:158 +msgid "Action" +msgstr "Eylem" + +#: wwa-profile-content.php:81 wwa-shortcodes.php:157 +msgid "Loading..." +msgstr "Yükleniyor..." + +#: wwa-profile-content.php:98 wwa-profile-content.php:101 +msgid "Register New Authenticator" +msgstr "Yeni Kimlik Doğrulayıcıyı Kaydet" + +#: wwa-profile-content.php:98 wwa-profile-content.php:142 +msgid "Verify Authenticator" +msgstr "Kimlik Doğrulayıcıyı Doğrula" + +#: wwa-profile-content.php:102 +msgid "" +"You are about to associate an authenticator with the current account " +"%s.
You can register multiple authenticators for an account." +msgstr "" +"Bir doğrulayıcıyı geçerli hesapla %s ilişkilendirmek " +"üzeresiniz.
Bir hesap için birden fazla doğrulayıcı kaydedebilirsiniz." + +#: wwa-profile-content.php:105 wwa-shortcodes.php:118 +msgid "Type of authenticator" +msgstr "Doğrulayıcı türü" + +#: wwa-profile-content.php:115 wwa-shortcodes.php:118 +msgid "" +"If a type is selected, the browser will only prompt for authenticators of " +"selected type.
Regardless of the type, you can only log in with the " +"very same authenticators you've registered." +msgstr "" +"Bir tür seçilirse, tarayıcı yalnızca seçilen türdeki doğrulayıcıları " +"soracaktır.
Türüne bakılmaksızın, yalnızca kaydettiğiniz kimlik " +"doğrulayıcılarla giriş yapabilirsiniz." + +#: wwa-profile-content.php:119 +msgid "Authenticator Identifier" +msgstr "Kimlik Doğrulayıcı Tanımlayıcı" + +#: wwa-profile-content.php:122 wwa-shortcodes.php:118 +msgid "" +"An easily identifiable name for the authenticator. DOES NOT " +"affect the authentication process in anyway." +msgstr "" +"Kimlik doğrulayıcı için kolayca tanımlanabilen bir ad. Kimlik doğrulama " +"sürecini hiçbir şekilde ETKİLEMEZ." + +#: wwa-profile-content.php:127 wwa-shortcodes.php:118 +msgid "Login without username" +msgstr "Kullanıcı adı olmadan giriş yap" + +#: wwa-profile-content.php:132 wwa-shortcodes.php:118 +msgid "" +"If registered authenticator with this feature, you can login without enter " +"your username.
Some authenticators like U2F-only authenticators and some " +"browsers DO NOT support this feature.
A record will be " +"stored in the authenticator permanently untill you reset it." +msgstr "" +"Kimlik doğrulayıcısı bu özellikle kaydolduysa, kullanıcı adınızı girmeden " +"oturum açabilirsiniz.
Yalnızca U2F kimlik doğrulayıcıları gibi bazı " +"kimlik doğrulayıcılar ve bazı tarayıcılar bu özelliği DESTEKLEMEZ.
Kayıtlar kimlik doğrulayıcısında siz sıfırlayana kadar kalıcı " +"olarak duracak." + +#: wwa-profile-content.php:138 +msgid "Start Registration" +msgstr "Kaydı Başlat" + +#: wwa-profile-content.php:143 +msgid "" +"Click Test Login to verify that the registered authenticators are working." +msgstr "" +"Kayıtlı kimlik doğrulayıcıların çalıştığını doğrulamak için Oturum Açmayı " +"Test Et'e tıklayın." + +#: wwa-profile-content.php:144 wwa-shortcodes.php:144 +msgid "Test Login" +msgstr "Test Girişi" + +#: wwa-profile-content.php:146 wwa-shortcodes.php:144 +msgid "Test Login (usernameless)" +msgstr "Test Girişi (kullanıcı adsız)" + +#: wwa-shortcodes.php:20 +msgid "Error: The username field is empty." +msgstr "Hata: Kullanıcı adı alanı boş." + +#: wwa-shortcodes.php:88 +msgid "Authenticate with password" +msgstr "Parola ile doğrulayın" + +#: wwa-shortcodes.php:105 wwa-shortcodes.php:133 wwa-shortcodes.php:166 +msgid "You haven't logged in yet." +msgstr "Henüz giriş yapmadınız." + +#: wwa-shortcodes.php:118 +msgid "Authenticator identifier" +msgstr "Kimlik doğrulayıcı tanımlayıcı" + +#: wwa-shortcodes.php:118 +msgid "Start registration" +msgstr "Kaydı başlat" diff --git a/wp-content/plugins/wp-webauthn/readme.txt b/wp-content/plugins/wp-webauthn/readme.txt new file mode 100644 index 00000000..82df5b99 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/readme.txt @@ -0,0 +1,147 @@ +=== WP-WebAuthn === +Contributors: axton +Donate link: https://flyhigher.top/about +Tags: u2f, fido, fido2, webauthn, login, security, password, authentication +Requires at least: 5.0 +Tested up to: 6.0 +Stable tag: 1.2.8 +Requires PHP: 7.2 +License: GPLv3 +License URI: https://www.gnu.org/licenses/gpl-3.0.html + +WP-WebAuthn enables passwordless login through FIDO2 and U2F devices like FaceID or Windows Hello for your site. + +== Description == + +WebAuthn is a new way for you to authenticate in web. It helps you replace your passwords with devices like USB Keys, fingerprint scanners, Windows Hello compatible cameras, FaceID/TouchID and more. Using WebAuthn, you can login to your a website with a glance or touch. + +When using WebAuthn, you just need to click once and perform a simple verification on the authenticator, then you are logged in. **No password needed.** + +WP-WebAuthn is a plug-in for WordPress to enable WebAuthn on your site. Just download and install it, and you are in the future of web authentication. + +WP-WebAuthn also supports usernameless authentication. + +This plugin has 4 built-in shortcodes and 4 built-in Gutenberg blocks, so you can add components like register form to frontend pages. + +Please refer to the [documentation](http://doc.flyhigher.top/wp-webauthn) before using the plugin. + +**PHP extensions gmp and mbstring are required.** + +**WebAuthn requires HTTPS connection or `localhost` to function normally.** + +You can contribute to this plugin on [GitHub](https://github.com/yrccondor/wp-webauthn). + +Please note that this plugin does NOT support Internet Explorer (including IE 11). To use FaceID or TouchID, you need to use iOS/iPadOS 14+. + += Security and Privacy = + +WebAuthn has become a W3C Recommendation since March 2019, which enabling the creation and use of strong, attested, scoped, public key-based credentials by web applications, for the purpose of strongly authenticating users using hardware authenticators. WebAuthn focuses on both security and privacy, it offers the possibility to create a secure authentication process without having to transfer any private data such as recognition data and fingerprint data. It will be the future of web authentication. + += GDPR Friendly = + +When authenticating with WebAuthn, no private data will leave user's device and no third-party involvement. The credentials transferred are not associate to any user's information but only for authentication. It's GDPR Friendly. + +== Installation == + +Notice: PHP extensions gmp and mbstring are required. + +1. Upload the plugin files to the `/wp-content/plugins/wp-webauthn` directory, or install the plugin through the WordPress plugins screen directly +2. Activate the plugin through the 'Plugins' screen in WordPress +3. Use the Settings->WP-WebAuthn screen to configure the plugin +4. Make sure that all settings are set, and you can start to register authenticators in your profile page + +== Frequently Asked Questions == + += What languages does this plugin support? = + +This plugin supports English, Chinese (Simplified), Traditional Chinese (Hong Kong), Traditional Chinese (Taiwan), Turkish, French & German currently. If you are using WordPress in none of those languages, English will be displayed as default language. + +All translation files are hosted on [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/wp-webauthn/) and [GitHub](https://github.com/yrccondor/wp-webauthn/tree/master/languages). You can help us to translate WP-WebAuthn into other languages! + += What should I do if the plugin could not work? = + +Make sure your are using HTTPS or host your site in `localhost`. Then check whether you have installed the gmp extension for PHP. + +If you can't solve the problem, [open an issue](https://github.com/yrccondor/wp-webauthn/issues/new) on [GitHub](https://github.com/yrccondor/wp-webauthn) with plugin log. + += Which browsers support WebAuthn? = + +The latest version of Chrome, FireFox, Edge and Safari are support WebAuthn. You can learn more on [Can I Use](https://caniuse.com/#feat=webauthn). + +To use FaceID or TouchID, you need to use iOS/iPadOS 14+. + +== Screenshots == + +1. Verifying +2. Verifying without username on iPad +3. The login page +4. The settings page +5. Profile + +== Changelog == + += 1.2.8 = +Fix: privilege check for admin panel + += 1.2.7 = +Add: Now a security warning will be shown if user verification is disabled +Fix: Style broken with some locales +Fix: privilege check for admin panel (thanks to @vanpop) +Update: Third party libraries + += 1.2.6 = +Update: Third party libraries + += 1.2.5 = +Update: German translation (thanks to niiconn) +Fix: HTTPS check + += 1.2.4 = +Add: French translation (thanks to Spomky) and Turkish translate (thanks to Sn0bzy) +Fix: HTTPS check +Update: Existing translations +Update: Third party libraries + += 1.2.3 = +Feat: Avoid locking users out if WebAuthn is not available +Update: translations +Update: Third party libraries + += 1.2.2 = +Fix: Cannot access to js files in apache 2.4+ + += 1.2.1 = +Feat: Allow to disable password login completely +Feat: Now we use WordPress transients instead of PHP sessions +Feat: Move register related settings to user's profile +Feat: Gutenberg block support +Feat: Traditional Chinese (Hong Kong) & Traditional Chinese (Taiwan) translation +Update: Chinese translation +Update: Third-party libraries + += 1.1.0 = +Add: Allow to remember login option +Add: Only allow a specific type of authenticator option +Fix: Toggle button may not working in login form +Update: Chinese translation +Update: Third-party libraries + +== Upgrade Notice == + += 1.2.5 = +Improvred HTTPS checking and updated German translation (by niiconn) + += 1.2.4 = +Improvred HTTPS checking and added new translations + += 1.2.3 = +Avoid locking users out if WebAuthn is not available and update translations + += 1.2.2 = +Fixed a problem that js files were broken in apache 2.4+ + += 1.2.1 = +New features, bug fixing and new translations + += 1.1.0 = +2 new features & bug fixing diff --git a/wp-content/plugins/wp-webauthn/vendor/autoload.php b/wp-content/plugins/wp-webauthn/vendor/autoload.php new file mode 100644 index 00000000..8737b350 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/autoload.php @@ -0,0 +1,12 @@ +=6.0.0", + "yoast/phpunit-polyfills": "^0.1.0" + }, + "autoload": { + "psr-4": { + "Assert\\": "lib/Assert" + }, + "files": [ + "lib/Assert/functions.php" + ] + }, + "autoload-dev": { + "psr-4": { + "Assert\\Tests\\": "tests/Assert/Tests" + }, + "files": [ + "tests/Assert/Tests/Fixtures/functions.php" + ] + }, + "scripts": { + "assert:generate-docs": "php bin/generate_method_docs.php", + "assert:cs-lint": "php-cs-fixer fix --diff -vvv --dry-run", + "assert:cs-fix": "php-cs-fixer fix . -vvv || true", + "assert:sa-code": "vendor/bin/phpstan analyse --configuration=phpstan-code.neon --no-progress --ansi -l 7 bin lib", + "assert:sa-tests": "vendor/bin/phpstan analyse --configuration=phpstan-tests.neon --no-progress --ansi -l 7 tests" + }, + "suggest": { + "ext-intl": "Needed to allow Assertion::count(), Assertion::isCountable(), Assertion::minCount(), and Assertion::maxCount() to operate on ResourceBundles" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assert.php b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assert.php new file mode 100644 index 00000000..3614b345 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assert.php @@ -0,0 +1,85 @@ +notEmpty()->integer(); + * Assert::that($value)->nullOr()->string()->startsWith("Foo"); + * + * The assertion chain can be stateful, that means be careful when you reuse + * it. You should never pass around the chain. + */ + public static function that($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain + { + $assertionChain = new AssertionChain($value, $defaultMessage, $defaultPropertyPath); + + return $assertionChain->setAssertionClassName(static::$assertionClass); + } + + /** + * Start validation on a set of values, returns {@link AssertionChain}. + * + * @param mixed $values + * @param string|callable|null $defaultMessage + */ + public static function thatAll($values, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain + { + return static::that($values, $defaultMessage, $defaultPropertyPath)->all(); + } + + /** + * Start validation and allow NULL, returns {@link AssertionChain}. + * + * @param mixed $value + * @param string|callable|null $defaultMessage + */ + public static function thatNullOr($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain + { + return static::that($value, $defaultMessage, $defaultPropertyPath)->nullOr(); + } + + /** + * Create a lazy assertion object. + */ + public static function lazy(): LazyAssertion + { + $lazyAssertion = new LazyAssertion(); + + return $lazyAssertion + ->setAssertClass(\get_called_class()) + ->setExceptionClass(static::$lazyAssertionExceptionClass); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assertion.php b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assertion.php new file mode 100644 index 00000000..243e64d2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/Assertion.php @@ -0,0 +1,2797 @@ + + * + * @method static bool allAlnum(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric for all values. + * @method static bool allBase64(string[] $value, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined for all values. + * @method static bool allBetween(mixed[] $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit for all values. + * @method static bool allBetweenExclusive(mixed[] $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit for all values. + * @method static bool allBetweenLength(mixed[] $value, int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths for all values. + * @method static bool allBoolean(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is php boolean for all values. + * @method static bool allChoice(mixed[] $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices for all values. + * @method static bool allChoicesNotEmpty(array[] $values, array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content for all values. + * @method static bool allClassExists(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that the class exists for all values. + * @method static bool allContains(mixed[] $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars for all values. + * @method static bool allCount(array[]|Countable[]|ResourceBundle[]|SimpleXMLElement[] $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count for all values. + * @method static bool allDate(string[] $value, string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format for all values. + * @method static bool allDefined(mixed[] $constant, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined for all values. + * @method static bool allDigit(mixed[] $value, string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit for all values. + * @method static bool allDirectory(string[] $value, string|callable $message = null, string $propertyPath = null) Assert that a directory exists for all values. + * @method static bool allE164(string[] $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number for all values. + * @method static bool allEmail(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL) for all values. + * @method static bool allEndsWith(mixed[] $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars for all values. + * @method static bool allEq(mixed[] $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==) for all values. + * @method static bool allEqArraySubset(mixed[] $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset for all values. + * @method static bool allExtensionLoaded(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded for all values. + * @method static bool allExtensionVersion(string[] $extension, string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed for all values. + * @method static bool allFalse(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False for all values. + * @method static bool allFile(string[] $value, string|callable $message = null, string $propertyPath = null) Assert that a file exists for all values. + * @method static bool allFloat(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php float for all values. + * @method static bool allGreaterOrEqualThan(mixed[] $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit for all values. + * @method static bool allGreaterThan(mixed[] $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit for all values. + * @method static bool allImplementsInterface(mixed[] $class, string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface for all values. + * @method static bool allInArray(mixed[] $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice() for all values. + * @method static bool allInteger(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer for all values. + * @method static bool allIntegerish(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish for all values. + * @method static bool allInterfaceExists(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that the interface exists for all values. + * @method static bool allIp(string[] $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address for all values. + * @method static bool allIpv4(string[] $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address for all values. + * @method static bool allIpv6(string[] $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address for all values. + * @method static bool allIsArray(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array for all values. + * @method static bool allIsArrayAccessible(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object for all values. + * @method static bool allIsCallable(mixed[] $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable for all values. + * @method static bool allIsCountable(array[]|Countable[]|ResourceBundle[]|SimpleXMLElement[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is countable for all values. + * @method static bool allIsInstanceOf(mixed[] $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name for all values. + * @method static bool allIsJsonString(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string for all values. + * @method static bool allIsObject(mixed[] $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object for all values. + * @method static bool allIsResource(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is a resource for all values. + * @method static bool allIsTraversable(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object for all values. + * @method static bool allKeyExists(mixed[] $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array for all values. + * @method static bool allKeyIsset(mixed[] $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset() for all values. + * @method static bool allKeyNotExists(mixed[] $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array for all values. + * @method static bool allLength(mixed[] $value, int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length for all values. + * @method static bool allLessOrEqualThan(mixed[] $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit for all values. + * @method static bool allLessThan(mixed[] $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit for all values. + * @method static bool allMax(mixed[] $value, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit for all values. + * @method static bool allMaxCount(array[]|Countable[]|ResourceBundle[]|SimpleXMLElement[] $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements for all values. + * @method static bool allMaxLength(mixed[] $value, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars for all values. + * @method static bool allMethodExists(string[] $value, mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object for all values. + * @method static bool allMin(mixed[] $value, mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit for all values. + * @method static bool allMinCount(array[]|Countable[]|ResourceBundle[]|SimpleXMLElement[] $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements for all values. + * @method static bool allMinLength(mixed[] $value, int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long for all values. + * @method static bool allNoContent(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is empty for all values. + * @method static bool allNotBlank(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is not blank for all values. + * @method static bool allNotContains(mixed[] $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars for all values. + * @method static bool allNotEmpty(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is not empty for all values. + * @method static bool allNotEmptyKey(mixed[] $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty for all values. + * @method static bool allNotEq(mixed[] $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==) for all values. + * @method static bool allNotInArray(mixed[] $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices for all values. + * @method static bool allNotIsInstanceOf(mixed[] $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name for all values. + * @method static bool allNotNull(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is not null for all values. + * @method static bool allNotRegex(mixed[] $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex for all values. + * @method static bool allNotSame(mixed[] $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===) for all values. + * @method static bool allNull(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is null for all values. + * @method static bool allNumeric(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is numeric for all values. + * @method static bool allObjectOrClass(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists for all values. + * @method static bool allPhpVersion(string[] $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version for all values. + * @method static bool allPropertiesExist(mixed[] $value, array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist for all values. + * @method static bool allPropertyExists(mixed[] $value, string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists for all values. + * @method static bool allRange(mixed[] $value, mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers for all values. + * @method static bool allReadable(string[] $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something readable for all values. + * @method static bool allRegex(mixed[] $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex for all values. + * @method static bool allSame(mixed[] $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===) for all values. + * @method static bool allSatisfy(mixed[] $value, callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback for all values. + * @method static bool allScalar(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar for all values. + * @method static bool allStartsWith(mixed[] $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars for all values. + * @method static bool allString(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is a string for all values. + * @method static bool allSubclassOf(mixed[] $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name for all values. + * @method static bool allTrue(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True for all values. + * @method static bool allUniqueValues(array[] $values, string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality) for all values. + * @method static bool allUrl(mixed[] $value, string|callable $message = null, string $propertyPath = null) Assert that value is an URL for all values. + * @method static bool allUuid(string[] $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID for all values. + * @method static bool allVersion(string[] $version1, string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions for all values. + * @method static bool allWriteable(string[] $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable for all values. + * @method static bool nullOrAlnum(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric or that the value is null. + * @method static bool nullOrBase64(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined or that the value is null. + * @method static bool nullOrBetween(mixed|null $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit or that the value is null. + * @method static bool nullOrBetweenExclusive(mixed|null $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit or that the value is null. + * @method static bool nullOrBetweenLength(mixed|null $value, int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths or that the value is null. + * @method static bool nullOrBoolean(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is php boolean or that the value is null. + * @method static bool nullOrChoice(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices or that the value is null. + * @method static bool nullOrChoicesNotEmpty(array|null $values, array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content or that the value is null. + * @method static bool nullOrClassExists(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the class exists or that the value is null. + * @method static bool nullOrContains(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars or that the value is null. + * @method static bool nullOrCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count or that the value is null. + * @method static bool nullOrDate(string|null $value, string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format or that the value is null. + * @method static bool nullOrDefined(mixed|null $constant, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined or that the value is null. + * @method static bool nullOrDigit(mixed|null $value, string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit or that the value is null. + * @method static bool nullOrDirectory(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a directory exists or that the value is null. + * @method static bool nullOrE164(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number or that the value is null. + * @method static bool nullOrEmail(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL) or that the value is null. + * @method static bool nullOrEndsWith(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars or that the value is null. + * @method static bool nullOrEq(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==) or that the value is null. + * @method static bool nullOrEqArraySubset(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset or that the value is null. + * @method static bool nullOrExtensionLoaded(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded or that the value is null. + * @method static bool nullOrExtensionVersion(string|null $extension, string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed or that the value is null. + * @method static bool nullOrFalse(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False or that the value is null. + * @method static bool nullOrFile(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a file exists or that the value is null. + * @method static bool nullOrFloat(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php float or that the value is null. + * @method static bool nullOrGreaterOrEqualThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit or that the value is null. + * @method static bool nullOrGreaterThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit or that the value is null. + * @method static bool nullOrImplementsInterface(mixed|null $class, string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface or that the value is null. + * @method static bool nullOrInArray(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice() or that the value is null. + * @method static bool nullOrInteger(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer or that the value is null. + * @method static bool nullOrIntegerish(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish or that the value is null. + * @method static bool nullOrInterfaceExists(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the interface exists or that the value is null. + * @method static bool nullOrIp(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address or that the value is null. + * @method static bool nullOrIpv4(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address or that the value is null. + * @method static bool nullOrIpv6(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address or that the value is null. + * @method static bool nullOrIsArray(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or that the value is null. + * @method static bool nullOrIsArrayAccessible(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object or that the value is null. + * @method static bool nullOrIsCallable(mixed|null $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable or that the value is null. + * @method static bool nullOrIsCountable(array|Countable|ResourceBundle|SimpleXMLElement|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is countable or that the value is null. + * @method static bool nullOrIsInstanceOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name or that the value is null. + * @method static bool nullOrIsJsonString(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string or that the value is null. + * @method static bool nullOrIsObject(mixed|null $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object or that the value is null. + * @method static bool nullOrIsResource(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a resource or that the value is null. + * @method static bool nullOrIsTraversable(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object or that the value is null. + * @method static bool nullOrKeyExists(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array or that the value is null. + * @method static bool nullOrKeyIsset(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset() or that the value is null. + * @method static bool nullOrKeyNotExists(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array or that the value is null. + * @method static bool nullOrLength(mixed|null $value, int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length or that the value is null. + * @method static bool nullOrLessOrEqualThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit or that the value is null. + * @method static bool nullOrLessThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit or that the value is null. + * @method static bool nullOrMax(mixed|null $value, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit or that the value is null. + * @method static bool nullOrMaxCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements or that the value is null. + * @method static bool nullOrMaxLength(mixed|null $value, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars or that the value is null. + * @method static bool nullOrMethodExists(string|null $value, mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object or that the value is null. + * @method static bool nullOrMin(mixed|null $value, mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit or that the value is null. + * @method static bool nullOrMinCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements or that the value is null. + * @method static bool nullOrMinLength(mixed|null $value, int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long or that the value is null. + * @method static bool nullOrNoContent(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is empty or that the value is null. + * @method static bool nullOrNotBlank(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not blank or that the value is null. + * @method static bool nullOrNotContains(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars or that the value is null. + * @method static bool nullOrNotEmpty(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not empty or that the value is null. + * @method static bool nullOrNotEmptyKey(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty or that the value is null. + * @method static bool nullOrNotEq(mixed|null $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==) or that the value is null. + * @method static bool nullOrNotInArray(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices or that the value is null. + * @method static bool nullOrNotIsInstanceOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name or that the value is null. + * @method static bool nullOrNotNull(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not null or that the value is null. + * @method static bool nullOrNotRegex(mixed|null $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex or that the value is null. + * @method static bool nullOrNotSame(mixed|null $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===) or that the value is null. + * @method static bool nullOrNull(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is null or that the value is null. + * @method static bool nullOrNumeric(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is numeric or that the value is null. + * @method static bool nullOrObjectOrClass(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists or that the value is null. + * @method static bool nullOrPhpVersion(string|null $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version or that the value is null. + * @method static bool nullOrPropertiesExist(mixed|null $value, array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist or that the value is null. + * @method static bool nullOrPropertyExists(mixed|null $value, string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists or that the value is null. + * @method static bool nullOrRange(mixed|null $value, mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers or that the value is null. + * @method static bool nullOrReadable(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something readable or that the value is null. + * @method static bool nullOrRegex(mixed|null $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex or that the value is null. + * @method static bool nullOrSame(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===) or that the value is null. + * @method static bool nullOrSatisfy(mixed|null $value, callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback or that the value is null. + * @method static bool nullOrScalar(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar or that the value is null. + * @method static bool nullOrStartsWith(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars or that the value is null. + * @method static bool nullOrString(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a string or that the value is null. + * @method static bool nullOrSubclassOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name or that the value is null. + * @method static bool nullOrTrue(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True or that the value is null. + * @method static bool nullOrUniqueValues(array|null $values, string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality) or that the value is null. + * @method static bool nullOrUrl(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an URL or that the value is null. + * @method static bool nullOrUuid(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID or that the value is null. + * @method static bool nullOrVersion(string|null $version1, string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions or that the value is null. + * @method static bool nullOrWriteable(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable or that the value is null. + */ +class Assertion +{ + const INVALID_FLOAT = 9; + const INVALID_INTEGER = 10; + const INVALID_DIGIT = 11; + const INVALID_INTEGERISH = 12; + const INVALID_BOOLEAN = 13; + const VALUE_EMPTY = 14; + const VALUE_NULL = 15; + const VALUE_NOT_NULL = 25; + const INVALID_STRING = 16; + const INVALID_REGEX = 17; + const INVALID_MIN_LENGTH = 18; + const INVALID_MAX_LENGTH = 19; + const INVALID_STRING_START = 20; + const INVALID_STRING_CONTAINS = 21; + const INVALID_CHOICE = 22; + const INVALID_NUMERIC = 23; + const INVALID_ARRAY = 24; + const INVALID_KEY_EXISTS = 26; + const INVALID_NOT_BLANK = 27; + const INVALID_INSTANCE_OF = 28; + const INVALID_SUBCLASS_OF = 29; + const INVALID_RANGE = 30; + const INVALID_ALNUM = 31; + const INVALID_TRUE = 32; + const INVALID_EQ = 33; + const INVALID_SAME = 34; + const INVALID_MIN = 35; + const INVALID_MAX = 36; + const INVALID_LENGTH = 37; + const INVALID_FALSE = 38; + const INVALID_STRING_END = 39; + const INVALID_UUID = 40; + const INVALID_COUNT = 41; + const INVALID_NOT_EQ = 42; + const INVALID_NOT_SAME = 43; + const INVALID_TRAVERSABLE = 44; + const INVALID_ARRAY_ACCESSIBLE = 45; + const INVALID_KEY_ISSET = 46; + const INVALID_VALUE_IN_ARRAY = 47; + const INVALID_E164 = 48; + const INVALID_BASE64 = 49; + const INVALID_NOT_REGEX = 50; + const INVALID_DIRECTORY = 101; + const INVALID_FILE = 102; + const INVALID_READABLE = 103; + const INVALID_WRITEABLE = 104; + const INVALID_CLASS = 105; + const INVALID_INTERFACE = 106; + const INVALID_FILE_NOT_EXISTS = 107; + const INVALID_EMAIL = 201; + const INTERFACE_NOT_IMPLEMENTED = 202; + const INVALID_URL = 203; + const INVALID_NOT_INSTANCE_OF = 204; + const VALUE_NOT_EMPTY = 205; + const INVALID_JSON_STRING = 206; + const INVALID_OBJECT = 207; + const INVALID_METHOD = 208; + const INVALID_SCALAR = 209; + const INVALID_LESS = 210; + const INVALID_LESS_OR_EQUAL = 211; + const INVALID_GREATER = 212; + const INVALID_GREATER_OR_EQUAL = 213; + const INVALID_DATE = 214; + const INVALID_CALLABLE = 215; + const INVALID_KEY_NOT_EXISTS = 216; + const INVALID_SATISFY = 217; + const INVALID_IP = 218; + const INVALID_BETWEEN = 219; + const INVALID_BETWEEN_EXCLUSIVE = 220; + const INVALID_EXTENSION = 222; + const INVALID_CONSTANT = 221; + const INVALID_VERSION = 223; + const INVALID_PROPERTY = 224; + const INVALID_RESOURCE = 225; + const INVALID_COUNTABLE = 226; + const INVALID_MIN_COUNT = 227; + const INVALID_MAX_COUNT = 228; + const INVALID_STRING_NOT_CONTAINS = 229; + const INVALID_UNIQUE_VALUES = 230; + + /** + * Exception to throw when an assertion failed. + * + * @var string + */ + protected static $exceptionClass = InvalidArgumentException::class; + + /** + * Assert that two values are equal (using ==). + * + * @param mixed $value + * @param mixed $value2 + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function eq($value, $value2, $message = null, string $propertyPath = null): bool + { + if ($value != $value2) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" does not equal expected value "%s".'), + static::stringify($value), + static::stringify($value2) + ); + + throw static::createException($value, $message, static::INVALID_EQ, $propertyPath, ['expected' => $value2]); + } + + return true; + } + + /** + * Assert that the array contains the subset. + * + * @param mixed $value + * @param mixed $value2 + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function eqArraySubset($value, $value2, $message = null, string $propertyPath = null): bool + { + static::isArray($value, $message, $propertyPath); + static::isArray($value2, $message, $propertyPath); + + $patched = \array_replace_recursive($value, $value2); + static::eq($patched, $value, $message, $propertyPath); + + return true; + } + + /** + * Assert that two values are the same (using ===). + * + * @param mixed $value + * @param mixed $value2 + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-template ExpectedType + * @psalm-param ExpectedType $value2 + * @psalm-assert =ExpectedType $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function same($value, $value2, $message = null, string $propertyPath = null): bool + { + if ($value !== $value2) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not the same as expected value "%s".'), + static::stringify($value), + static::stringify($value2) + ); + + throw static::createException($value, $message, static::INVALID_SAME, $propertyPath, ['expected' => $value2]); + } + + return true; + } + + /** + * Assert that two values are not equal (using ==). + * + * @param mixed $value1 + * @param mixed $value2 + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function notEq($value1, $value2, $message = null, string $propertyPath = null): bool + { + if ($value1 == $value2) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" was not expected to be equal to value "%s".'), + static::stringify($value1), + static::stringify($value2) + ); + throw static::createException($value1, $message, static::INVALID_NOT_EQ, $propertyPath, ['expected' => $value2]); + } + + return true; + } + + /** + * Assert that two values are not the same (using ===). + * + * @param mixed $value1 + * @param mixed $value2 + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-template ExpectedType + * @psalm-param ExpectedType $value2 + * @psalm-assert !=ExpectedType $value1 + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function notSame($value1, $value2, $message = null, string $propertyPath = null): bool + { + if ($value1 === $value2) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" was not expected to be the same as value "%s".'), + static::stringify($value1), + static::stringify($value2) + ); + throw static::createException($value1, $message, static::INVALID_NOT_SAME, $propertyPath, ['expected' => $value2]); + } + + return true; + } + + /** + * Assert that value is not in array of choices. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function notInArray($value, array $choices, $message = null, string $propertyPath = null): bool + { + if (true === \in_array($value, $choices)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" was not expected to be an element of the values: %s'), + static::stringify($value), + static::stringify($choices) + ); + throw static::createException($value, $message, static::INVALID_VALUE_IN_ARRAY, $propertyPath, ['choices' => $choices]); + } + + return true; + } + + /** + * Assert that value is a php integer. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert int $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function integer($value, $message = null, string $propertyPath = null): bool + { + if (!\is_int($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not an integer.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_INTEGER, $propertyPath); + } + + return true; + } + + /** + * Assert that value is a php float. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert float $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function float($value, $message = null, string $propertyPath = null): bool + { + if (!\is_float($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a float.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_FLOAT, $propertyPath); + } + + return true; + } + + /** + * Validates if an integer or integerish is a digit. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =numeric $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function digit($value, $message = null, string $propertyPath = null): bool + { + if (!\ctype_digit((string)$value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a digit.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_DIGIT, $propertyPath); + } + + return true; + } + + /** + * Assert that value is a php integer'ish. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function integerish($value, $message = null, string $propertyPath = null): bool + { + if ( + \is_resource($value) || + \is_object($value) || + \is_bool($value) || + \is_null($value) || + \is_array($value) || + (\is_string($value) && '' == $value) || + ( + \strval(\intval($value)) !== \strval($value) && + \strval(\intval($value)) !== \strval(\ltrim($value, '0')) && + '' !== \strval(\intval($value)) && + '' !== \strval(\ltrim($value, '0')) + ) + ) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not an integer or a number castable to integer.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_INTEGERISH, $propertyPath); + } + + return true; + } + + /** + * Assert that value is php boolean. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert bool $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function boolean($value, $message = null, string $propertyPath = null): bool + { + if (!\is_bool($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a boolean.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_BOOLEAN, $propertyPath); + } + + return true; + } + + /** + * Assert that value is a PHP scalar. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert scalar $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function scalar($value, $message = null, string $propertyPath = null): bool + { + if (!\is_scalar($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a scalar.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_SCALAR, $propertyPath); + } + + return true; + } + + /** + * Assert that value is not empty. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert !empty $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function notEmpty($value, $message = null, string $propertyPath = null): bool + { + if (empty($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is empty, but non empty value was expected.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::VALUE_EMPTY, $propertyPath); + } + + return true; + } + + /** + * Assert that value is empty. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert empty $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function noContent($value, $message = null, string $propertyPath = null): bool + { + if (!empty($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not empty, but empty value was expected.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::VALUE_NOT_EMPTY, $propertyPath); + } + + return true; + } + + /** + * Assert that value is null. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert null $value + * + * @return bool + */ + public static function null($value, $message = null, string $propertyPath = null): bool + { + if (null !== $value) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not null, but null value was expected.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::VALUE_NOT_NULL, $propertyPath); + } + + return true; + } + + /** + * Assert that value is not null. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert !null $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function notNull($value, $message = null, string $propertyPath = null): bool + { + if (null === $value) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is null, but non null value was expected.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::VALUE_NULL, $propertyPath); + } + + return true; + } + + /** + * Assert that value is a string. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function string($value, $message = null, string $propertyPath = null) + { + if (!\is_string($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" expected to be string, type %s given.'), + static::stringify($value), + \gettype($value) + ); + + throw static::createException($value, $message, static::INVALID_STRING, $propertyPath); + } + + return true; + } + + /** + * Assert that value matches a regex. + * + * @param mixed $value + * @param string $pattern + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function regex($value, $pattern, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + + if (!\preg_match($pattern, $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" does not match expression.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_REGEX, $propertyPath, ['pattern' => $pattern]); + } + + return true; + } + + /** + * Assert that value does not match a regex. + * + * @param mixed $value + * @param string $pattern + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert !=string $value + * + * @throws AssertionFailedException + */ + public static function notRegex($value, $pattern, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + + if (\preg_match($pattern, $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" matches expression.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_NOT_REGEX, $propertyPath, ['pattern' => $pattern]); + } + + return true; + } + + /** + * Assert that string has a given length. + * + * @param mixed $value + * @param int $length + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function length($value, $length, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($value, $message, $propertyPath); + + if (\mb_strlen($value, $encoding) !== $length) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" has to be %d exactly characters long, but length is %d.'), + static::stringify($value), + $length, + \mb_strlen($value, $encoding) + ); + + throw static::createException($value, $message, static::INVALID_LENGTH, $propertyPath, ['length' => $length, 'encoding' => $encoding]); + } + + return true; + } + + /** + * Assert that a string is at least $minLength chars long. + * + * @param mixed $value + * @param int $minLength + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function minLength($value, $minLength, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($value, $message, $propertyPath); + + if (\mb_strlen($value, $encoding) < $minLength) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is too short, it should have at least %d characters, but only has %d characters.'), + static::stringify($value), + $minLength, + \mb_strlen($value, $encoding) + ); + + throw static::createException($value, $message, static::INVALID_MIN_LENGTH, $propertyPath, ['min_length' => $minLength, 'encoding' => $encoding]); + } + + return true; + } + + /** + * Assert that string value is not longer than $maxLength chars. + * + * @param mixed $value + * @param int $maxLength + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function maxLength($value, $maxLength, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($value, $message, $propertyPath); + + if (\mb_strlen($value, $encoding) > $maxLength) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is too long, it should have no more than %d characters, but has %d characters.'), + static::stringify($value), + $maxLength, + \mb_strlen($value, $encoding) + ); + + throw static::createException($value, $message, static::INVALID_MAX_LENGTH, $propertyPath, ['max_length' => $maxLength, 'encoding' => $encoding]); + } + + return true; + } + + /** + * Assert that string length is between min and max lengths. + * + * @param mixed $value + * @param int $minLength + * @param int $maxLength + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function betweenLength($value, $minLength, $maxLength, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($value, $message, $propertyPath); + static::minLength($value, $minLength, $message, $propertyPath, $encoding); + static::maxLength($value, $maxLength, $message, $propertyPath, $encoding); + + return true; + } + + /** + * Assert that string starts with a sequence of chars. + * + * @param mixed $string + * @param string $needle + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $string + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function startsWith($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($string, $message, $propertyPath); + + if (0 !== \mb_strpos($string, $needle, 0, $encoding)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" does not start with "%s".'), + static::stringify($string), + static::stringify($needle) + ); + + throw static::createException($string, $message, static::INVALID_STRING_START, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); + } + + return true; + } + + /** + * Assert that string ends with a sequence of chars. + * + * @param mixed $string + * @param string $needle + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $string + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function endsWith($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($string, $message, $propertyPath); + + $stringPosition = \mb_strlen($string, $encoding) - \mb_strlen($needle, $encoding); + + if (\mb_strripos($string, $needle, 0, $encoding) !== $stringPosition) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" does not end with "%s".'), + static::stringify($string), + static::stringify($needle) + ); + + throw static::createException($string, $message, static::INVALID_STRING_END, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); + } + + return true; + } + + /** + * Assert that string contains a sequence of chars. + * + * @param mixed $string + * @param string $needle + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $string + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function contains($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($string, $message, $propertyPath); + + if (false === \mb_strpos($string, $needle, 0, $encoding)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" does not contain "%s".'), + static::stringify($string), + static::stringify($needle) + ); + + throw static::createException($string, $message, static::INVALID_STRING_CONTAINS, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); + } + + return true; + } + + /** + * Assert that string does not contains a sequence of chars. + * + * @param mixed $string + * @param string $needle + * @param string|callable|null $message + * @param string|null $propertyPath + * @param string $encoding + * + * @psalm-assert =string $string + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function notContains($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool + { + static::string($string, $message, $propertyPath); + + if (false !== \mb_strpos($string, $needle, 0, $encoding)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" contains "%s".'), + static::stringify($string), + static::stringify($needle) + ); + + throw static::createException($string, $message, static::INVALID_STRING_NOT_CONTAINS, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); + } + + return true; + } + + /** + * Assert that value is in array of choices. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function choice($value, array $choices, $message = null, string $propertyPath = null): bool + { + if (!\in_array($value, $choices, true)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not an element of the valid values: %s'), + static::stringify($value), + \implode(', ', \array_map([\get_called_class(), 'stringify'], $choices)) + ); + + throw static::createException($value, $message, static::INVALID_CHOICE, $propertyPath, ['choices' => $choices]); + } + + return true; + } + + /** + * Assert that value is in array of choices. + * + * This is an alias of {@see choice()}. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function inArray($value, array $choices, $message = null, string $propertyPath = null): bool + { + return static::choice($value, $choices, $message, $propertyPath); + } + + /** + * Assert that value is numeric. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert numeric $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function numeric($value, $message = null, string $propertyPath = null): bool + { + if (!\is_numeric($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not numeric.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_NUMERIC, $propertyPath); + } + + return true; + } + + /** + * Assert that value is a resource. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert resource $value + * + * @return bool + */ + public static function isResource($value, $message = null, string $propertyPath = null): bool + { + if (!\is_resource($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a resource.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_RESOURCE, $propertyPath); + } + + return true; + } + + /** + * Assert that value is an array. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert array $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function isArray($value, $message = null, string $propertyPath = null): bool + { + if (!\is_array($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not an array.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_ARRAY, $propertyPath); + } + + return true; + } + + /** + * Assert that value is an array or a traversable object. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert iterable $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function isTraversable($value, $message = null, string $propertyPath = null): bool + { + if (!\is_array($value) && !$value instanceof Traversable) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not an array and does not implement Traversable.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_TRAVERSABLE, $propertyPath); + } + + return true; + } + + /** + * Assert that value is an array or an array-accessible object. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function isArrayAccessible($value, $message = null, string $propertyPath = null): bool + { + if (!\is_array($value) && !$value instanceof ArrayAccess) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not an array and does not implement ArrayAccess.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_ARRAY_ACCESSIBLE, $propertyPath); + } + + return true; + } + + /** + * Assert that value is countable. + * + * @param array|Countable|ResourceBundle|SimpleXMLElement $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert countable $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function isCountable($value, $message = null, string $propertyPath = null): bool + { + if (\function_exists('is_countable')) { + $assert = \is_countable($value); + } else { + $assert = \is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXMLElement; + } + + if (!$assert) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not an array and does not implement Countable.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_COUNTABLE, $propertyPath); + } + + return true; + } + + /** + * Assert that key exists in an array. + * + * @param mixed $value + * @param string|int $key + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function keyExists($value, $key, $message = null, string $propertyPath = null): bool + { + static::isArray($value, $message, $propertyPath); + + if (!\array_key_exists($key, $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Array does not contain an element with key "%s"'), + static::stringify($key) + ); + + throw static::createException($value, $message, static::INVALID_KEY_EXISTS, $propertyPath, ['key' => $key]); + } + + return true; + } + + /** + * Assert that key does not exist in an array. + * + * @param mixed $value + * @param string|int $key + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function keyNotExists($value, $key, $message = null, string $propertyPath = null): bool + { + static::isArray($value, $message, $propertyPath); + + if (\array_key_exists($key, $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Array contains an element with key "%s"'), + static::stringify($key) + ); + + throw static::createException($value, $message, static::INVALID_KEY_NOT_EXISTS, $propertyPath, ['key' => $key]); + } + + return true; + } + + /** + * Assert that values in array are unique (using strict equality). + * + * @param mixed[] $values + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function uniqueValues(array $values, $message = null, string $propertyPath = null): bool + { + foreach ($values as $key => $value) { + if (\array_search($value, $values, true) !== $key) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" occurs more than once in array'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_UNIQUE_VALUES, $propertyPath, ['value' => $value]); + } + } + + return true; + } + + /** + * Assert that key exists in an array/array-accessible object using isset(). + * + * @param mixed $value + * @param string|int $key + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function keyIsset($value, $key, $message = null, string $propertyPath = null): bool + { + static::isArrayAccessible($value, $message, $propertyPath); + + if (!isset($value[$key])) { + $message = \sprintf( + static::generateMessage($message ?: 'The element with key "%s" was not found'), + static::stringify($key) + ); + + throw static::createException($value, $message, static::INVALID_KEY_ISSET, $propertyPath, ['key' => $key]); + } + + return true; + } + + /** + * Assert that key exists in an array/array-accessible object and its value is not empty. + * + * @param mixed $value + * @param string|int $key + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function notEmptyKey($value, $key, $message = null, string $propertyPath = null): bool + { + static::keyIsset($value, $key, $message, $propertyPath); + static::notEmpty($value[$key], $message, $propertyPath); + + return true; + } + + /** + * Assert that value is not blank. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function notBlank($value, $message = null, string $propertyPath = null): bool + { + if (false === $value || (empty($value) && '0' != $value) || (\is_string($value) && '' === \trim($value))) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is blank, but was expected to contain a value.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_NOT_BLANK, $propertyPath); + } + + return true; + } + + /** + * Assert that value is instance of given class-name. + * + * @param mixed $value + * @param string $className + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-template ExpectedType of object + * @psalm-param class-string $className + * @psalm-assert ExpectedType $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function isInstanceOf($value, $className, $message = null, string $propertyPath = null): bool + { + if (!($value instanceof $className)) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" was expected to be instanceof of "%s" but is not.'), + static::stringify($value), + $className + ); + + throw static::createException($value, $message, static::INVALID_INSTANCE_OF, $propertyPath, ['class' => $className]); + } + + return true; + } + + /** + * Assert that value is not instance of given class-name. + * + * @param mixed $value + * @param string $className + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-template ExpectedType of object + * @psalm-param class-string $className + * @psalm-assert !ExpectedType $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function notIsInstanceOf($value, $className, $message = null, string $propertyPath = null): bool + { + if ($value instanceof $className) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" was not expected to be instanceof of "%s".'), + static::stringify($value), + $className + ); + + throw static::createException($value, $message, static::INVALID_NOT_INSTANCE_OF, $propertyPath, ['class' => $className]); + } + + return true; + } + + /** + * Assert that value is subclass of given class-name. + * + * @param mixed $value + * @param string $className + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function subclassOf($value, $className, $message = null, string $propertyPath = null): bool + { + if (!\is_subclass_of($value, $className)) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" was expected to be subclass of "%s".'), + static::stringify($value), + $className + ); + + throw static::createException($value, $message, static::INVALID_SUBCLASS_OF, $propertyPath, ['class' => $className]); + } + + return true; + } + + /** + * Assert that value is in range of numbers. + * + * @param mixed $value + * @param mixed $minValue + * @param mixed $maxValue + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =numeric $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function range($value, $minValue, $maxValue, $message = null, string $propertyPath = null): bool + { + static::numeric($value, $message, $propertyPath); + + if ($value < $minValue || $value > $maxValue) { + $message = \sprintf( + static::generateMessage($message ?: 'Number "%s" was expected to be at least "%d" and at most "%d".'), + static::stringify($value), + static::stringify($minValue), + static::stringify($maxValue) + ); + + throw static::createException($value, $message, static::INVALID_RANGE, $propertyPath, ['min' => $minValue, 'max' => $maxValue]); + } + + return true; + } + + /** + * Assert that a value is at least as big as a given limit. + * + * @param mixed $value + * @param mixed $minValue + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =numeric $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function min($value, $minValue, $message = null, string $propertyPath = null): bool + { + static::numeric($value, $message, $propertyPath); + + if ($value < $minValue) { + $message = \sprintf( + static::generateMessage($message ?: 'Number "%s" was expected to be at least "%s".'), + static::stringify($value), + static::stringify($minValue) + ); + + throw static::createException($value, $message, static::INVALID_MIN, $propertyPath, ['min' => $minValue]); + } + + return true; + } + + /** + * Assert that a number is smaller as a given limit. + * + * @param mixed $value + * @param mixed $maxValue + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =numeric $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function max($value, $maxValue, $message = null, string $propertyPath = null): bool + { + static::numeric($value, $message, $propertyPath); + + if ($value > $maxValue) { + $message = \sprintf( + static::generateMessage($message ?: 'Number "%s" was expected to be at most "%s".'), + static::stringify($value), + static::stringify($maxValue) + ); + + throw static::createException($value, $message, static::INVALID_MAX, $propertyPath, ['max' => $maxValue]); + } + + return true; + } + + /** + * Assert that a file exists. + * + * @param string $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function file($value, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + static::notEmpty($value, $message, $propertyPath); + + if (!\is_file($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'File "%s" was expected to exist.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_FILE, $propertyPath); + } + + return true; + } + + /** + * Assert that a directory exists. + * + * @param string $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function directory($value, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + + if (!\is_dir($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Path "%s" was expected to be a directory.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_DIRECTORY, $propertyPath); + } + + return true; + } + + /** + * Assert that the value is something readable. + * + * @param string $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function readable($value, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + + if (!\is_readable($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Path "%s" was expected to be readable.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_READABLE, $propertyPath); + } + + return true; + } + + /** + * Assert that the value is something writeable. + * + * @param string $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function writeable($value, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + + if (!\is_writable($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Path "%s" was expected to be writeable.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_WRITEABLE, $propertyPath); + } + + return true; + } + + /** + * Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL). + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function email($value, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + + if (!\filter_var($value, FILTER_VALIDATE_EMAIL)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" was expected to be a valid e-mail address.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_EMAIL, $propertyPath); + } + + return true; + } + + /** + * Assert that value is an URL. + * + * This code snipped was taken from the Symfony project and modified to the special demands of this method. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + * + * @see https://github.com/symfony/Validator/blob/master/Constraints/UrlValidator.php + * @see https://github.com/symfony/Validator/blob/master/Constraints/Url.php + */ + public static function url($value, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + + $protocols = ['http', 'https']; + + $pattern = '~^ + (%s):// # protocol + (([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth + ( + ([\pL\pN\pS\-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name + | # or + \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address + | # or + \[ + (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) + \] # an IPv6 address + ) + (:[0-9]+)? # a port (optional) + (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path + (?:\? (?:[\pL\pN\-._\~!$&\'\[\]()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional) + (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional) + $~ixu'; + + $pattern = \sprintf($pattern, \implode('|', $protocols)); + + if (!\preg_match($pattern, $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" was expected to be a valid URL starting with http or https'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_URL, $propertyPath); + } + + return true; + } + + /** + * Assert that value is alphanumeric. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function alnum($value, $message = null, string $propertyPath = null): bool + { + try { + static::regex($value, '(^([a-zA-Z]{1}[a-zA-Z0-9]*)$)', $message, $propertyPath); + } catch (Throwable $e) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not alphanumeric, starting with letters and containing only letters and numbers.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_ALNUM, $propertyPath); + } + + return true; + } + + /** + * Assert that the value is boolean True. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert true $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function true($value, $message = null, string $propertyPath = null): bool + { + if (true !== $value) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not TRUE.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_TRUE, $propertyPath); + } + + return true; + } + + /** + * Assert that the value is boolean False. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert false $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function false($value, $message = null, string $propertyPath = null): bool + { + if (false !== $value) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not FALSE.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_FALSE, $propertyPath); + } + + return true; + } + + /** + * Assert that the class exists. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert class-string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function classExists($value, $message = null, string $propertyPath = null): bool + { + if (!\class_exists($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" does not exist.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_CLASS, $propertyPath); + } + + return true; + } + + /** + * Assert that the interface exists. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert class-string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function interfaceExists($value, $message = null, string $propertyPath = null): bool + { + if (!\interface_exists($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Interface "%s" does not exist.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_INTERFACE, $propertyPath); + } + + return true; + } + + /** + * Assert that the class implements the interface. + * + * @param mixed $class + * @param string $interfaceName + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function implementsInterface($class, $interfaceName, $message = null, string $propertyPath = null): bool + { + try { + $reflection = new ReflectionClass($class); + if (!$reflection->implementsInterface($interfaceName)) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" does not implement interface "%s".'), + static::stringify($class), + static::stringify($interfaceName) + ); + + throw static::createException($class, $message, static::INTERFACE_NOT_IMPLEMENTED, $propertyPath, ['interface' => $interfaceName]); + } + } catch (ReflectionException $e) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" failed reflection.'), + static::stringify($class) + ); + throw static::createException($class, $message, static::INTERFACE_NOT_IMPLEMENTED, $propertyPath, ['interface' => $interfaceName]); + } + + return true; + } + + /** + * Assert that the given string is a valid json string. + * + * NOTICE: + * Since this does a json_decode to determine its validity + * you probably should consider, when using the variable + * content afterwards, just to decode and check for yourself instead + * of using this assertion. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert =string $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function isJsonString($value, $message = null, string $propertyPath = null): bool + { + if (null === \json_decode($value) && JSON_ERROR_NONE !== \json_last_error()) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a valid JSON string.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_JSON_STRING, $propertyPath); + } + + return true; + } + + /** + * Assert that the given string is a valid UUID. + * + * Uses code from {@link https://github.com/ramsey/uuid} that is MIT licensed. + * + * @param string $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function uuid($value, $message = null, string $propertyPath = null): bool + { + $value = \str_replace(['urn:', 'uuid:', '{', '}'], '', $value); + + if ('00000000-0000-0000-0000-000000000000' === $value) { + return true; + } + + if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a valid UUID.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_UUID, $propertyPath); + } + + return true; + } + + /** + * Assert that the given string is a valid E164 Phone Number. + * + * @see https://en.wikipedia.org/wiki/E.164 + * + * @param string $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function e164($value, $message = null, string $propertyPath = null): bool + { + if (!\preg_match('/^\+?[1-9]\d{1,14}$/', $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" is not a valid E164.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_E164, $propertyPath); + } + + return true; + } + + /** + * Assert that the count of countable is equal to count. + * + * @param array|Countable|ResourceBundle|SimpleXMLElement $countable + * @param int $count + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function count($countable, $count, $message = null, string $propertyPath = null): bool + { + if ($count !== \count($countable)) { + $message = \sprintf( + static::generateMessage($message ?: 'List does not contain exactly %d elements (%d given).'), + static::stringify($count), + static::stringify(\count($countable)) + ); + + throw static::createException($countable, $message, static::INVALID_COUNT, $propertyPath, ['count' => $count]); + } + + return true; + } + + /** + * Assert that the countable have at least $count elements. + * + * @param array|Countable|ResourceBundle|SimpleXMLElement $countable + * @param int $count + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function minCount($countable, $count, $message = null, string $propertyPath = null): bool + { + if ($count > \count($countable)) { + $message = \sprintf( + static::generateMessage($message ?: 'List should have at least %d elements, but has %d elements.'), + static::stringify($count), + static::stringify(\count($countable)) + ); + + throw static::createException($countable, $message, static::INVALID_MIN_COUNT, $propertyPath, ['count' => $count]); + } + + return true; + } + + /** + * Assert that the countable have at most $count elements. + * + * @param array|Countable|ResourceBundle|SimpleXMLElement $countable + * @param int $count + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function maxCount($countable, $count, $message = null, string $propertyPath = null): bool + { + if ($count < \count($countable)) { + $message = \sprintf( + static::generateMessage($message ?: 'List should have at most %d elements, but has %d elements.'), + static::stringify($count), + static::stringify(\count($countable)) + ); + + throw static::createException($countable, $message, static::INVALID_MAX_COUNT, $propertyPath, ['count' => $count]); + } + + return true; + } + + /** + * static call handler to implement: + * - "null or assertion" delegation + * - "all" delegation. + * + * @param string $method + * @param array $args + * + * @return bool|mixed + * + * @throws AssertionFailedException + */ + public static function __callStatic($method, $args) + { + if (0 === \strpos($method, 'nullOr')) { + if (!\array_key_exists(0, $args)) { + throw new BadMethodCallException('Missing the first argument.'); + } + + if (null === $args[0]) { + return true; + } + + $method = \substr($method, 6); + + return \call_user_func_array([\get_called_class(), $method], $args); + } + + if (0 === \strpos($method, 'all')) { + if (!\array_key_exists(0, $args)) { + throw new BadMethodCallException('Missing the first argument.'); + } + + static::isTraversable($args[0]); + + $method = \substr($method, 3); + $values = \array_shift($args); + $calledClass = \get_called_class(); + + foreach ($values as $value) { + \call_user_func_array([$calledClass, $method], \array_merge([$value], $args)); + } + + return true; + } + + throw new BadMethodCallException('No assertion Assertion#'.$method.' exists.'); + } + + /** + * Determines if the values array has every choice as key and that this choice has content. + * + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function choicesNotEmpty(array $values, array $choices, $message = null, string $propertyPath = null): bool + { + static::notEmpty($values, $message, $propertyPath); + + foreach ($choices as $choice) { + static::notEmptyKey($values, $choice, $message, $propertyPath); + } + + return true; + } + + /** + * Determines that the named method is defined in the provided object. + * + * @param string $value + * @param mixed $object + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function methodExists($value, $object, $message = null, string $propertyPath = null): bool + { + static::isObject($object, $message, $propertyPath); + + if (!\method_exists($object, $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Expected "%s" does not exist in provided object.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_METHOD, $propertyPath, ['object' => \get_class($object)]); + } + + return true; + } + + /** + * Determines that the provided value is an object. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert object $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function isObject($value, $message = null, string $propertyPath = null): bool + { + if (!\is_object($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is not a valid object.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_OBJECT, $propertyPath); + } + + return true; + } + + /** + * Determines if the value is less than given limit. + * + * @param mixed $value + * @param mixed $limit + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function lessThan($value, $limit, $message = null, string $propertyPath = null): bool + { + if ($value >= $limit) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is not less than "%s".'), + static::stringify($value), + static::stringify($limit) + ); + + throw static::createException($value, $message, static::INVALID_LESS, $propertyPath, ['limit' => $limit]); + } + + return true; + } + + /** + * Determines if the value is less or equal than given limit. + * + * @param mixed $value + * @param mixed $limit + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function lessOrEqualThan($value, $limit, $message = null, string $propertyPath = null): bool + { + if ($value > $limit) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is not less or equal than "%s".'), + static::stringify($value), + static::stringify($limit) + ); + + throw static::createException($value, $message, static::INVALID_LESS_OR_EQUAL, $propertyPath, ['limit' => $limit]); + } + + return true; + } + + /** + * Determines if the value is greater than given limit. + * + * @param mixed $value + * @param mixed $limit + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function greaterThan($value, $limit, $message = null, string $propertyPath = null): bool + { + if ($value <= $limit) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is not greater than "%s".'), + static::stringify($value), + static::stringify($limit) + ); + + throw static::createException($value, $message, static::INVALID_GREATER, $propertyPath, ['limit' => $limit]); + } + + return true; + } + + /** + * Determines if the value is greater or equal than given limit. + * + * @param mixed $value + * @param mixed $limit + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function greaterOrEqualThan($value, $limit, $message = null, string $propertyPath = null): bool + { + if ($value < $limit) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is not greater or equal than "%s".'), + static::stringify($value), + static::stringify($limit) + ); + + throw static::createException($value, $message, static::INVALID_GREATER_OR_EQUAL, $propertyPath, ['limit' => $limit]); + } + + return true; + } + + /** + * Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit. + * + * @param mixed $value + * @param mixed $lowerLimit + * @param mixed $upperLimit + * @param string|callable|null $message + * @param string $propertyPath + * + * @throws AssertionFailedException + */ + public static function between($value, $lowerLimit, $upperLimit, $message = null, string $propertyPath = null): bool + { + if ($lowerLimit > $value || $value > $upperLimit) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is neither greater than or equal to "%s" nor less than or equal to "%s".'), + static::stringify($value), + static::stringify($lowerLimit), + static::stringify($upperLimit) + ); + + throw static::createException($value, $message, static::INVALID_BETWEEN, $propertyPath, ['lower' => $lowerLimit, 'upper' => $upperLimit]); + } + + return true; + } + + /** + * Assert that a value is greater than a lower limit, and less than an upper limit. + * + * @param mixed $value + * @param mixed $lowerLimit + * @param mixed $upperLimit + * @param string|callable|null $message + * @param string $propertyPath + * + * @throws AssertionFailedException + */ + public static function betweenExclusive($value, $lowerLimit, $upperLimit, $message = null, string $propertyPath = null): bool + { + if ($lowerLimit >= $value || $value >= $upperLimit) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is neither greater than "%s" nor less than "%s".'), + static::stringify($value), + static::stringify($lowerLimit), + static::stringify($upperLimit) + ); + + throw static::createException($value, $message, static::INVALID_BETWEEN_EXCLUSIVE, $propertyPath, ['lower' => $lowerLimit, 'upper' => $upperLimit]); + } + + return true; + } + + /** + * Assert that extension is loaded. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function extensionLoaded($value, $message = null, string $propertyPath = null): bool + { + if (!\extension_loaded($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Extension "%s" is required.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_EXTENSION, $propertyPath); + } + + return true; + } + + /** + * Assert that date is valid and corresponds to the given format. + * + * @param string $value + * @param string $format supports all of the options date(), except for the following: + * N, w, W, t, L, o, B, a, A, g, h, I, O, P, Z, c, r + * @param string|callable|null $message + * + * @throws AssertionFailedException + * + * @see http://php.net/manual/function.date.php#refsect1-function.date-parameters + */ + public static function date($value, $format, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + static::string($format, $message, $propertyPath); + + $dateTime = DateTime::createFromFormat('!'.$format, $value); + + if (false === $dateTime || $value !== $dateTime->format($format)) { + $message = \sprintf( + static::generateMessage($message ?: 'Date "%s" is invalid or does not match format "%s".'), + static::stringify($value), + static::stringify($format) + ); + + throw static::createException($value, $message, static::INVALID_DATE, $propertyPath, ['format' => $format]); + } + + return true; + } + + /** + * Assert that the value is an object, or a class that exists. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function objectOrClass($value, $message = null, string $propertyPath = null): bool + { + if (!\is_object($value)) { + static::classExists($value, $message, $propertyPath); + } + + return true; + } + + /** + * Assert that the value is an object or class, and that the property exists. + * + * @param mixed $value + * @param string $property + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function propertyExists($value, $property, $message = null, string $propertyPath = null): bool + { + static::objectOrClass($value); + + if (!\property_exists($value, $property)) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" does not have property "%s".'), + static::stringify($value), + static::stringify($property) + ); + + throw static::createException($value, $message, static::INVALID_PROPERTY, $propertyPath, ['property' => $property]); + } + + return true; + } + + /** + * Assert that the value is an object or class, and that the properties all exist. + * + * @param mixed $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function propertiesExist($value, array $properties, $message = null, string $propertyPath = null): bool + { + static::objectOrClass($value); + static::allString($properties, $message, $propertyPath); + + $invalidProperties = []; + foreach ($properties as $property) { + if (!\property_exists($value, $property)) { + $invalidProperties[] = $property; + } + } + + if ($invalidProperties) { + $message = \sprintf( + static::generateMessage($message ?: 'Class "%s" does not have these properties: %s.'), + static::stringify($value), + static::stringify(\implode(', ', $invalidProperties)) + ); + + throw static::createException($value, $message, static::INVALID_PROPERTY, $propertyPath, ['properties' => $properties]); + } + + return true; + } + + /** + * Assert comparison of two versions. + * + * @param string $version1 + * @param string $operator + * @param string $version2 + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function version($version1, $operator, $version2, $message = null, string $propertyPath = null): bool + { + static::notEmpty($operator, 'versionCompare operator is required and cannot be empty.'); + + if (true !== \version_compare($version1, $version2, $operator)) { + $message = \sprintf( + static::generateMessage($message ?: 'Version "%s" is not "%s" version "%s".'), + static::stringify($version1), + static::stringify($operator), + static::stringify($version2) + ); + + throw static::createException($version1, $message, static::INVALID_VERSION, $propertyPath, ['operator' => $operator, 'version' => $version2]); + } + + return true; + } + + /** + * Assert on PHP version. + * + * @param string $operator + * @param mixed $version + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function phpVersion($operator, $version, $message = null, string $propertyPath = null): bool + { + static::defined('PHP_VERSION'); + + return static::version(PHP_VERSION, $operator, $version, $message, $propertyPath); + } + + /** + * Assert that extension is loaded and a specific version is installed. + * + * @param string $extension + * @param string $operator + * @param mixed $version + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function extensionVersion($extension, $operator, $version, $message = null, string $propertyPath = null): bool + { + static::extensionLoaded($extension, $message, $propertyPath); + + return static::version(\phpversion($extension), $operator, $version, $message, $propertyPath); + } + + /** + * Determines that the provided value is callable. + * + * @param mixed $value + * @param string|callable|null $message + * @param string|null $propertyPath + * + * @psalm-assert callable $value + * + * @return bool + * + * @throws AssertionFailedException + */ + public static function isCallable($value, $message = null, string $propertyPath = null): bool + { + if (!\is_callable($value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is not a callable.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_CALLABLE, $propertyPath); + } + + return true; + } + + /** + * Assert that the provided value is valid according to a callback. + * + * If the callback returns `false` the assertion will fail. + * + * @param mixed $value + * @param callable $callback + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function satisfy($value, $callback, $message = null, string $propertyPath = null): bool + { + static::isCallable($callback); + + if (false === \call_user_func($callback, $value)) { + $message = \sprintf( + static::generateMessage($message ?: 'Provided "%s" is invalid according to custom rule.'), + static::stringify($value) + ); + + throw static::createException($value, $message, static::INVALID_SATISFY, $propertyPath); + } + + return true; + } + + /** + * Assert that value is an IPv4 or IPv6 address + * (using input_filter/FILTER_VALIDATE_IP). + * + * @param string $value + * @param int|null $flag + * @param string|callable|null $message + * + * @throws AssertionFailedException + * + * @see http://php.net/manual/filter.filters.flags.php + */ + public static function ip($value, $flag = null, $message = null, string $propertyPath = null): bool + { + static::string($value, $message, $propertyPath); + if ($flag === null) { + $filterVarResult = \filter_var($value, FILTER_VALIDATE_IP); + } else { + $filterVarResult = \filter_var($value, FILTER_VALIDATE_IP, $flag); + } + if (!$filterVarResult) { + $message = \sprintf( + static::generateMessage($message ?: 'Value "%s" was expected to be a valid IP address.'), + static::stringify($value) + ); + throw static::createException($value, $message, static::INVALID_IP, $propertyPath, ['flag' => $flag]); + } + + return true; + } + + /** + * Assert that value is an IPv4 address + * (using input_filter/FILTER_VALIDATE_IP). + * + * @param string $value + * @param int|null $flag + * @param string|callable|null $message + * + * @throws AssertionFailedException + * + * @see http://php.net/manual/filter.filters.flags.php + */ + public static function ipv4($value, $flag = null, $message = null, string $propertyPath = null): bool + { + static::ip($value, $flag | FILTER_FLAG_IPV4, static::generateMessage($message ?: 'Value "%s" was expected to be a valid IPv4 address.'), $propertyPath); + + return true; + } + + /** + * Assert that value is an IPv6 address + * (using input_filter/FILTER_VALIDATE_IP). + * + * @param string $value + * @param int|null $flag + * @param string|callable|null $message + * + * @throws AssertionFailedException + * + * @see http://php.net/manual/filter.filters.flags.php + */ + public static function ipv6($value, $flag = null, $message = null, string $propertyPath = null): bool + { + static::ip($value, $flag | FILTER_FLAG_IPV6, static::generateMessage($message ?: 'Value "%s" was expected to be a valid IPv6 address.'), $propertyPath); + + return true; + } + + /** + * Assert that a constant is defined. + * + * @param mixed $constant + * @param string|callable|null $message + */ + public static function defined($constant, $message = null, string $propertyPath = null): bool + { + if (!\defined($constant)) { + $message = \sprintf(static::generateMessage($message ?: 'Value "%s" expected to be a defined constant.'), $constant); + + throw static::createException($constant, $message, static::INVALID_CONSTANT, $propertyPath); + } + + return true; + } + + /** + * Assert that a constant is defined. + * + * @param string $value + * @param string|callable|null $message + * + * @throws AssertionFailedException + */ + public static function base64($value, $message = null, string $propertyPath = null): bool + { + if (false === \base64_decode($value, true)) { + $message = \sprintf(static::generateMessage($message ?: 'Value "%s" is not a valid base64 string.'), $value); + + throw static::createException($value, $message, static::INVALID_BASE64, $propertyPath); + } + + return true; + } + + /** + * Helper method that handles building the assertion failure exceptions. + * They are returned from this method so that the stack trace still shows + * the assertions method. + * + * @param mixed $value + * @param string|callable|null $message + * @param int $code + * + * @return mixed + */ + protected static function createException($value, $message, $code, $propertyPath = null, array $constraints = []) + { + $exceptionClass = static::$exceptionClass; + + return new $exceptionClass($message, $code, $propertyPath, $value, $constraints); + } + + /** + * Make a string version of a value. + * + * @param mixed $value + */ + protected static function stringify($value): string + { + $result = \gettype($value); + + if (\is_bool($value)) { + $result = $value ? '' : ''; + } elseif (\is_scalar($value)) { + $val = (string)$value; + + if (\mb_strlen($val) > 100) { + $val = \mb_substr($val, 0, 97).'...'; + } + + $result = $val; + } elseif (\is_array($value)) { + $result = ''; + } elseif (\is_object($value)) { + $result = \get_class($value); + } elseif (\is_resource($value)) { + $result = \get_resource_type($value); + } elseif (null === $value) { + $result = ''; + } + + return $result; + } + + /** + * Generate the message. + * + * @param string|callable|null $message + */ + protected static function generateMessage($message): string + { + if (\is_callable($message)) { + $traces = \debug_backtrace(0); + + $parameters = []; + + try { + $reflection = new ReflectionClass($traces[1]['class']); + $method = $reflection->getMethod($traces[1]['function']); + foreach ($method->getParameters() as $index => $parameter) { + if ('message' !== $parameter->getName()) { + $parameters[$parameter->getName()] = \array_key_exists($index, $traces[1]['args']) + ? $traces[1]['args'][$index] + : $parameter->getDefaultValue(); + } + } + + $parameters['::assertion'] = \sprintf('%s%s%s', $traces[1]['class'], $traces[1]['type'], $traces[1]['function']); + + $message = \call_user_func_array($message, [$parameters]); + } // @codeCoverageIgnoreStart + catch (Throwable $exception) { + $message = \sprintf('Unable to generate message : %s', $exception->getMessage()); + } // @codeCoverageIgnoreEnd + } + + return (string)$message; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionChain.php b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionChain.php new file mode 100644 index 00000000..4c444350 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionChain.php @@ -0,0 +1,247 @@ + + * + * @method AssertionChain alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric. + * @method AssertionChain base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. + * @method AssertionChain between(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit. + * @method AssertionChain betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit. + * @method AssertionChain betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths. + * @method AssertionChain boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean. + * @method AssertionChain choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. + * @method AssertionChain choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content. + * @method AssertionChain classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists. + * @method AssertionChain contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars. + * @method AssertionChain count(int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count. + * @method AssertionChain date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format. + * @method AssertionChain defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. + * @method AssertionChain digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit. + * @method AssertionChain directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists. + * @method AssertionChain e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number. + * @method AssertionChain email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL). + * @method AssertionChain endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars. + * @method AssertionChain eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==). + * @method AssertionChain eqArraySubset(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset. + * @method AssertionChain extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded. + * @method AssertionChain extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed. + * @method AssertionChain false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False. + * @method AssertionChain file(string|callable $message = null, string $propertyPath = null) Assert that a file exists. + * @method AssertionChain float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float. + * @method AssertionChain greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit. + * @method AssertionChain greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit. + * @method AssertionChain implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface. + * @method AssertionChain inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice(). + * @method AssertionChain integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer. + * @method AssertionChain integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish. + * @method AssertionChain interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists. + * @method AssertionChain ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address. + * @method AssertionChain ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address. + * @method AssertionChain ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address. + * @method AssertionChain isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array. + * @method AssertionChain isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object. + * @method AssertionChain isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable. + * @method AssertionChain isCountable(string|callable $message = null, string $propertyPath = null) Assert that value is countable. + * @method AssertionChain isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name. + * @method AssertionChain isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string. + * @method AssertionChain isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object. + * @method AssertionChain isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource. + * @method AssertionChain isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object. + * @method AssertionChain keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array. + * @method AssertionChain keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset(). + * @method AssertionChain keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array. + * @method AssertionChain length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length. + * @method AssertionChain lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit. + * @method AssertionChain lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit. + * @method AssertionChain max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit. + * @method AssertionChain maxCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements. + * @method AssertionChain maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars. + * @method AssertionChain methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object. + * @method AssertionChain min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit. + * @method AssertionChain minCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements. + * @method AssertionChain minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long. + * @method AssertionChain noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty. + * @method AssertionChain notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank. + * @method AssertionChain notContains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars. + * @method AssertionChain notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty. + * @method AssertionChain notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty. + * @method AssertionChain notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==). + * @method AssertionChain notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices. + * @method AssertionChain notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name. + * @method AssertionChain notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null. + * @method AssertionChain notRegex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex. + * @method AssertionChain notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===). + * @method AssertionChain null(string|callable $message = null, string $propertyPath = null) Assert that value is null. + * @method AssertionChain numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric. + * @method AssertionChain objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists. + * @method AssertionChain phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version. + * @method AssertionChain propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist. + * @method AssertionChain propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists. + * @method AssertionChain range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers. + * @method AssertionChain readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable. + * @method AssertionChain regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex. + * @method AssertionChain same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===). + * @method AssertionChain satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback. + * @method AssertionChain scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar. + * @method AssertionChain startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars. + * @method AssertionChain string(string|callable $message = null, string $propertyPath = null) Assert that value is a string. + * @method AssertionChain subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name. + * @method AssertionChain true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True. + * @method AssertionChain uniqueValues(string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality). + * @method AssertionChain url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL. + * @method AssertionChain uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID. + * @method AssertionChain version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions. + * @method AssertionChain writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable. + */ +class AssertionChain +{ + /** + * @var mixed + */ + private $value; + + /** + * @var string|callable|null + */ + private $defaultMessage; + + /** + * @var string|null + */ + private $defaultPropertyPath; + + /** + * Return each assertion as always valid. + * + * @var bool + */ + private $alwaysValid = false; + + /** + * Perform assertion on every element of array or traversable. + * + * @var bool + */ + private $all = false; + + /** @var string|Assertion Class to use for assertion calls */ + private $assertionClassName = 'Assert\Assertion'; + + /** + * AssertionChain constructor. + * + * @param mixed $value + * @param string|callable|null $defaultMessage + */ + public function __construct($value, $defaultMessage = null, string $defaultPropertyPath = null) + { + $this->value = $value; + $this->defaultMessage = $defaultMessage; + $this->defaultPropertyPath = $defaultPropertyPath; + } + + /** + * Call assertion on the current value in the chain. + * + * @param string $methodName + * @param array $args + */ + public function __call($methodName, $args): AssertionChain + { + if (true === $this->alwaysValid) { + return $this; + } + + try { + $method = new \ReflectionMethod($this->assertionClassName, $methodName); + } catch (\ReflectionException $exception) { + throw new \RuntimeException("Assertion '".$methodName."' does not exist."); + } + + \array_unshift($args, $this->value); + $params = $method->getParameters(); + + foreach ($params as $idx => $param) { + if (isset($args[$idx])) { + continue; + } + + switch ($param->getName()) { + case 'message': + $args[$idx] = $this->defaultMessage; + break; + case 'propertyPath': + $args[$idx] = $this->defaultPropertyPath; + break; + } + } + + if ($this->all) { + $methodName = 'all'.$methodName; + } + + \call_user_func_array([$this->assertionClassName, $methodName], $args); + + return $this; + } + + /** + * Switch chain into validation mode for an array of values. + */ + public function all(): AssertionChain + { + $this->all = true; + + return $this; + } + + /** + * Switch chain into mode allowing nulls, ignoring further assertions. + */ + public function nullOr(): AssertionChain + { + if (null === $this->value) { + $this->alwaysValid = true; + } + + return $this; + } + + /** + * @param string $className + * + * @return $this + */ + public function setAssertionClassName($className): AssertionChain + { + if (!\is_string($className)) { + throw new LogicException('Exception class name must be passed as a string'); + } + + if (Assertion::class !== $className && !\is_subclass_of($className, Assertion::class)) { + throw new LogicException($className.' is not (a subclass of) '.Assertion::class); + } + + $this->assertionClassName = $className; + + return $this; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionFailedException.php b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionFailedException.php new file mode 100644 index 00000000..7e0b2ec3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/AssertionFailedException.php @@ -0,0 +1,32 @@ +propertyPath = $propertyPath; + $this->value = $value; + $this->constraints = $constraints; + } + + /** + * User controlled way to define a sub-property causing + * the failure of a currently asserted objects. + * + * Useful to transport information about the nature of the error + * back to higher layers. + * + * @return string|null + */ + public function getPropertyPath() + { + return $this->propertyPath; + } + + /** + * Get the value that caused the assertion to fail. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * Get the constraints that applied to the failed assertion. + */ + public function getConstraints(): array + { + return $this->constraints; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertion.php b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertion.php new file mode 100644 index 00000000..b3052178 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertion.php @@ -0,0 +1,228 @@ + + * + * @method LazyAssertion alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric. + * @method LazyAssertion base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. + * @method LazyAssertion between(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit. + * @method LazyAssertion betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit. + * @method LazyAssertion betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths. + * @method LazyAssertion boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean. + * @method LazyAssertion choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. + * @method LazyAssertion choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content. + * @method LazyAssertion classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists. + * @method LazyAssertion contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars. + * @method LazyAssertion count(int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count. + * @method LazyAssertion date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format. + * @method LazyAssertion defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined. + * @method LazyAssertion digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit. + * @method LazyAssertion directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists. + * @method LazyAssertion e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number. + * @method LazyAssertion email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL). + * @method LazyAssertion endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars. + * @method LazyAssertion eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==). + * @method LazyAssertion eqArraySubset(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset. + * @method LazyAssertion extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded. + * @method LazyAssertion extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed. + * @method LazyAssertion false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False. + * @method LazyAssertion file(string|callable $message = null, string $propertyPath = null) Assert that a file exists. + * @method LazyAssertion float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float. + * @method LazyAssertion greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit. + * @method LazyAssertion greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit. + * @method LazyAssertion implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface. + * @method LazyAssertion inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice(). + * @method LazyAssertion integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer. + * @method LazyAssertion integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish. + * @method LazyAssertion interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists. + * @method LazyAssertion ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address. + * @method LazyAssertion ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address. + * @method LazyAssertion ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address. + * @method LazyAssertion isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array. + * @method LazyAssertion isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object. + * @method LazyAssertion isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable. + * @method LazyAssertion isCountable(string|callable $message = null, string $propertyPath = null) Assert that value is countable. + * @method LazyAssertion isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name. + * @method LazyAssertion isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string. + * @method LazyAssertion isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object. + * @method LazyAssertion isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource. + * @method LazyAssertion isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object. + * @method LazyAssertion keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array. + * @method LazyAssertion keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset(). + * @method LazyAssertion keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array. + * @method LazyAssertion length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length. + * @method LazyAssertion lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit. + * @method LazyAssertion lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit. + * @method LazyAssertion max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit. + * @method LazyAssertion maxCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements. + * @method LazyAssertion maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars. + * @method LazyAssertion methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object. + * @method LazyAssertion min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit. + * @method LazyAssertion minCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements. + * @method LazyAssertion minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long. + * @method LazyAssertion noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty. + * @method LazyAssertion notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank. + * @method LazyAssertion notContains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars. + * @method LazyAssertion notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty. + * @method LazyAssertion notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty. + * @method LazyAssertion notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==). + * @method LazyAssertion notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices. + * @method LazyAssertion notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name. + * @method LazyAssertion notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null. + * @method LazyAssertion notRegex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex. + * @method LazyAssertion notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===). + * @method LazyAssertion null(string|callable $message = null, string $propertyPath = null) Assert that value is null. + * @method LazyAssertion numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric. + * @method LazyAssertion objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists. + * @method LazyAssertion phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version. + * @method LazyAssertion propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist. + * @method LazyAssertion propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists. + * @method LazyAssertion range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers. + * @method LazyAssertion readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable. + * @method LazyAssertion regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex. + * @method LazyAssertion same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===). + * @method LazyAssertion satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback. + * @method LazyAssertion scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar. + * @method LazyAssertion startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars. + * @method LazyAssertion string(string|callable $message = null, string $propertyPath = null) Assert that value is a string. + * @method LazyAssertion subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name. + * @method LazyAssertion true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True. + * @method LazyAssertion uniqueValues(string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality). + * @method LazyAssertion url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL. + * @method LazyAssertion uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID. + * @method LazyAssertion version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions. + * @method LazyAssertion writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable. + * @method LazyAssertion all() Switch chain into validation mode for an array of values. + * @method LazyAssertion nullOr() Switch chain into mode allowing nulls, ignoring further assertions. + */ +class LazyAssertion +{ + private $currentChainFailed = false; + private $alwaysTryAll = false; + private $thisChainTryAll = false; + private $currentChain; + private $errors = []; + + /** @var string The class to use as AssertionChain factory */ + private $assertClass = Assert::class; + + /** @var string|LazyAssertionException The class to use for exceptions */ + private $exceptionClass = LazyAssertionException::class; + + /** + * @param mixed $value + * @param string|callable|null $defaultMessage + * + * @return static + */ + public function that($value, string $propertyPath = null, $defaultMessage = null) + { + $this->currentChainFailed = false; + $this->thisChainTryAll = false; + $assertClass = $this->assertClass; + $this->currentChain = $assertClass::that($value, $defaultMessage, $propertyPath); + + return $this; + } + + /** + * @return static + */ + public function tryAll() + { + if (!$this->currentChain) { + $this->alwaysTryAll = true; + } + + $this->thisChainTryAll = true; + + return $this; + } + + /** + * @param string $method + * @param array $args + * + * @return static + */ + public function __call($method, $args) + { + if (false === $this->alwaysTryAll + && false === $this->thisChainTryAll + && true === $this->currentChainFailed + ) { + return $this; + } + + try { + \call_user_func_array([$this->currentChain, $method], $args); + } catch (AssertionFailedException $e) { + $this->errors[] = $e; + $this->currentChainFailed = true; + } + + return $this; + } + + /** + * @throws LazyAssertionException + */ + public function verifyNow(): bool + { + if ($this->errors) { + throw \call_user_func([$this->exceptionClass, 'fromErrors'], $this->errors); + } + + return true; + } + + /** + * @param string $className + * + * @return static + */ + public function setAssertClass(string $className): LazyAssertion + { + if (Assert::class !== $className && !\is_subclass_of($className, Assert::class)) { + throw new LogicException($className.' is not (a subclass of) '.Assert::class); + } + + $this->assertClass = $className; + + return $this; + } + + /** + * @param string $className + * + * @return static + */ + public function setExceptionClass(string $className): LazyAssertion + { + if (LazyAssertionException::class !== $className && !\is_subclass_of($className, LazyAssertionException::class)) { + throw new LogicException($className.' is not (a subclass of) '.LazyAssertionException::class); + } + + $this->exceptionClass = $className; + + return $this; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertionException.php b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertionException.php new file mode 100644 index 00000000..2ba59dd7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/LazyAssertionException.php @@ -0,0 +1,53 @@ +getPropertyPath(), $error->getMessage()); + } + + return new static($message, $errors); + } + + public function __construct($message, array $errors) + { + parent::__construct($message, 0, null, null); + + $this->errors = $errors; + } + + /** + * @return InvalidArgumentException[] + */ + public function getErrorExceptions(): array + { + return $this->errors; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/functions.php b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/functions.php new file mode 100644 index 00000000..1a4e84d9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/beberlei/assert/lib/Assert/functions.php @@ -0,0 +1,72 @@ +notEmpty()->integer(); + * \Assert\that($value)->nullOr()->string()->startsWith("Foo"); + * + * The assertion chain can be stateful, that means be careful when you reuse + * it. You should never pass around the chain. + */ +function that($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain +{ + return Assert::that($value, $defaultMessage, $defaultPropertyPath); +} + +/** + * Start validation on a set of values, returns {@link AssertionChain}. + * + * @param mixed $values + * @param string|callable|null $defaultMessage + * @param string $defaultPropertyPath + */ +function thatAll($values, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain +{ + return Assert::thatAll($values, $defaultMessage, $defaultPropertyPath); +} + +/** + * Start validation and allow NULL, returns {@link AssertionChain}. + * + * @param mixed $value + * @param string|callable|null $defaultMessage + * @param string $defaultPropertyPath + * + * @deprecated In favour of Assert::thatNullOr($value, $defaultMessage = null, $defaultPropertyPath = null) + */ +function thatNullOr($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain +{ + return Assert::thatNullOr($value, $defaultMessage, $defaultPropertyPath); +} + +/** + * Create a lazy assertion object. + */ +function lazy(): LazyAssertion +{ + return Assert::lazy(); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/CHANGELOG.md b/wp-content/plugins/wp-webauthn/vendor/brick/math/CHANGELOG.md new file mode 100644 index 00000000..03c3d824 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/CHANGELOG.md @@ -0,0 +1,415 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [0.9.3](https://github.com/brick/math/releases/tag/0.9.3) - 2021-08-15 + +🚀 **Compatibility with PHP 8.1** + +- Support for custom object serialization; this removes a warning on PHP 8.1 due to the `Serializable` interface being deprecated (thanks @TRowbotham) + +## [0.9.2](https://github.com/brick/math/releases/tag/0.9.2) - 2021-01-20 + +🐛 **Bug fix** + +- Incorrect results could be returned when using the BCMath calculator, with a default scale set with `bcscale()`, on PHP >= 7.2 (#55). + +## [0.9.1](https://github.com/brick/math/releases/tag/0.9.1) - 2020-08-19 + +✨ New features + +- `BigInteger::not()` returns the bitwise `NOT` value + +🐛 **Bug fixes** + +- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers +- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available + +## [0.9.0](https://github.com/brick/math/releases/tag/0.9.0) - 2020-08-18 + +👌 **Improvements** + +- `BigNumber::of()` now accepts `.123` and `123.` formats, both of which return a `BigDecimal` + +💥 **Breaking changes** + +- Deprecated method `BigInteger::powerMod()` has been removed - use `modPow()` instead +- Deprecated method `BigInteger::parse()` has been removed - use `fromBase()` instead + +## [0.8.17](https://github.com/brick/math/releases/tag/0.8.17) - 2020-08-19 + +🐛 **Bug fix** + +- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers +- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available + +## [0.8.16](https://github.com/brick/math/releases/tag/0.8.16) - 2020-08-18 + +🚑 **Critical fix** + +- This version reintroduces the deprecated `BigInteger::parse()` method, that has been removed by mistake in version `0.8.9` and should have lasted for the whole `0.8` release cycle. + +✨ **New features** + +- `BigInteger::modInverse()` calculates a modular multiplicative inverse +- `BigInteger::fromBytes()` creates a `BigInteger` from a byte string +- `BigInteger::toBytes()` converts a `BigInteger` to a byte string +- `BigInteger::randomBits()` creates a pseudo-random `BigInteger` of a given bit length +- `BigInteger::randomRange()` creates a pseudo-random `BigInteger` between two bounds + +💩 **Deprecations** + +- `BigInteger::powerMod()` is now deprecated in favour of `modPow()` + +## [0.8.15](https://github.com/brick/math/releases/tag/0.8.15) - 2020-04-15 + +🐛 **Fixes** + +- added missing `ext-json` requirement, due to `BigNumber` implementing `JsonSerializable` + +⚡️ **Optimizations** + +- additional optimization in `BigInteger::remainder()` + +## [0.8.14](https://github.com/brick/math/releases/tag/0.8.14) - 2020-02-18 + +✨ **New features** + +- `BigInteger::getLowestSetBit()` returns the index of the rightmost one bit + +## [0.8.13](https://github.com/brick/math/releases/tag/0.8.13) - 2020-02-16 + +✨ **New features** + +- `BigInteger::isEven()` tests whether the number is even +- `BigInteger::isOdd()` tests whether the number is odd +- `BigInteger::testBit()` tests if a bit is set +- `BigInteger::getBitLength()` returns the number of bits in the minimal representation of the number + +## [0.8.12](https://github.com/brick/math/releases/tag/0.8.12) - 2020-02-03 + +🛠️ **Maintenance release** + +Classes are now annotated for better static analysis with [psalm](https://psalm.dev/). + +This is a maintenance release: no bug fixes, no new features, no breaking changes. + +## [0.8.11](https://github.com/brick/math/releases/tag/0.8.11) - 2020-01-23 + +✨ **New feature** + +`BigInteger::powerMod()` performs a power-with-modulo operation. Useful for crypto. + +## [0.8.10](https://github.com/brick/math/releases/tag/0.8.10) - 2020-01-21 + +✨ **New feature** + +`BigInteger::mod()` returns the **modulo** of two numbers. The *modulo* differs from the *remainder* when the signs of the operands are different. + +## [0.8.9](https://github.com/brick/math/releases/tag/0.8.9) - 2020-01-08 + +⚡️ **Performance improvements** + +A few additional optimizations in `BigInteger` and `BigDecimal` when one of the operands can be returned as is. Thanks to @tomtomsen in #24. + +## [0.8.8](https://github.com/brick/math/releases/tag/0.8.8) - 2019-04-25 + +🐛 **Bug fixes** + +- `BigInteger::toBase()` could return an empty string for zero values (BCMath & Native calculators only, GMP calculator unaffected) + +✨ **New features** + +- `BigInteger::toArbitraryBase()` converts a number to an arbitrary base, using a custom alphabet +- `BigInteger::fromArbitraryBase()` converts a string in an arbitrary base, using a custom alphabet, back to a number + +These methods can be used as the foundation to convert strings between different bases/alphabets, using BigInteger as an intermediate representation. + +💩 **Deprecations** + +- `BigInteger::parse()` is now deprecated in favour of `fromBase()` + +`BigInteger::fromBase()` works the same way as `parse()`, with 2 minor differences: + +- the `$base` parameter is required, it does not default to `10` +- it throws a `NumberFormatException` instead of an `InvalidArgumentException` when the number is malformed + +## [0.8.7](https://github.com/brick/math/releases/tag/0.8.7) - 2019-04-20 + +**Improvements** + +- Safer conversion from `float` when using custom locales +- **Much faster** `NativeCalculator` implementation 🚀 + +You can expect **at least a 3x performance improvement** for common arithmetic operations when using the library on systems without GMP or BCMath; it gets exponentially faster on multiplications with a high number of digits. This is due to calculations now being performed on whole blocks of digits (the block size depending on the platform, 32-bit or 64-bit) instead of digit-by-digit as before. + +## [0.8.6](https://github.com/brick/math/releases/tag/0.8.6) - 2019-04-11 + +**New method** + +`BigNumber::sum()` returns the sum of one or more numbers. + +## [0.8.5](https://github.com/brick/math/releases/tag/0.8.5) - 2019-02-12 + +**Bug fix**: `of()` factory methods could fail when passing a `float` in environments using a `LC_NUMERIC` locale with a decimal separator other than `'.'` (#20). + +Thanks @manowark 👍 + +## [0.8.4](https://github.com/brick/math/releases/tag/0.8.4) - 2018-12-07 + +**New method** + +`BigDecimal::sqrt()` calculates the square root of a decimal number, to a given scale. + +## [0.8.3](https://github.com/brick/math/releases/tag/0.8.3) - 2018-12-06 + +**New method** + +`BigInteger::sqrt()` calculates the square root of a number (thanks @peter279k). + +**New exception** + +`NegativeNumberException` is thrown when calling `sqrt()` on a negative number. + +## [0.8.2](https://github.com/brick/math/releases/tag/0.8.2) - 2018-11-08 + +**Performance update** + +- Further improvement of `toInt()` performance +- `NativeCalculator` can now perform some multiplications more efficiently + +## [0.8.1](https://github.com/brick/math/releases/tag/0.8.1) - 2018-11-07 + +Performance optimization of `toInt()` methods. + +## [0.8.0](https://github.com/brick/math/releases/tag/0.8.0) - 2018-10-13 + +**Breaking changes** + +The following deprecated methods have been removed. Use the new method name instead: + +| Method removed | Replacement method | +| --- | --- | +| `BigDecimal::getIntegral()` | `BigDecimal::getIntegralPart()` | +| `BigDecimal::getFraction()` | `BigDecimal::getFractionalPart()` | + +--- + +**New features** + +`BigInteger` has been augmented with 5 new methods for bitwise operations: + +| New method | Description | +| --- | --- | +| `and()` | performs a bitwise `AND` operation on two numbers | +| `or()` | performs a bitwise `OR` operation on two numbers | +| `xor()` | performs a bitwise `XOR` operation on two numbers | +| `shiftedLeft()` | returns the number shifted left by a number of bits | +| `shiftedRight()` | returns the number shifted right by a number of bits | + +Thanks to @DASPRiD 👍 + +## [0.7.3](https://github.com/brick/math/releases/tag/0.7.3) - 2018-08-20 + +**New method:** `BigDecimal::hasNonZeroFractionalPart()` + +**Renamed/deprecated methods:** + +- `BigDecimal::getIntegral()` has been renamed to `getIntegralPart()` and is now deprecated +- `BigDecimal::getFraction()` has been renamed to `getFractionalPart()` and is now deprecated + +## [0.7.2](https://github.com/brick/math/releases/tag/0.7.2) - 2018-07-21 + +**Performance update** + +`BigInteger::parse()` and `toBase()` now use GMP's built-in base conversion features when available. + +## [0.7.1](https://github.com/brick/math/releases/tag/0.7.1) - 2018-03-01 + +This is a maintenance release, no code has been changed. + +- When installed with `--no-dev`, the autoloader does not autoload tests anymore +- Tests and other files unnecessary for production are excluded from the dist package + +This will help make installations more compact. + +## [0.7.0](https://github.com/brick/math/releases/tag/0.7.0) - 2017-10-02 + +Methods renamed: + +- `BigNumber:sign()` has been renamed to `getSign()` +- `BigDecimal::unscaledValue()` has been renamed to `getUnscaledValue()` +- `BigDecimal::scale()` has been renamed to `getScale()` +- `BigDecimal::integral()` has been renamed to `getIntegral()` +- `BigDecimal::fraction()` has been renamed to `getFraction()` +- `BigRational::numerator()` has been renamed to `getNumerator()` +- `BigRational::denominator()` has been renamed to `getDenominator()` + +Classes renamed: + +- `ArithmeticException` has been renamed to `MathException` + +## [0.6.2](https://github.com/brick/math/releases/tag/0.6.2) - 2017-10-02 + +The base class for all exceptions is now `MathException`. +`ArithmeticException` has been deprecated, and will be removed in 0.7.0. + +## [0.6.1](https://github.com/brick/math/releases/tag/0.6.1) - 2017-10-02 + +A number of methods have been renamed: + +- `BigNumber:sign()` is deprecated; use `getSign()` instead +- `BigDecimal::unscaledValue()` is deprecated; use `getUnscaledValue()` instead +- `BigDecimal::scale()` is deprecated; use `getScale()` instead +- `BigDecimal::integral()` is deprecated; use `getIntegral()` instead +- `BigDecimal::fraction()` is deprecated; use `getFraction()` instead +- `BigRational::numerator()` is deprecated; use `getNumerator()` instead +- `BigRational::denominator()` is deprecated; use `getDenominator()` instead + +The old methods will be removed in version 0.7.0. + +## [0.6.0](https://github.com/brick/math/releases/tag/0.6.0) - 2017-08-25 + +- Minimum PHP version is now [7.1](https://gophp71.org/); for PHP 5.6 and PHP 7.0 support, use version `0.5` +- Deprecated method `BigDecimal::withScale()` has been removed; use `toScale()` instead +- Method `BigNumber::toInteger()` has been renamed to `toInt()` + +## [0.5.4](https://github.com/brick/math/releases/tag/0.5.4) - 2016-10-17 + +`BigNumber` classes now implement [JsonSerializable](http://php.net/manual/en/class.jsonserializable.php). +The JSON output is always a string. + +## [0.5.3](https://github.com/brick/math/releases/tag/0.5.3) - 2016-03-31 + +This is a bugfix release. Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6. + +## [0.5.2](https://github.com/brick/math/releases/tag/0.5.2) - 2015-08-06 + +The `$scale` parameter of `BigDecimal::dividedBy()` is now optional again. + +## [0.5.1](https://github.com/brick/math/releases/tag/0.5.1) - 2015-07-05 + +**New method: `BigNumber::toScale()`** + +This allows to convert any `BigNumber` to a `BigDecimal` with a given scale, using rounding if necessary. + +## [0.5.0](https://github.com/brick/math/releases/tag/0.5.0) - 2015-07-04 + +**New features** +- Common `BigNumber` interface for all classes, with the following methods: + - `sign()` and derived methods (`isZero()`, `isPositive()`, ...) + - `compareTo()` and derived methods (`isEqualTo()`, `isGreaterThan()`, ...) that work across different `BigNumber` types + - `toBigInteger()`, `toBigDecimal()`, `toBigRational`() conversion methods + - `toInteger()` and `toFloat()` conversion methods to native types +- Unified `of()` behaviour: every class now accepts any type of number, provided that it can be safely converted to the current type +- New method: `BigDecimal::exactlyDividedBy()`; this method automatically computes the scale of the result, provided that the division yields a finite number of digits +- New methods: `BigRational::quotient()` and `remainder()` +- Fine-grained exceptions: `DivisionByZeroException`, `RoundingNecessaryException`, `NumberFormatException` +- Factory methods `zero()`, `one()` and `ten()` available in all classes +- Rounding mode reintroduced in `BigInteger::dividedBy()` + +This release also comes with many performance improvements. + +--- + +**Breaking changes** +- `BigInteger`: + - `getSign()` is renamed to `sign()` + - `toString()` is renamed to `toBase()` + - `BigInteger::dividedBy()` now throws an exception by default if the remainder is not zero; use `quotient()` to get the previous behaviour +- `BigDecimal`: + - `getSign()` is renamed to `sign()` + - `getUnscaledValue()` is renamed to `unscaledValue()` + - `getScale()` is renamed to `scale()` + - `getIntegral()` is renamed to `integral()` + - `getFraction()` is renamed to `fraction()` + - `divideAndRemainder()` is renamed to `quotientAndRemainder()` + - `dividedBy()` now takes a **mandatory** `$scale` parameter **before** the rounding mode + - `toBigInteger()` does not accept a `$roundingMode` parameter any more + - `toBigRational()` does not simplify the fraction any more; explicitly add `->simplified()` to get the previous behaviour +- `BigRational`: + - `getSign()` is renamed to `sign()` + - `getNumerator()` is renamed to `numerator()` + - `getDenominator()` is renamed to `denominator()` + - `of()` is renamed to `nd()`, while `parse()` is renamed to `of()` +- Miscellaneous: + - `ArithmeticException` is moved to an `Exception\` sub-namespace + - `of()` factory methods now throw `NumberFormatException` instead of `InvalidArgumentException` + +## [0.4.3](https://github.com/brick/math/releases/tag/0.4.3) - 2016-03-31 + +Backport of two bug fixes from the 0.5 branch: +- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected +- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6. + +## [0.4.2](https://github.com/brick/math/releases/tag/0.4.2) - 2015-06-16 + +New method: `BigDecimal::stripTrailingZeros()` + +## [0.4.1](https://github.com/brick/math/releases/tag/0.4.1) - 2015-06-12 + +Introducing a `BigRational` class, to perform calculations on fractions of any size. + +## [0.4.0](https://github.com/brick/math/releases/tag/0.4.0) - 2015-06-12 + +Rounding modes have been removed from `BigInteger`, and are now a concept specific to `BigDecimal`. + +`BigInteger::dividedBy()` now always returns the quotient of the division. + +## [0.3.5](https://github.com/brick/math/releases/tag/0.3.5) - 2016-03-31 + +Backport of two bug fixes from the 0.5 branch: + +- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected +- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6. + +## [0.3.4](https://github.com/brick/math/releases/tag/0.3.4) - 2015-06-11 + +New methods: +- `BigInteger::remainder()` returns the remainder of a division only +- `BigInteger::gcd()` returns the greatest common divisor of two numbers + +## [0.3.3](https://github.com/brick/math/releases/tag/0.3.3) - 2015-06-07 + +Fix `toString()` not handling negative numbers. + +## [0.3.2](https://github.com/brick/math/releases/tag/0.3.2) - 2015-06-07 + +`BigInteger` and `BigDecimal` now have a `getSign()` method that returns: +- `-1` if the number is negative +- `0` if the number is zero +- `1` if the number is positive + +## [0.3.1](https://github.com/brick/math/releases/tag/0.3.1) - 2015-06-05 + +Minor performance improvements + +## [0.3.0](https://github.com/brick/math/releases/tag/0.3.0) - 2015-06-04 + +The `$roundingMode` and `$scale` parameters have been swapped in `BigDecimal::dividedBy()`. + +## [0.2.2](https://github.com/brick/math/releases/tag/0.2.2) - 2015-06-04 + +Stronger immutability guarantee for `BigInteger` and `BigDecimal`. + +So far, it would have been possible to break immutability of these classes by calling the `unserialize()` internal function. This release fixes that. + +## [0.2.1](https://github.com/brick/math/releases/tag/0.2.1) - 2015-06-02 + +Added `BigDecimal::divideAndRemainder()` + +## [0.2.0](https://github.com/brick/math/releases/tag/0.2.0) - 2015-05-22 + +- `min()` and `max()` do not accept an `array` any more, but a variable number of parameters +- **minimum PHP version is now 5.6** +- continuous integration with PHP 7 + +## [0.1.1](https://github.com/brick/math/releases/tag/0.1.1) - 2014-09-01 + +- Added `BigInteger::power()` +- Added HHVM support + +## [0.1.0](https://github.com/brick/math/releases/tag/0.1.0) - 2014-08-31 + +First beta release. + diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/LICENSE b/wp-content/plugins/wp-webauthn/vendor/brick/math/LICENSE new file mode 100644 index 00000000..f9b724f0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013-present Benjamin Morel + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/SECURITY.md b/wp-content/plugins/wp-webauthn/vendor/brick/math/SECURITY.md new file mode 100644 index 00000000..cc8289bb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +## Supported Versions + +Only the last two release streams are supported. + +| Version | Supported | +| ------- | ------------------ | +| 0.9.x | :white_check_mark: | +| 0.8.x | :white_check_mark: | +| < 0.8 | :x: | + +## Reporting a Vulnerability + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/composer.json b/wp-content/plugins/wp-webauthn/vendor/brick/math/composer.json new file mode 100644 index 00000000..ec196632 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/composer.json @@ -0,0 +1,35 @@ +{ + "name": "brick/math", + "description": "Arbitrary-precision arithmetic library", + "type": "library", + "keywords": [ + "Brick", + "Math", + "Arbitrary-precision", + "Arithmetic", + "BigInteger", + "BigDecimal", + "BigRational", + "Bignum" + ], + "license": "MIT", + "require": { + "php": "^7.1 || ^8.0", + "ext-json": "*" + }, + "require-dev": { + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", + "php-coveralls/php-coveralls": "^2.2", + "vimeo/psalm": "4.9.2" + }, + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Brick\\Math\\Tests\\": "tests/" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigDecimal.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigDecimal.php new file mode 100644 index 00000000..78246500 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigDecimal.php @@ -0,0 +1,895 @@ +value = $value; + $this->scale = $scale; + } + + /** + * Creates a BigDecimal of the given value. + * + * @param BigNumber|int|float|string $value + * + * @return BigDecimal + * + * @throws MathException If the value cannot be converted to a BigDecimal. + * + * @psalm-pure + */ + public static function of($value) : BigNumber + { + return parent::of($value)->toBigDecimal(); + } + + /** + * Creates a BigDecimal from an unscaled value and a scale. + * + * Example: `(12345, 3)` will result in the BigDecimal `12.345`. + * + * @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger. + * @param int $scale The scale of the number, positive or zero. + * + * @return BigDecimal + * + * @throws \InvalidArgumentException If the scale is negative. + * + * @psalm-pure + */ + public static function ofUnscaledValue($value, int $scale = 0) : BigDecimal + { + if ($scale < 0) { + throw new \InvalidArgumentException('The scale cannot be negative.'); + } + + return new BigDecimal((string) BigInteger::of($value), $scale); + } + + /** + * Returns a BigDecimal representing zero, with a scale of zero. + * + * @return BigDecimal + * + * @psalm-pure + */ + public static function zero() : BigDecimal + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigDecimal|null $zero + */ + static $zero; + + if ($zero === null) { + $zero = new BigDecimal('0'); + } + + return $zero; + } + + /** + * Returns a BigDecimal representing one, with a scale of zero. + * + * @return BigDecimal + * + * @psalm-pure + */ + public static function one() : BigDecimal + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigDecimal|null $one + */ + static $one; + + if ($one === null) { + $one = new BigDecimal('1'); + } + + return $one; + } + + /** + * Returns a BigDecimal representing ten, with a scale of zero. + * + * @return BigDecimal + * + * @psalm-pure + */ + public static function ten() : BigDecimal + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigDecimal|null $ten + */ + static $ten; + + if ($ten === null) { + $ten = new BigDecimal('10'); + } + + return $ten; + } + + /** + * Returns the sum of this number and the given one. + * + * The result has a scale of `max($this->scale, $that->scale)`. + * + * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal. + * + * @return BigDecimal The result. + * + * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. + */ + public function plus($that) : BigDecimal + { + $that = BigDecimal::of($that); + + if ($that->value === '0' && $that->scale <= $this->scale) { + return $this; + } + + if ($this->value === '0' && $this->scale <= $that->scale) { + return $that; + } + + [$a, $b] = $this->scaleValues($this, $that); + + $value = Calculator::get()->add($a, $b); + $scale = $this->scale > $that->scale ? $this->scale : $that->scale; + + return new BigDecimal($value, $scale); + } + + /** + * Returns the difference of this number and the given one. + * + * The result has a scale of `max($this->scale, $that->scale)`. + * + * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal. + * + * @return BigDecimal The result. + * + * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. + */ + public function minus($that) : BigDecimal + { + $that = BigDecimal::of($that); + + if ($that->value === '0' && $that->scale <= $this->scale) { + return $this; + } + + [$a, $b] = $this->scaleValues($this, $that); + + $value = Calculator::get()->sub($a, $b); + $scale = $this->scale > $that->scale ? $this->scale : $that->scale; + + return new BigDecimal($value, $scale); + } + + /** + * Returns the product of this number and the given one. + * + * The result has a scale of `$this->scale + $that->scale`. + * + * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal. + * + * @return BigDecimal The result. + * + * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal. + */ + public function multipliedBy($that) : BigDecimal + { + $that = BigDecimal::of($that); + + if ($that->value === '1' && $that->scale === 0) { + return $this; + } + + if ($this->value === '1' && $this->scale === 0) { + return $that; + } + + $value = Calculator::get()->mul($this->value, $that->value); + $scale = $this->scale + $that->scale; + + return new BigDecimal($value, $scale); + } + + /** + * Returns the result of the division of this number by the given one, at the given scale. + * + * @param BigNumber|int|float|string $that The divisor. + * @param int|null $scale The desired scale, or null to use the scale of this number. + * @param int $roundingMode An optional rounding mode. + * + * @return BigDecimal + * + * @throws \InvalidArgumentException If the scale or rounding mode is invalid. + * @throws MathException If the number is invalid, is zero, or rounding was necessary. + */ + public function dividedBy($that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + { + $that = BigDecimal::of($that); + + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); + } + + if ($scale === null) { + $scale = $this->scale; + } elseif ($scale < 0) { + throw new \InvalidArgumentException('Scale cannot be negative.'); + } + + if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) { + return $this; + } + + $p = $this->valueWithMinScale($that->scale + $scale); + $q = $that->valueWithMinScale($this->scale - $scale); + + $result = Calculator::get()->divRound($p, $q, $roundingMode); + + return new BigDecimal($result, $scale); + } + + /** + * Returns the exact result of the division of this number by the given one. + * + * The scale of the result is automatically calculated to fit all the fraction digits. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. + * + * @return BigDecimal The result. + * + * @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero, + * or the result yields an infinite number of digits. + */ + public function exactlyDividedBy($that) : BigDecimal + { + $that = BigDecimal::of($that); + + if ($that->value === '0') { + throw DivisionByZeroException::divisionByZero(); + } + + [, $b] = $this->scaleValues($this, $that); + + $d = \rtrim($b, '0'); + $scale = \strlen($b) - \strlen($d); + + $calculator = Calculator::get(); + + foreach ([5, 2] as $prime) { + for (;;) { + $lastDigit = (int) $d[-1]; + + if ($lastDigit % $prime !== 0) { + break; + } + + $d = $calculator->divQ($d, (string) $prime); + $scale++; + } + } + + return $this->dividedBy($that, $scale)->stripTrailingZeros(); + } + + /** + * Returns this number exponentiated to the given value. + * + * The result has a scale of `$this->scale * $exponent`. + * + * @param int $exponent The exponent. + * + * @return BigDecimal The result. + * + * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. + */ + public function power(int $exponent) : BigDecimal + { + if ($exponent === 0) { + return BigDecimal::one(); + } + + if ($exponent === 1) { + return $this; + } + + if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { + throw new \InvalidArgumentException(\sprintf( + 'The exponent %d is not in the range 0 to %d.', + $exponent, + Calculator::MAX_POWER + )); + } + + return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent); + } + + /** + * Returns the quotient of the division of this number by this given one. + * + * The quotient has a scale of `0`. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. + * + * @return BigDecimal The quotient. + * + * @throws MathException If the divisor is not a valid decimal number, or is zero. + */ + public function quotient($that) : BigDecimal + { + $that = BigDecimal::of($that); + + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); + } + + $p = $this->valueWithMinScale($that->scale); + $q = $that->valueWithMinScale($this->scale); + + $quotient = Calculator::get()->divQ($p, $q); + + return new BigDecimal($quotient, 0); + } + + /** + * Returns the remainder of the division of this number by this given one. + * + * The remainder has a scale of `max($this->scale, $that->scale)`. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. + * + * @return BigDecimal The remainder. + * + * @throws MathException If the divisor is not a valid decimal number, or is zero. + */ + public function remainder($that) : BigDecimal + { + $that = BigDecimal::of($that); + + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); + } + + $p = $this->valueWithMinScale($that->scale); + $q = $that->valueWithMinScale($this->scale); + + $remainder = Calculator::get()->divR($p, $q); + + $scale = $this->scale > $that->scale ? $this->scale : $that->scale; + + return new BigDecimal($remainder, $scale); + } + + /** + * Returns the quotient and remainder of the division of this number by the given one. + * + * The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. + * + * @return BigDecimal[] An array containing the quotient and the remainder. + * + * @throws MathException If the divisor is not a valid decimal number, or is zero. + */ + public function quotientAndRemainder($that) : array + { + $that = BigDecimal::of($that); + + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); + } + + $p = $this->valueWithMinScale($that->scale); + $q = $that->valueWithMinScale($this->scale); + + [$quotient, $remainder] = Calculator::get()->divQR($p, $q); + + $scale = $this->scale > $that->scale ? $this->scale : $that->scale; + + $quotient = new BigDecimal($quotient, 0); + $remainder = new BigDecimal($remainder, $scale); + + return [$quotient, $remainder]; + } + + /** + * Returns the square root of this number, rounded down to the given number of decimals. + * + * @param int $scale + * + * @return BigDecimal + * + * @throws \InvalidArgumentException If the scale is negative. + * @throws NegativeNumberException If this number is negative. + */ + public function sqrt(int $scale) : BigDecimal + { + if ($scale < 0) { + throw new \InvalidArgumentException('Scale cannot be negative.'); + } + + if ($this->value === '0') { + return new BigDecimal('0', $scale); + } + + if ($this->value[0] === '-') { + throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); + } + + $value = $this->value; + $addDigits = 2 * $scale - $this->scale; + + if ($addDigits > 0) { + // add zeros + $value .= \str_repeat('0', $addDigits); + } elseif ($addDigits < 0) { + // trim digits + if (-$addDigits >= \strlen($this->value)) { + // requesting a scale too low, will always yield a zero result + return new BigDecimal('0', $scale); + } + + $value = \substr($value, 0, $addDigits); + } + + $value = Calculator::get()->sqrt($value); + + return new BigDecimal($value, $scale); + } + + /** + * Returns a copy of this BigDecimal with the decimal point moved $n places to the left. + * + * @param int $n + * + * @return BigDecimal + */ + public function withPointMovedLeft(int $n) : BigDecimal + { + if ($n === 0) { + return $this; + } + + if ($n < 0) { + return $this->withPointMovedRight(-$n); + } + + return new BigDecimal($this->value, $this->scale + $n); + } + + /** + * Returns a copy of this BigDecimal with the decimal point moved $n places to the right. + * + * @param int $n + * + * @return BigDecimal + */ + public function withPointMovedRight(int $n) : BigDecimal + { + if ($n === 0) { + return $this; + } + + if ($n < 0) { + return $this->withPointMovedLeft(-$n); + } + + $value = $this->value; + $scale = $this->scale - $n; + + if ($scale < 0) { + if ($value !== '0') { + $value .= \str_repeat('0', -$scale); + } + $scale = 0; + } + + return new BigDecimal($value, $scale); + } + + /** + * Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part. + * + * @return BigDecimal + */ + public function stripTrailingZeros() : BigDecimal + { + if ($this->scale === 0) { + return $this; + } + + $trimmedValue = \rtrim($this->value, '0'); + + if ($trimmedValue === '') { + return BigDecimal::zero(); + } + + $trimmableZeros = \strlen($this->value) - \strlen($trimmedValue); + + if ($trimmableZeros === 0) { + return $this; + } + + if ($trimmableZeros > $this->scale) { + $trimmableZeros = $this->scale; + } + + $value = \substr($this->value, 0, -$trimmableZeros); + $scale = $this->scale - $trimmableZeros; + + return new BigDecimal($value, $scale); + } + + /** + * Returns the absolute value of this number. + * + * @return BigDecimal + */ + public function abs() : BigDecimal + { + return $this->isNegative() ? $this->negated() : $this; + } + + /** + * Returns the negated value of this number. + * + * @return BigDecimal + */ + public function negated() : BigDecimal + { + return new BigDecimal(Calculator::get()->neg($this->value), $this->scale); + } + + /** + * {@inheritdoc} + */ + public function compareTo($that) : int + { + $that = BigNumber::of($that); + + if ($that instanceof BigInteger) { + $that = $that->toBigDecimal(); + } + + if ($that instanceof BigDecimal) { + [$a, $b] = $this->scaleValues($this, $that); + + return Calculator::get()->cmp($a, $b); + } + + return - $that->compareTo($this); + } + + /** + * {@inheritdoc} + */ + public function getSign() : int + { + return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); + } + + /** + * @return BigInteger + */ + public function getUnscaledValue() : BigInteger + { + return BigInteger::create($this->value); + } + + /** + * @return int + */ + public function getScale() : int + { + return $this->scale; + } + + /** + * Returns a string representing the integral part of this decimal number. + * + * Example: `-123.456` => `-123`. + * + * @return string + */ + public function getIntegralPart() : string + { + if ($this->scale === 0) { + return $this->value; + } + + $value = $this->getUnscaledValueWithLeadingZeros(); + + return \substr($value, 0, -$this->scale); + } + + /** + * Returns a string representing the fractional part of this decimal number. + * + * If the scale is zero, an empty string is returned. + * + * Examples: `-123.456` => '456', `123` => ''. + * + * @return string + */ + public function getFractionalPart() : string + { + if ($this->scale === 0) { + return ''; + } + + $value = $this->getUnscaledValueWithLeadingZeros(); + + return \substr($value, -$this->scale); + } + + /** + * Returns whether this decimal number has a non-zero fractional part. + * + * @return bool + */ + public function hasNonZeroFractionalPart() : bool + { + return $this->getFractionalPart() !== \str_repeat('0', $this->scale); + } + + /** + * {@inheritdoc} + */ + public function toBigInteger() : BigInteger + { + $zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0); + + return BigInteger::create($zeroScaleDecimal->value); + } + + /** + * {@inheritdoc} + */ + public function toBigDecimal() : BigDecimal + { + return $this; + } + + /** + * {@inheritdoc} + */ + public function toBigRational() : BigRational + { + $numerator = BigInteger::create($this->value); + $denominator = BigInteger::create('1' . \str_repeat('0', $this->scale)); + + return BigRational::create($numerator, $denominator, false); + } + + /** + * {@inheritdoc} + */ + public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + { + if ($scale === $this->scale) { + return $this; + } + + return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode); + } + + /** + * {@inheritdoc} + */ + public function toInt() : int + { + return $this->toBigInteger()->toInt(); + } + + /** + * {@inheritdoc} + */ + public function toFloat() : float + { + return (float) (string) $this; + } + + /** + * {@inheritdoc} + */ + public function __toString() : string + { + if ($this->scale === 0) { + return $this->value; + } + + $value = $this->getUnscaledValueWithLeadingZeros(); + + return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale); + } + + /** + * This method is required for serializing the object and SHOULD NOT be accessed directly. + * + * @internal + * + * @return array{value: string, scale: int} + */ + public function __serialize(): array + { + return ['value' => $this->value, 'scale' => $this->scale]; + } + + /** + * This method is only here to allow unserializing the object and cannot be accessed directly. + * + * @internal + * @psalm-suppress RedundantPropertyInitializationCheck + * + * @param array{value: string, scale: int} $data + * + * @return void + * + * @throws \LogicException + */ + public function __unserialize(array $data): void + { + if (isset($this->value)) { + throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); + } + + $this->value = $data['value']; + $this->scale = $data['scale']; + } + + /** + * This method is required by interface Serializable and SHOULD NOT be accessed directly. + * + * @internal + * + * @return string + */ + public function serialize() : string + { + return $this->value . ':' . $this->scale; + } + + /** + * This method is only here to implement interface Serializable and cannot be accessed directly. + * + * @internal + * @psalm-suppress RedundantPropertyInitializationCheck + * + * @param string $value + * + * @return void + * + * @throws \LogicException + */ + public function unserialize($value) : void + { + if (isset($this->value)) { + throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); + } + + [$value, $scale] = \explode(':', $value); + + $this->value = $value; + $this->scale = (int) $scale; + } + + /** + * Puts the internal values of the given decimal numbers on the same scale. + * + * @param BigDecimal $x The first decimal number. + * @param BigDecimal $y The second decimal number. + * + * @return array{string, string} The scaled integer values of $x and $y. + */ + private function scaleValues(BigDecimal $x, BigDecimal $y) : array + { + $a = $x->value; + $b = $y->value; + + if ($b !== '0' && $x->scale > $y->scale) { + $b .= \str_repeat('0', $x->scale - $y->scale); + } elseif ($a !== '0' && $x->scale < $y->scale) { + $a .= \str_repeat('0', $y->scale - $x->scale); + } + + return [$a, $b]; + } + + /** + * @param int $scale + * + * @return string + */ + private function valueWithMinScale(int $scale) : string + { + $value = $this->value; + + if ($this->value !== '0' && $scale > $this->scale) { + $value .= \str_repeat('0', $scale - $this->scale); + } + + return $value; + } + + /** + * Adds leading zeros if necessary to the unscaled value to represent the full decimal number. + * + * @return string + */ + private function getUnscaledValueWithLeadingZeros() : string + { + $value = $this->value; + $targetLength = $this->scale + 1; + $negative = ($value[0] === '-'); + $length = \strlen($value); + + if ($negative) { + $length--; + } + + if ($length >= $targetLength) { + return $this->value; + } + + if ($negative) { + $value = \substr($value, 1); + } + + $value = \str_pad($value, $targetLength, '0', STR_PAD_LEFT); + + if ($negative) { + $value = '-' . $value; + } + + return $value; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigInteger.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigInteger.php new file mode 100644 index 00000000..f213fbed --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigInteger.php @@ -0,0 +1,1184 @@ +value = $value; + } + + /** + * Creates a BigInteger of the given value. + * + * @param BigNumber|int|float|string $value + * + * @return BigInteger + * + * @throws MathException If the value cannot be converted to a BigInteger. + * + * @psalm-pure + */ + public static function of($value) : BigNumber + { + return parent::of($value)->toBigInteger(); + } + + /** + * Creates a number from a string in a given base. + * + * The string can optionally be prefixed with the `+` or `-` sign. + * + * Bases greater than 36 are not supported by this method, as there is no clear consensus on which of the lowercase + * or uppercase characters should come first. Instead, this method accepts any base up to 36, and does not + * differentiate lowercase and uppercase characters, which are considered equal. + * + * For bases greater than 36, and/or custom alphabets, use the fromArbitraryBase() method. + * + * @param string $number The number to convert, in the given base. + * @param int $base The base of the number, between 2 and 36. + * + * @return BigInteger + * + * @throws NumberFormatException If the number is empty, or contains invalid chars for the given base. + * @throws \InvalidArgumentException If the base is out of range. + * + * @psalm-pure + */ + public static function fromBase(string $number, int $base) : BigInteger + { + if ($number === '') { + throw new NumberFormatException('The number cannot be empty.'); + } + + if ($base < 2 || $base > 36) { + throw new \InvalidArgumentException(\sprintf('Base %d is not in range 2 to 36.', $base)); + } + + if ($number[0] === '-') { + $sign = '-'; + $number = \substr($number, 1); + } elseif ($number[0] === '+') { + $sign = ''; + $number = \substr($number, 1); + } else { + $sign = ''; + } + + if ($number === '') { + throw new NumberFormatException('The number cannot be empty.'); + } + + $number = \ltrim($number, '0'); + + if ($number === '') { + // The result will be the same in any base, avoid further calculation. + return BigInteger::zero(); + } + + if ($number === '1') { + // The result will be the same in any base, avoid further calculation. + return new BigInteger($sign . '1'); + } + + $pattern = '/[^' . \substr(Calculator::ALPHABET, 0, $base) . ']/'; + + if (\preg_match($pattern, \strtolower($number), $matches) === 1) { + throw new NumberFormatException(\sprintf('"%s" is not a valid character in base %d.', $matches[0], $base)); + } + + if ($base === 10) { + // The number is usable as is, avoid further calculation. + return new BigInteger($sign . $number); + } + + $result = Calculator::get()->fromBase($number, $base); + + return new BigInteger($sign . $result); + } + + /** + * Parses a string containing an integer in an arbitrary base, using a custom alphabet. + * + * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers. + * + * @param string $number The number to parse. + * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. + * + * @return BigInteger + * + * @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet. + * @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars. + * + * @psalm-pure + */ + public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger + { + if ($number === '') { + throw new NumberFormatException('The number cannot be empty.'); + } + + $base = \strlen($alphabet); + + if ($base < 2) { + throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); + } + + $pattern = '/[^' . \preg_quote($alphabet, '/') . ']/'; + + if (\preg_match($pattern, $number, $matches) === 1) { + throw NumberFormatException::charNotInAlphabet($matches[0]); + } + + $number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base); + + return new BigInteger($number); + } + + /** + * Translates a string of bytes containing the binary representation of a BigInteger into a BigInteger. + * + * The input string is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element. + * + * If `$signed` is true, the input is assumed to be in two's-complement representation, and the leading bit is + * interpreted as a sign bit. If `$signed` is false, the input is interpreted as an unsigned number, and the + * resulting BigInteger will always be positive or zero. + * + * This method can be used to retrieve a number exported by `toBytes()`, as long as the `$signed` flags match. + * + * @param string $value The byte string. + * @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading + * sign bit. + * + * @return BigInteger + * + * @throws NumberFormatException If the string is empty. + */ + public static function fromBytes(string $value, bool $signed = true) : BigInteger + { + if ($value === '') { + throw new NumberFormatException('The byte string must not be empty.'); + } + + $twosComplement = false; + + if ($signed) { + $x = \ord($value[0]); + + if (($twosComplement = ($x >= 0x80))) { + $value = ~$value; + } + } + + $number = self::fromBase(\bin2hex($value), 16); + + if ($twosComplement) { + return $number->plus(1)->negated(); + } + + return $number; + } + + /** + * Generates a pseudo-random number in the range 0 to 2^numBits - 1. + * + * Using the default random bytes generator, this method is suitable for cryptographic use. + * + * @psalm-param callable(int): string $randomBytesGenerator + * + * @param int $numBits The number of bits. + * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, and returns a + * string of random bytes of the given length. Defaults to the + * `random_bytes()` function. + * + * @return BigInteger + * + * @throws \InvalidArgumentException If $numBits is negative. + */ + public static function randomBits(int $numBits, ?callable $randomBytesGenerator = null) : BigInteger + { + if ($numBits < 0) { + throw new \InvalidArgumentException('The number of bits cannot be negative.'); + } + + if ($numBits === 0) { + return BigInteger::zero(); + } + + if ($randomBytesGenerator === null) { + $randomBytesGenerator = 'random_bytes'; + } + + $byteLength = \intdiv($numBits - 1, 8) + 1; + + $extraBits = ($byteLength * 8 - $numBits); + $bitmask = \chr(0xFF >> $extraBits); + + $randomBytes = $randomBytesGenerator($byteLength); + $randomBytes[0] = $randomBytes[0] & $bitmask; + + return self::fromBytes($randomBytes, false); + } + + /** + * Generates a pseudo-random number between `$min` and `$max`. + * + * Using the default random bytes generator, this method is suitable for cryptographic use. + * + * @psalm-param (callable(int): string)|null $randomBytesGenerator + * + * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger. + * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger. + * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, + * and returns a string of random bytes of the given length. + * Defaults to the `random_bytes()` function. + * + * @return BigInteger + * + * @throws MathException If one of the parameters cannot be converted to a BigInteger, + * or `$min` is greater than `$max`. + */ + public static function randomRange($min, $max, ?callable $randomBytesGenerator = null) : BigInteger + { + $min = BigInteger::of($min); + $max = BigInteger::of($max); + + if ($min->isGreaterThan($max)) { + throw new MathException('$min cannot be greater than $max.'); + } + + if ($min->isEqualTo($max)) { + return $min; + } + + $diff = $max->minus($min); + $bitLength = $diff->getBitLength(); + + // try until the number is in range (50% to 100% chance of success) + do { + $randomNumber = self::randomBits($bitLength, $randomBytesGenerator); + } while ($randomNumber->isGreaterThan($diff)); + + return $randomNumber->plus($min); + } + + /** + * Returns a BigInteger representing zero. + * + * @return BigInteger + * + * @psalm-pure + */ + public static function zero() : BigInteger + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigInteger|null $zero + */ + static $zero; + + if ($zero === null) { + $zero = new BigInteger('0'); + } + + return $zero; + } + + /** + * Returns a BigInteger representing one. + * + * @return BigInteger + * + * @psalm-pure + */ + public static function one() : BigInteger + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigInteger|null $one + */ + static $one; + + if ($one === null) { + $one = new BigInteger('1'); + } + + return $one; + } + + /** + * Returns a BigInteger representing ten. + * + * @return BigInteger + * + * @psalm-pure + */ + public static function ten() : BigInteger + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigInteger|null $ten + */ + static $ten; + + if ($ten === null) { + $ten = new BigInteger('10'); + } + + return $ten; + } + + /** + * Returns the sum of this number and the given one. + * + * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger. + * + * @return BigInteger The result. + * + * @throws MathException If the number is not valid, or is not convertible to a BigInteger. + */ + public function plus($that) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '0') { + return $this; + } + + if ($this->value === '0') { + return $that; + } + + $value = Calculator::get()->add($this->value, $that->value); + + return new BigInteger($value); + } + + /** + * Returns the difference of this number and the given one. + * + * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger. + * + * @return BigInteger The result. + * + * @throws MathException If the number is not valid, or is not convertible to a BigInteger. + */ + public function minus($that) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '0') { + return $this; + } + + $value = Calculator::get()->sub($this->value, $that->value); + + return new BigInteger($value); + } + + /** + * Returns the product of this number and the given one. + * + * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger. + * + * @return BigInteger The result. + * + * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger. + */ + public function multipliedBy($that) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '1') { + return $this; + } + + if ($this->value === '1') { + return $that; + } + + $value = Calculator::get()->mul($this->value, $that->value); + + return new BigInteger($value); + } + + /** + * Returns the result of the division of this number by the given one. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * @param int $roundingMode An optional rounding mode. + * + * @return BigInteger The result. + * + * @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero, + * or RoundingMode::UNNECESSARY is used and the remainder is not zero. + */ + public function dividedBy($that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '1') { + return $this; + } + + if ($that->value === '0') { + throw DivisionByZeroException::divisionByZero(); + } + + $result = Calculator::get()->divRound($this->value, $that->value, $roundingMode); + + return new BigInteger($result); + } + + /** + * Returns this number exponentiated to the given value. + * + * @param int $exponent The exponent. + * + * @return BigInteger The result. + * + * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. + */ + public function power(int $exponent) : BigInteger + { + if ($exponent === 0) { + return BigInteger::one(); + } + + if ($exponent === 1) { + return $this; + } + + if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { + throw new \InvalidArgumentException(\sprintf( + 'The exponent %d is not in the range 0 to %d.', + $exponent, + Calculator::MAX_POWER + )); + } + + return new BigInteger(Calculator::get()->pow($this->value, $exponent)); + } + + /** + * Returns the quotient of the division of this number by the given one. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * + * @return BigInteger + * + * @throws DivisionByZeroException If the divisor is zero. + */ + public function quotient($that) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '1') { + return $this; + } + + if ($that->value === '0') { + throw DivisionByZeroException::divisionByZero(); + } + + $quotient = Calculator::get()->divQ($this->value, $that->value); + + return new BigInteger($quotient); + } + + /** + * Returns the remainder of the division of this number by the given one. + * + * The remainder, when non-zero, has the same sign as the dividend. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * + * @return BigInteger + * + * @throws DivisionByZeroException If the divisor is zero. + */ + public function remainder($that) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '1') { + return BigInteger::zero(); + } + + if ($that->value === '0') { + throw DivisionByZeroException::divisionByZero(); + } + + $remainder = Calculator::get()->divR($this->value, $that->value); + + return new BigInteger($remainder); + } + + /** + * Returns the quotient and remainder of the division of this number by the given one. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * + * @return BigInteger[] An array containing the quotient and the remainder. + * + * @throws DivisionByZeroException If the divisor is zero. + */ + public function quotientAndRemainder($that) : array + { + $that = BigInteger::of($that); + + if ($that->value === '0') { + throw DivisionByZeroException::divisionByZero(); + } + + [$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value); + + return [ + new BigInteger($quotient), + new BigInteger($remainder) + ]; + } + + /** + * Returns the modulo of this number and the given one. + * + * The modulo operation yields the same result as the remainder operation when both operands are of the same sign, + * and may differ when signs are different. + * + * The result of the modulo operation, when non-zero, has the same sign as the divisor. + * + * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * + * @return BigInteger + * + * @throws DivisionByZeroException If the divisor is zero. + */ + public function mod($that) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '0') { + throw DivisionByZeroException::modulusMustNotBeZero(); + } + + $value = Calculator::get()->mod($this->value, $that->value); + + return new BigInteger($value); + } + + /** + * Returns the modular multiplicative inverse of this BigInteger modulo $m. + * + * @param BigInteger $m + * + * @return BigInteger + * + * @throws DivisionByZeroException If $m is zero. + * @throws NegativeNumberException If $m is negative. + * @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger + * is not relatively prime to m). + */ + public function modInverse(BigInteger $m) : BigInteger + { + if ($m->value === '0') { + throw DivisionByZeroException::modulusMustNotBeZero(); + } + + if ($m->isNegative()) { + throw new NegativeNumberException('Modulus must not be negative.'); + } + + if ($m->value === '1') { + return BigInteger::zero(); + } + + $value = Calculator::get()->modInverse($this->value, $m->value); + + if ($value === null) { + throw new MathException('Unable to compute the modInverse for the given modulus.'); + } + + return new BigInteger($value); + } + + /** + * Returns this number raised into power with modulo. + * + * This operation only works on positive numbers. + * + * @param BigNumber|int|float|string $exp The exponent. Must be positive or zero. + * @param BigNumber|int|float|string $mod The modulus. Must be strictly positive. + * + * @return BigInteger + * + * @throws NegativeNumberException If any of the operands is negative. + * @throws DivisionByZeroException If the modulus is zero. + */ + public function modPow($exp, $mod) : BigInteger + { + $exp = BigInteger::of($exp); + $mod = BigInteger::of($mod); + + if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) { + throw new NegativeNumberException('The operands cannot be negative.'); + } + + if ($mod->isZero()) { + throw DivisionByZeroException::modulusMustNotBeZero(); + } + + $result = Calculator::get()->modPow($this->value, $exp->value, $mod->value); + + return new BigInteger($result); + } + + /** + * Returns the greatest common divisor of this number and the given one. + * + * The GCD is always positive, unless both operands are zero, in which case it is zero. + * + * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * + * @return BigInteger + */ + public function gcd($that) : BigInteger + { + $that = BigInteger::of($that); + + if ($that->value === '0' && $this->value[0] !== '-') { + return $this; + } + + if ($this->value === '0' && $that->value[0] !== '-') { + return $that; + } + + $value = Calculator::get()->gcd($this->value, $that->value); + + return new BigInteger($value); + } + + /** + * Returns the integer square root number of this number, rounded down. + * + * The result is the largest x such that x² ≤ n. + * + * @return BigInteger + * + * @throws NegativeNumberException If this number is negative. + */ + public function sqrt() : BigInteger + { + if ($this->value[0] === '-') { + throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); + } + + $value = Calculator::get()->sqrt($this->value); + + return new BigInteger($value); + } + + /** + * Returns the absolute value of this number. + * + * @return BigInteger + */ + public function abs() : BigInteger + { + return $this->isNegative() ? $this->negated() : $this; + } + + /** + * Returns the inverse of this number. + * + * @return BigInteger + */ + public function negated() : BigInteger + { + return new BigInteger(Calculator::get()->neg($this->value)); + } + + /** + * Returns the integer bitwise-and combined with another integer. + * + * This method returns a negative BigInteger if and only if both operands are negative. + * + * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * + * @return BigInteger + */ + public function and($that) : BigInteger + { + $that = BigInteger::of($that); + + return new BigInteger(Calculator::get()->and($this->value, $that->value)); + } + + /** + * Returns the integer bitwise-or combined with another integer. + * + * This method returns a negative BigInteger if and only if either of the operands is negative. + * + * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * + * @return BigInteger + */ + public function or($that) : BigInteger + { + $that = BigInteger::of($that); + + return new BigInteger(Calculator::get()->or($this->value, $that->value)); + } + + /** + * Returns the integer bitwise-xor combined with another integer. + * + * This method returns a negative BigInteger if and only if exactly one of the operands is negative. + * + * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * + * @return BigInteger + */ + public function xor($that) : BigInteger + { + $that = BigInteger::of($that); + + return new BigInteger(Calculator::get()->xor($this->value, $that->value)); + } + + /** + * Returns the bitwise-not of this BigInteger. + * + * @return BigInteger + */ + public function not() : BigInteger + { + return $this->negated()->minus(1); + } + + /** + * Returns the integer left shifted by a given number of bits. + * + * @param int $distance The distance to shift. + * + * @return BigInteger + */ + public function shiftedLeft(int $distance) : BigInteger + { + if ($distance === 0) { + return $this; + } + + if ($distance < 0) { + return $this->shiftedRight(- $distance); + } + + return $this->multipliedBy(BigInteger::of(2)->power($distance)); + } + + /** + * Returns the integer right shifted by a given number of bits. + * + * @param int $distance The distance to shift. + * + * @return BigInteger + */ + public function shiftedRight(int $distance) : BigInteger + { + if ($distance === 0) { + return $this; + } + + if ($distance < 0) { + return $this->shiftedLeft(- $distance); + } + + $operand = BigInteger::of(2)->power($distance); + + if ($this->isPositiveOrZero()) { + return $this->quotient($operand); + } + + return $this->dividedBy($operand, RoundingMode::UP); + } + + /** + * Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit. + * + * For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation. + * Computes (ceil(log2(this < 0 ? -this : this+1))). + * + * @return int + */ + public function getBitLength() : int + { + if ($this->value === '0') { + return 0; + } + + if ($this->isNegative()) { + return $this->abs()->minus(1)->getBitLength(); + } + + return \strlen($this->toBase(2)); + } + + /** + * Returns the index of the rightmost (lowest-order) one bit in this BigInteger. + * + * Returns -1 if this BigInteger contains no one bits. + * + * @return int + */ + public function getLowestSetBit() : int + { + $n = $this; + $bitLength = $this->getBitLength(); + + for ($i = 0; $i <= $bitLength; $i++) { + if ($n->isOdd()) { + return $i; + } + + $n = $n->shiftedRight(1); + } + + return -1; + } + + /** + * Returns whether this number is even. + * + * @return bool + */ + public function isEven() : bool + { + return \in_array($this->value[-1], ['0', '2', '4', '6', '8'], true); + } + + /** + * Returns whether this number is odd. + * + * @return bool + */ + public function isOdd() : bool + { + return \in_array($this->value[-1], ['1', '3', '5', '7', '9'], true); + } + + /** + * Returns true if and only if the designated bit is set. + * + * Computes ((this & (1<shiftedRight($n)->isOdd(); + } + + /** + * {@inheritdoc} + */ + public function compareTo($that) : int + { + $that = BigNumber::of($that); + + if ($that instanceof BigInteger) { + return Calculator::get()->cmp($this->value, $that->value); + } + + return - $that->compareTo($this); + } + + /** + * {@inheritdoc} + */ + public function getSign() : int + { + return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); + } + + /** + * {@inheritdoc} + */ + public function toBigInteger() : BigInteger + { + return $this; + } + + /** + * {@inheritdoc} + */ + public function toBigDecimal() : BigDecimal + { + return BigDecimal::create($this->value); + } + + /** + * {@inheritdoc} + */ + public function toBigRational() : BigRational + { + return BigRational::create($this, BigInteger::one(), false); + } + + /** + * {@inheritdoc} + */ + public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + { + return $this->toBigDecimal()->toScale($scale, $roundingMode); + } + + /** + * {@inheritdoc} + */ + public function toInt() : int + { + $intValue = (int) $this->value; + + if ($this->value !== (string) $intValue) { + throw IntegerOverflowException::toIntOverflow($this); + } + + return $intValue; + } + + /** + * {@inheritdoc} + */ + public function toFloat() : float + { + return (float) $this->value; + } + + /** + * Returns a string representation of this number in the given base. + * + * The output will always be lowercase for bases greater than 10. + * + * @param int $base + * + * @return string + * + * @throws \InvalidArgumentException If the base is out of range. + */ + public function toBase(int $base) : string + { + if ($base === 10) { + return $this->value; + } + + if ($base < 2 || $base > 36) { + throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base)); + } + + return Calculator::get()->toBase($this->value, $base); + } + + /** + * Returns a string representation of this number in an arbitrary base with a custom alphabet. + * + * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers; + * a NegativeNumberException will be thrown when attempting to call this method on a negative number. + * + * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. + * + * @return string + * + * @throws NegativeNumberException If this number is negative. + * @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars. + */ + public function toArbitraryBase(string $alphabet) : string + { + $base = \strlen($alphabet); + + if ($base < 2) { + throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); + } + + if ($this->value[0] === '-') { + throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.'); + } + + return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base); + } + + /** + * Returns a string of bytes containing the binary representation of this BigInteger. + * + * The string is in big-endian byte-order: the most significant byte is in the zeroth element. + * + * If `$signed` is true, the output will be in two's-complement representation, and a sign bit will be prepended to + * the output. If `$signed` is false, no sign bit will be prepended, and this method will throw an exception if the + * number is negative. + * + * The string will contain the minimum number of bytes required to represent this BigInteger, including a sign bit + * if `$signed` is true. + * + * This representation is compatible with the `fromBytes()` factory method, as long as the `$signed` flags match. + * + * @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit. + * + * @return string + * + * @throws NegativeNumberException If $signed is false, and the number is negative. + */ + public function toBytes(bool $signed = true) : string + { + if (! $signed && $this->isNegative()) { + throw new NegativeNumberException('Cannot convert a negative number to a byte string when $signed is false.'); + } + + $hex = $this->abs()->toBase(16); + + if (\strlen($hex) % 2 !== 0) { + $hex = '0' . $hex; + } + + $baseHexLength = \strlen($hex); + + if ($signed) { + if ($this->isNegative()) { + $bin = \hex2bin($hex); + assert($bin !== false); + + $hex = \bin2hex(~$bin); + $hex = self::fromBase($hex, 16)->plus(1)->toBase(16); + + $hexLength = \strlen($hex); + + if ($hexLength < $baseHexLength) { + $hex = \str_repeat('0', $baseHexLength - $hexLength) . $hex; + } + + if ($hex[0] < '8') { + $hex = 'FF' . $hex; + } + } else { + if ($hex[0] >= '8') { + $hex = '00' . $hex; + } + } + } + + return \hex2bin($hex); + } + + /** + * {@inheritdoc} + */ + public function __toString() : string + { + return $this->value; + } + + /** + * This method is required for serializing the object and SHOULD NOT be accessed directly. + * + * @internal + * + * @return array{value: string} + */ + public function __serialize(): array + { + return ['value' => $this->value]; + } + + /** + * This method is only here to allow unserializing the object and cannot be accessed directly. + * + * @internal + * @psalm-suppress RedundantPropertyInitializationCheck + * + * @param array{value: string} $data + * + * @return void + * + * @throws \LogicException + */ + public function __unserialize(array $data): void + { + if (isset($this->value)) { + throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); + } + + $this->value = $data['value']; + } + + /** + * This method is required by interface Serializable and SHOULD NOT be accessed directly. + * + * @internal + * + * @return string + */ + public function serialize() : string + { + return $this->value; + } + + /** + * This method is only here to implement interface Serializable and cannot be accessed directly. + * + * @internal + * @psalm-suppress RedundantPropertyInitializationCheck + * + * @param string $value + * + * @return void + * + * @throws \LogicException + */ + public function unserialize($value) : void + { + if (isset($this->value)) { + throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); + } + + $this->value = $value; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigNumber.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigNumber.php new file mode 100644 index 00000000..38c8c554 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigNumber.php @@ -0,0 +1,572 @@ +[\-\+])?' . + '(?:' . + '(?:' . + '(?[0-9]+)?' . + '(?\.)?' . + '(?[0-9]+)?' . + '(?:[eE](?[\-\+]?[0-9]+))?' . + ')|(?:' . + '(?[0-9]+)' . + '\/?' . + '(?[0-9]+)' . + ')' . + ')' . + '$/'; + + /** + * Creates a BigNumber of the given value. + * + * The concrete return type is dependent on the given value, with the following rules: + * + * - BigNumber instances are returned as is + * - integer numbers are returned as BigInteger + * - floating point numbers are converted to a string then parsed as such + * - strings containing a `/` character are returned as BigRational + * - strings containing a `.` character or using an exponential notation are returned as BigDecimal + * - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger + * + * @param BigNumber|int|float|string $value + * + * @return BigNumber + * + * @throws NumberFormatException If the format of the number is not valid. + * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero. + * + * @psalm-pure + */ + public static function of($value) : BigNumber + { + if ($value instanceof BigNumber) { + return $value; + } + + if (\is_int($value)) { + return new BigInteger((string) $value); + } + + /** @psalm-suppress RedundantCastGivenDocblockType We cannot trust the untyped $value here! */ + $value = \is_float($value) ? self::floatToString($value) : (string) $value; + + $throw = static function() use ($value) : void { + throw new NumberFormatException(\sprintf( + 'The given value "%s" does not represent a valid number.', + $value + )); + }; + + if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) { + $throw(); + } + + $getMatch = static function(string $value) use ($matches) : ?string { + return isset($matches[$value]) && $matches[$value] !== '' ? $matches[$value] : null; + }; + + $sign = $getMatch('sign'); + $numerator = $getMatch('numerator'); + $denominator = $getMatch('denominator'); + + if ($numerator !== null) { + assert($denominator !== null); + + if ($sign !== null) { + $numerator = $sign . $numerator; + } + + $numerator = self::cleanUp($numerator); + $denominator = self::cleanUp($denominator); + + if ($denominator === '0') { + throw DivisionByZeroException::denominatorMustNotBeZero(); + } + + return new BigRational( + new BigInteger($numerator), + new BigInteger($denominator), + false + ); + } + + $point = $getMatch('point'); + $integral = $getMatch('integral'); + $fractional = $getMatch('fractional'); + $exponent = $getMatch('exponent'); + + if ($integral === null && $fractional === null) { + $throw(); + } + + if ($integral === null) { + $integral = '0'; + } + + if ($point !== null || $exponent !== null) { + $fractional = ($fractional ?? ''); + $exponent = ($exponent !== null) ? (int) $exponent : 0; + + if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) { + throw new NumberFormatException('Exponent too large.'); + } + + $unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional); + + $scale = \strlen($fractional) - $exponent; + + if ($scale < 0) { + if ($unscaledValue !== '0') { + $unscaledValue .= \str_repeat('0', - $scale); + } + $scale = 0; + } + + return new BigDecimal($unscaledValue, $scale); + } + + $integral = self::cleanUp(($sign ?? '') . $integral); + + return new BigInteger($integral); + } + + /** + * Safely converts float to string, avoiding locale-dependent issues. + * + * @see https://github.com/brick/math/pull/20 + * + * @param float $float + * + * @return string + * + * @psalm-pure + * @psalm-suppress ImpureFunctionCall + */ + private static function floatToString(float $float) : string + { + $currentLocale = \setlocale(LC_NUMERIC, '0'); + \setlocale(LC_NUMERIC, 'C'); + + $result = (string) $float; + + \setlocale(LC_NUMERIC, $currentLocale); + + return $result; + } + + /** + * Proxy method to access protected constructors from sibling classes. + * + * @internal + * + * @param mixed ...$args The arguments to the constructor. + * + * @return static + * + * @psalm-pure + * @psalm-suppress TooManyArguments + * @psalm-suppress UnsafeInstantiation + */ + protected static function create(... $args) : BigNumber + { + return new static(... $args); + } + + /** + * Returns the minimum of the given values. + * + * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible + * to an instance of the class this method is called on. + * + * @return static The minimum value. + * + * @throws \InvalidArgumentException If no values are given. + * @throws MathException If an argument is not valid. + * + * @psalm-suppress LessSpecificReturnStatement + * @psalm-suppress MoreSpecificReturnType + * @psalm-pure + */ + public static function min(...$values) : BigNumber + { + $min = null; + + foreach ($values as $value) { + $value = static::of($value); + + if ($min === null || $value->isLessThan($min)) { + $min = $value; + } + } + + if ($min === null) { + throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); + } + + return $min; + } + + /** + * Returns the maximum of the given values. + * + * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible + * to an instance of the class this method is called on. + * + * @return static The maximum value. + * + * @throws \InvalidArgumentException If no values are given. + * @throws MathException If an argument is not valid. + * + * @psalm-suppress LessSpecificReturnStatement + * @psalm-suppress MoreSpecificReturnType + * @psalm-pure + */ + public static function max(...$values) : BigNumber + { + $max = null; + + foreach ($values as $value) { + $value = static::of($value); + + if ($max === null || $value->isGreaterThan($max)) { + $max = $value; + } + } + + if ($max === null) { + throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); + } + + return $max; + } + + /** + * Returns the sum of the given values. + * + * @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible + * to an instance of the class this method is called on. + * + * @return static The sum. + * + * @throws \InvalidArgumentException If no values are given. + * @throws MathException If an argument is not valid. + * + * @psalm-suppress LessSpecificReturnStatement + * @psalm-suppress MoreSpecificReturnType + * @psalm-pure + */ + public static function sum(...$values) : BigNumber + { + /** @var BigNumber|null $sum */ + $sum = null; + + foreach ($values as $value) { + $value = static::of($value); + + $sum = $sum === null ? $value : self::add($sum, $value); + } + + if ($sum === null) { + throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); + } + + return $sum; + } + + /** + * Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException. + * + * @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to + * concrete classes the responsibility to perform the addition themselves or delegate it to the given number, + * depending on their ability to perform the operation. This will also require a version bump because we're + * potentially breaking custom BigNumber implementations (if any...) + * + * @param BigNumber $a + * @param BigNumber $b + * + * @return BigNumber + * + * @psalm-pure + */ + private static function add(BigNumber $a, BigNumber $b) : BigNumber + { + if ($a instanceof BigRational) { + return $a->plus($b); + } + + if ($b instanceof BigRational) { + return $b->plus($a); + } + + if ($a instanceof BigDecimal) { + return $a->plus($b); + } + + if ($b instanceof BigDecimal) { + return $b->plus($a); + } + + /** @var BigInteger $a */ + + return $a->plus($b); + } + + /** + * Removes optional leading zeros and + sign from the given number. + * + * @param string $number The number, validated as a non-empty string of digits with optional leading sign. + * + * @return string + * + * @psalm-pure + */ + private static function cleanUp(string $number) : string + { + $firstChar = $number[0]; + + if ($firstChar === '+' || $firstChar === '-') { + $number = \substr($number, 1); + } + + $number = \ltrim($number, '0'); + + if ($number === '') { + return '0'; + } + + if ($firstChar === '-') { + return '-' . $number; + } + + return $number; + } + + /** + * Checks if this number is equal to the given one. + * + * @param BigNumber|int|float|string $that + * + * @return bool + */ + public function isEqualTo($that) : bool + { + return $this->compareTo($that) === 0; + } + + /** + * Checks if this number is strictly lower than the given one. + * + * @param BigNumber|int|float|string $that + * + * @return bool + */ + public function isLessThan($that) : bool + { + return $this->compareTo($that) < 0; + } + + /** + * Checks if this number is lower than or equal to the given one. + * + * @param BigNumber|int|float|string $that + * + * @return bool + */ + public function isLessThanOrEqualTo($that) : bool + { + return $this->compareTo($that) <= 0; + } + + /** + * Checks if this number is strictly greater than the given one. + * + * @param BigNumber|int|float|string $that + * + * @return bool + */ + public function isGreaterThan($that) : bool + { + return $this->compareTo($that) > 0; + } + + /** + * Checks if this number is greater than or equal to the given one. + * + * @param BigNumber|int|float|string $that + * + * @return bool + */ + public function isGreaterThanOrEqualTo($that) : bool + { + return $this->compareTo($that) >= 0; + } + + /** + * Checks if this number equals zero. + * + * @return bool + */ + public function isZero() : bool + { + return $this->getSign() === 0; + } + + /** + * Checks if this number is strictly negative. + * + * @return bool + */ + public function isNegative() : bool + { + return $this->getSign() < 0; + } + + /** + * Checks if this number is negative or zero. + * + * @return bool + */ + public function isNegativeOrZero() : bool + { + return $this->getSign() <= 0; + } + + /** + * Checks if this number is strictly positive. + * + * @return bool + */ + public function isPositive() : bool + { + return $this->getSign() > 0; + } + + /** + * Checks if this number is positive or zero. + * + * @return bool + */ + public function isPositiveOrZero() : bool + { + return $this->getSign() >= 0; + } + + /** + * Returns the sign of this number. + * + * @return int -1 if the number is negative, 0 if zero, 1 if positive. + */ + abstract public function getSign() : int; + + /** + * Compares this number to the given one. + * + * @param BigNumber|int|float|string $that + * + * @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`. + * + * @throws MathException If the number is not valid. + */ + abstract public function compareTo($that) : int; + + /** + * Converts this number to a BigInteger. + * + * @return BigInteger The converted number. + * + * @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding. + */ + abstract public function toBigInteger() : BigInteger; + + /** + * Converts this number to a BigDecimal. + * + * @return BigDecimal The converted number. + * + * @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding. + */ + abstract public function toBigDecimal() : BigDecimal; + + /** + * Converts this number to a BigRational. + * + * @return BigRational The converted number. + */ + abstract public function toBigRational() : BigRational; + + /** + * Converts this number to a BigDecimal with the given scale, using rounding if necessary. + * + * @param int $scale The scale of the resulting `BigDecimal`. + * @param int $roundingMode A `RoundingMode` constant. + * + * @return BigDecimal + * + * @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding. + * This only applies when RoundingMode::UNNECESSARY is used. + */ + abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal; + + /** + * Returns the exact value of this number as a native integer. + * + * If this number cannot be converted to a native integer without losing precision, an exception is thrown. + * Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit. + * + * @return int The converted value. + * + * @throws MathException If this number cannot be exactly converted to a native integer. + */ + abstract public function toInt() : int; + + /** + * Returns an approximation of this number as a floating-point value. + * + * Note that this method can discard information as the precision of a floating-point value + * is inherently limited. + * + * If the number is greater than the largest representable floating point number, positive infinity is returned. + * If the number is less than the smallest representable floating point number, negative infinity is returned. + * + * @return float The converted value. + */ + abstract public function toFloat() : float; + + /** + * Returns a string representation of this number. + * + * The output of this method can be parsed by the `of()` factory method; + * this will yield an object equal to this one, without any information loss. + * + * @return string + */ + abstract public function __toString() : string; + + /** + * {@inheritdoc} + */ + public function jsonSerialize() : string + { + return $this->__toString(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigRational.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigRational.php new file mode 100644 index 00000000..bee094f7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/BigRational.php @@ -0,0 +1,523 @@ +isZero()) { + throw DivisionByZeroException::denominatorMustNotBeZero(); + } + + if ($denominator->isNegative()) { + $numerator = $numerator->negated(); + $denominator = $denominator->negated(); + } + } + + $this->numerator = $numerator; + $this->denominator = $denominator; + } + + /** + * Creates a BigRational of the given value. + * + * @param BigNumber|int|float|string $value + * + * @return BigRational + * + * @throws MathException If the value cannot be converted to a BigRational. + * + * @psalm-pure + */ + public static function of($value) : BigNumber + { + return parent::of($value)->toBigRational(); + } + + /** + * Creates a BigRational out of a numerator and a denominator. + * + * If the denominator is negative, the signs of both the numerator and the denominator + * will be inverted to ensure that the denominator is always positive. + * + * @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger. + * @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger. + * + * @return BigRational + * + * @throws NumberFormatException If an argument does not represent a valid number. + * @throws RoundingNecessaryException If an argument represents a non-integer number. + * @throws DivisionByZeroException If the denominator is zero. + * + * @psalm-pure + */ + public static function nd($numerator, $denominator) : BigRational + { + $numerator = BigInteger::of($numerator); + $denominator = BigInteger::of($denominator); + + return new BigRational($numerator, $denominator, true); + } + + /** + * Returns a BigRational representing zero. + * + * @return BigRational + * + * @psalm-pure + */ + public static function zero() : BigRational + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigRational|null $zero + */ + static $zero; + + if ($zero === null) { + $zero = new BigRational(BigInteger::zero(), BigInteger::one(), false); + } + + return $zero; + } + + /** + * Returns a BigRational representing one. + * + * @return BigRational + * + * @psalm-pure + */ + public static function one() : BigRational + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigRational|null $one + */ + static $one; + + if ($one === null) { + $one = new BigRational(BigInteger::one(), BigInteger::one(), false); + } + + return $one; + } + + /** + * Returns a BigRational representing ten. + * + * @return BigRational + * + * @psalm-pure + */ + public static function ten() : BigRational + { + /** + * @psalm-suppress ImpureStaticVariable + * @var BigRational|null $ten + */ + static $ten; + + if ($ten === null) { + $ten = new BigRational(BigInteger::ten(), BigInteger::one(), false); + } + + return $ten; + } + + /** + * @return BigInteger + */ + public function getNumerator() : BigInteger + { + return $this->numerator; + } + + /** + * @return BigInteger + */ + public function getDenominator() : BigInteger + { + return $this->denominator; + } + + /** + * Returns the quotient of the division of the numerator by the denominator. + * + * @return BigInteger + */ + public function quotient() : BigInteger + { + return $this->numerator->quotient($this->denominator); + } + + /** + * Returns the remainder of the division of the numerator by the denominator. + * + * @return BigInteger + */ + public function remainder() : BigInteger + { + return $this->numerator->remainder($this->denominator); + } + + /** + * Returns the quotient and remainder of the division of the numerator by the denominator. + * + * @return BigInteger[] + */ + public function quotientAndRemainder() : array + { + return $this->numerator->quotientAndRemainder($this->denominator); + } + + /** + * Returns the sum of this number and the given one. + * + * @param BigNumber|int|float|string $that The number to add. + * + * @return BigRational The result. + * + * @throws MathException If the number is not valid. + */ + public function plus($that) : BigRational + { + $that = BigRational::of($that); + + $numerator = $this->numerator->multipliedBy($that->denominator); + $numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator)); + $denominator = $this->denominator->multipliedBy($that->denominator); + + return new BigRational($numerator, $denominator, false); + } + + /** + * Returns the difference of this number and the given one. + * + * @param BigNumber|int|float|string $that The number to subtract. + * + * @return BigRational The result. + * + * @throws MathException If the number is not valid. + */ + public function minus($that) : BigRational + { + $that = BigRational::of($that); + + $numerator = $this->numerator->multipliedBy($that->denominator); + $numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator)); + $denominator = $this->denominator->multipliedBy($that->denominator); + + return new BigRational($numerator, $denominator, false); + } + + /** + * Returns the product of this number and the given one. + * + * @param BigNumber|int|float|string $that The multiplier. + * + * @return BigRational The result. + * + * @throws MathException If the multiplier is not a valid number. + */ + public function multipliedBy($that) : BigRational + { + $that = BigRational::of($that); + + $numerator = $this->numerator->multipliedBy($that->numerator); + $denominator = $this->denominator->multipliedBy($that->denominator); + + return new BigRational($numerator, $denominator, false); + } + + /** + * Returns the result of the division of this number by the given one. + * + * @param BigNumber|int|float|string $that The divisor. + * + * @return BigRational The result. + * + * @throws MathException If the divisor is not a valid number, or is zero. + */ + public function dividedBy($that) : BigRational + { + $that = BigRational::of($that); + + $numerator = $this->numerator->multipliedBy($that->denominator); + $denominator = $this->denominator->multipliedBy($that->numerator); + + return new BigRational($numerator, $denominator, true); + } + + /** + * Returns this number exponentiated to the given value. + * + * @param int $exponent The exponent. + * + * @return BigRational The result. + * + * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. + */ + public function power(int $exponent) : BigRational + { + if ($exponent === 0) { + $one = BigInteger::one(); + + return new BigRational($one, $one, false); + } + + if ($exponent === 1) { + return $this; + } + + return new BigRational( + $this->numerator->power($exponent), + $this->denominator->power($exponent), + false + ); + } + + /** + * Returns the reciprocal of this BigRational. + * + * The reciprocal has the numerator and denominator swapped. + * + * @return BigRational + * + * @throws DivisionByZeroException If the numerator is zero. + */ + public function reciprocal() : BigRational + { + return new BigRational($this->denominator, $this->numerator, true); + } + + /** + * Returns the absolute value of this BigRational. + * + * @return BigRational + */ + public function abs() : BigRational + { + return new BigRational($this->numerator->abs(), $this->denominator, false); + } + + /** + * Returns the negated value of this BigRational. + * + * @return BigRational + */ + public function negated() : BigRational + { + return new BigRational($this->numerator->negated(), $this->denominator, false); + } + + /** + * Returns the simplified value of this BigRational. + * + * @return BigRational + */ + public function simplified() : BigRational + { + $gcd = $this->numerator->gcd($this->denominator); + + $numerator = $this->numerator->quotient($gcd); + $denominator = $this->denominator->quotient($gcd); + + return new BigRational($numerator, $denominator, false); + } + + /** + * {@inheritdoc} + */ + public function compareTo($that) : int + { + return $this->minus($that)->getSign(); + } + + /** + * {@inheritdoc} + */ + public function getSign() : int + { + return $this->numerator->getSign(); + } + + /** + * {@inheritdoc} + */ + public function toBigInteger() : BigInteger + { + $simplified = $this->simplified(); + + if (! $simplified->denominator->isEqualTo(1)) { + throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.'); + } + + return $simplified->numerator; + } + + /** + * {@inheritdoc} + */ + public function toBigDecimal() : BigDecimal + { + return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator); + } + + /** + * {@inheritdoc} + */ + public function toBigRational() : BigRational + { + return $this; + } + + /** + * {@inheritdoc} + */ + public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + { + return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode); + } + + /** + * {@inheritdoc} + */ + public function toInt() : int + { + return $this->toBigInteger()->toInt(); + } + + /** + * {@inheritdoc} + */ + public function toFloat() : float + { + return $this->numerator->toFloat() / $this->denominator->toFloat(); + } + + /** + * {@inheritdoc} + */ + public function __toString() : string + { + $numerator = (string) $this->numerator; + $denominator = (string) $this->denominator; + + if ($denominator === '1') { + return $numerator; + } + + return $this->numerator . '/' . $this->denominator; + } + + /** + * This method is required for serializing the object and SHOULD NOT be accessed directly. + * + * @internal + * + * @return array{numerator: BigInteger, denominator: BigInteger} + */ + public function __serialize(): array + { + return ['numerator' => $this->numerator, 'denominator' => $this->denominator]; + } + + /** + * This method is only here to allow unserializing the object and cannot be accessed directly. + * + * @internal + * @psalm-suppress RedundantPropertyInitializationCheck + * + * @param array{numerator: BigInteger, denominator: BigInteger} $data + * + * @return void + * + * @throws \LogicException + */ + public function __unserialize(array $data): void + { + if (isset($this->numerator)) { + throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); + } + + $this->numerator = $data['numerator']; + $this->denominator = $data['denominator']; + } + + /** + * This method is required by interface Serializable and SHOULD NOT be accessed directly. + * + * @internal + * + * @return string + */ + public function serialize() : string + { + return $this->numerator . '/' . $this->denominator; + } + + /** + * This method is only here to implement interface Serializable and cannot be accessed directly. + * + * @internal + * @psalm-suppress RedundantPropertyInitializationCheck + * + * @param string $value + * + * @return void + * + * @throws \LogicException + */ + public function unserialize($value) : void + { + if (isset($this->numerator)) { + throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); + } + + [$numerator, $denominator] = \explode('/', $value); + + $this->numerator = BigInteger::of($numerator); + $this->denominator = BigInteger::of($denominator); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/DivisionByZeroException.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/DivisionByZeroException.php new file mode 100644 index 00000000..a4e44317 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/DivisionByZeroException.php @@ -0,0 +1,41 @@ + 126) { + $char = \strtoupper(\dechex($ord)); + + if ($ord < 10) { + $char = '0' . $char; + } + } else { + $char = '"' . $char . '"'; + } + + return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/RoundingNecessaryException.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/RoundingNecessaryException.php new file mode 100644 index 00000000..1c610056 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Exception/RoundingNecessaryException.php @@ -0,0 +1,21 @@ +init($a, $b); + + if ($aNeg && ! $bNeg) { + return -1; + } + + if ($bNeg && ! $aNeg) { + return 1; + } + + $aLen = \strlen($aDig); + $bLen = \strlen($bDig); + + if ($aLen < $bLen) { + $result = -1; + } elseif ($aLen > $bLen) { + $result = 1; + } else { + $result = $aDig <=> $bDig; + } + + return $aNeg ? -$result : $result; + } + + /** + * Adds two numbers. + * + * @param string $a The augend. + * @param string $b The addend. + * + * @return string The sum. + */ + abstract public function add(string $a, string $b) : string; + + /** + * Subtracts two numbers. + * + * @param string $a The minuend. + * @param string $b The subtrahend. + * + * @return string The difference. + */ + abstract public function sub(string $a, string $b) : string; + + /** + * Multiplies two numbers. + * + * @param string $a The multiplicand. + * @param string $b The multiplier. + * + * @return string The product. + */ + abstract public function mul(string $a, string $b) : string; + + /** + * Returns the quotient of the division of two numbers. + * + * @param string $a The dividend. + * @param string $b The divisor, must not be zero. + * + * @return string The quotient. + */ + abstract public function divQ(string $a, string $b) : string; + + /** + * Returns the remainder of the division of two numbers. + * + * @param string $a The dividend. + * @param string $b The divisor, must not be zero. + * + * @return string The remainder. + */ + abstract public function divR(string $a, string $b) : string; + + /** + * Returns the quotient and remainder of the division of two numbers. + * + * @param string $a The dividend. + * @param string $b The divisor, must not be zero. + * + * @return string[] An array containing the quotient and remainder. + */ + abstract public function divQR(string $a, string $b) : array; + + /** + * Exponentiates a number. + * + * @param string $a The base number. + * @param int $e The exponent, validated as an integer between 0 and MAX_POWER. + * + * @return string The power. + */ + abstract public function pow(string $a, int $e) : string; + + /** + * @param string $a + * @param string $b The modulus; must not be zero. + * + * @return string + */ + public function mod(string $a, string $b) : string + { + return $this->divR($this->add($this->divR($a, $b), $b), $b); + } + + /** + * Returns the modular multiplicative inverse of $x modulo $m. + * + * If $x has no multiplicative inverse mod m, this method must return null. + * + * This method can be overridden by the concrete implementation if the underlying library has built-in support. + * + * @param string $x + * @param string $m The modulus; must not be negative or zero. + * + * @return string|null + */ + public function modInverse(string $x, string $m) : ?string + { + if ($m === '1') { + return '0'; + } + + $modVal = $x; + + if ($x[0] === '-' || ($this->cmp($this->abs($x), $m) >= 0)) { + $modVal = $this->mod($x, $m); + } + + $x = '0'; + $y = '0'; + $g = $this->gcdExtended($modVal, $m, $x, $y); + + if ($g !== '1') { + return null; + } + + return $this->mod($this->add($this->mod($x, $m), $m), $m); + } + + /** + * Raises a number into power with modulo. + * + * @param string $base The base number; must be positive or zero. + * @param string $exp The exponent; must be positive or zero. + * @param string $mod The modulus; must be strictly positive. + * + * @return string The power. + */ + abstract public function modPow(string $base, string $exp, string $mod) : string; + + /** + * Returns the greatest common divisor of the two numbers. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for GCD calculations. + * + * @param string $a The first number. + * @param string $b The second number. + * + * @return string The GCD, always positive, or zero if both arguments are zero. + */ + public function gcd(string $a, string $b) : string + { + if ($a === '0') { + return $this->abs($b); + } + + if ($b === '0') { + return $this->abs($a); + } + + return $this->gcd($b, $this->divR($a, $b)); + } + + private function gcdExtended(string $a, string $b, string &$x, string &$y) : string + { + if ($a === '0') { + $x = '0'; + $y = '1'; + + return $b; + } + + $x1 = '0'; + $y1 = '0'; + + $gcd = $this->gcdExtended($this->mod($b, $a), $a, $x1, $y1); + + $x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1)); + $y = $x1; + + return $gcd; + } + + /** + * Returns the square root of the given number, rounded down. + * + * The result is the largest x such that x² ≤ n. + * The input MUST NOT be negative. + * + * @param string $n The number. + * + * @return string The square root. + */ + abstract public function sqrt(string $n) : string; + + /** + * Converts a number from an arbitrary base. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for base conversion. + * + * @param string $number The number, positive or zero, non-empty, case-insensitively validated for the given base. + * @param int $base The base of the number, validated from 2 to 36. + * + * @return string The converted number, following the Calculator conventions. + */ + public function fromBase(string $number, int $base) : string + { + return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base); + } + + /** + * Converts a number to an arbitrary base. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for base conversion. + * + * @param string $number The number to convert, following the Calculator conventions. + * @param int $base The base to convert to, validated from 2 to 36. + * + * @return string The converted number, lowercase. + */ + public function toBase(string $number, int $base) : string + { + $negative = ($number[0] === '-'); + + if ($negative) { + $number = \substr($number, 1); + } + + $number = $this->toArbitraryBase($number, self::ALPHABET, $base); + + if ($negative) { + return '-' . $number; + } + + return $number; + } + + /** + * Converts a non-negative number in an arbitrary base using a custom alphabet, to base 10. + * + * @param string $number The number to convert, validated as a non-empty string, + * containing only chars in the given alphabet/base. + * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum. + * @param int $base The base of the number, validated from 2 to alphabet length. + * + * @return string The number in base 10, following the Calculator conventions. + */ + final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string + { + // remove leading "zeros" + $number = \ltrim($number, $alphabet[0]); + + if ($number === '') { + return '0'; + } + + // optimize for "one" + if ($number === $alphabet[1]) { + return '1'; + } + + $result = '0'; + $power = '1'; + + $base = (string) $base; + + for ($i = \strlen($number) - 1; $i >= 0; $i--) { + $index = \strpos($alphabet, $number[$i]); + + if ($index !== 0) { + $result = $this->add($result, ($index === 1) + ? $power + : $this->mul($power, (string) $index) + ); + } + + if ($i !== 0) { + $power = $this->mul($power, $base); + } + } + + return $result; + } + + /** + * Converts a non-negative number to an arbitrary base using a custom alphabet. + * + * @param string $number The number to convert, positive or zero, following the Calculator conventions. + * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum. + * @param int $base The base to convert to, validated from 2 to alphabet length. + * + * @return string The converted number in the given alphabet. + */ + final public function toArbitraryBase(string $number, string $alphabet, int $base) : string + { + if ($number === '0') { + return $alphabet[0]; + } + + $base = (string) $base; + $result = ''; + + while ($number !== '0') { + [$number, $remainder] = $this->divQR($number, $base); + $remainder = (int) $remainder; + + $result .= $alphabet[$remainder]; + } + + return \strrev($result); + } + + /** + * Performs a rounded division. + * + * Rounding is performed when the remainder of the division is not zero. + * + * @param string $a The dividend. + * @param string $b The divisor, must not be zero. + * @param int $roundingMode The rounding mode. + * + * @return string + * + * @throws \InvalidArgumentException If the rounding mode is invalid. + * @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary. + */ + final public function divRound(string $a, string $b, int $roundingMode) : string + { + [$quotient, $remainder] = $this->divQR($a, $b); + + $hasDiscardedFraction = ($remainder !== '0'); + $isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-'); + + $discardedFractionSign = function() use ($remainder, $b) : int { + $r = $this->abs($this->mul($remainder, '2')); + $b = $this->abs($b); + + return $this->cmp($r, $b); + }; + + $increment = false; + + switch ($roundingMode) { + case RoundingMode::UNNECESSARY: + if ($hasDiscardedFraction) { + throw RoundingNecessaryException::roundingNecessary(); + } + break; + + case RoundingMode::UP: + $increment = $hasDiscardedFraction; + break; + + case RoundingMode::DOWN: + break; + + case RoundingMode::CEILING: + $increment = $hasDiscardedFraction && $isPositiveOrZero; + break; + + case RoundingMode::FLOOR: + $increment = $hasDiscardedFraction && ! $isPositiveOrZero; + break; + + case RoundingMode::HALF_UP: + $increment = $discardedFractionSign() >= 0; + break; + + case RoundingMode::HALF_DOWN: + $increment = $discardedFractionSign() > 0; + break; + + case RoundingMode::HALF_CEILING: + $increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0; + break; + + case RoundingMode::HALF_FLOOR: + $increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0; + break; + + case RoundingMode::HALF_EVEN: + $lastDigit = (int) $quotient[-1]; + $lastDigitIsEven = ($lastDigit % 2 === 0); + $increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0; + break; + + default: + throw new \InvalidArgumentException('Invalid rounding mode.'); + } + + if ($increment) { + return $this->add($quotient, $isPositiveOrZero ? '1' : '-1'); + } + + return $quotient; + } + + /** + * Calculates bitwise AND of two numbers. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for bitwise operations. + * + * @param string $a + * @param string $b + * + * @return string + */ + public function and(string $a, string $b) : string + { + return $this->bitwise('and', $a, $b); + } + + /** + * Calculates bitwise OR of two numbers. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for bitwise operations. + * + * @param string $a + * @param string $b + * + * @return string + */ + public function or(string $a, string $b) : string + { + return $this->bitwise('or', $a, $b); + } + + /** + * Calculates bitwise XOR of two numbers. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for bitwise operations. + * + * @param string $a + * @param string $b + * + * @return string + */ + public function xor(string $a, string $b) : string + { + return $this->bitwise('xor', $a, $b); + } + + /** + * Performs a bitwise operation on a decimal number. + * + * @param string $operator The operator to use, must be "and", "or" or "xor". + * @param string $a The left operand. + * @param string $b The right operand. + * + * @return string + */ + private function bitwise(string $operator, string $a, string $b) : string + { + [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); + + $aBin = $this->toBinary($aDig); + $bBin = $this->toBinary($bDig); + + $aLen = \strlen($aBin); + $bLen = \strlen($bBin); + + if ($aLen > $bLen) { + $bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin; + } elseif ($bLen > $aLen) { + $aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin; + } + + if ($aNeg) { + $aBin = $this->twosComplement($aBin); + } + if ($bNeg) { + $bBin = $this->twosComplement($bBin); + } + + switch ($operator) { + case 'and': + $value = $aBin & $bBin; + $negative = ($aNeg and $bNeg); + break; + + case 'or': + $value = $aBin | $bBin; + $negative = ($aNeg or $bNeg); + break; + + case 'xor': + $value = $aBin ^ $bBin; + $negative = ($aNeg xor $bNeg); + break; + + // @codeCoverageIgnoreStart + default: + throw new \InvalidArgumentException('Invalid bitwise operator.'); + // @codeCoverageIgnoreEnd + } + + if ($negative) { + $value = $this->twosComplement($value); + } + + $result = $this->toDecimal($value); + + return $negative ? $this->neg($result) : $result; + } + + /** + * @param string $number A positive, binary number. + * + * @return string + */ + private function twosComplement(string $number) : string + { + $xor = \str_repeat("\xff", \strlen($number)); + + $number ^= $xor; + + for ($i = \strlen($number) - 1; $i >= 0; $i--) { + $byte = \ord($number[$i]); + + if (++$byte !== 256) { + $number[$i] = \chr($byte); + break; + } + + $number[$i] = "\x00"; + + if ($i === 0) { + $number = "\x01" . $number; + } + } + + return $number; + } + + /** + * Converts a decimal number to a binary string. + * + * @param string $number The number to convert, positive or zero, only digits. + * + * @return string + */ + private function toBinary(string $number) : string + { + $result = ''; + + while ($number !== '0') { + [$number, $remainder] = $this->divQR($number, '256'); + $result .= \chr((int) $remainder); + } + + return \strrev($result); + } + + /** + * Returns the positive decimal representation of a binary number. + * + * @param string $bytes The bytes representing the number. + * + * @return string + */ + private function toDecimal(string $bytes) : string + { + $result = '0'; + $power = '1'; + + for ($i = \strlen($bytes) - 1; $i >= 0; $i--) { + $index = \ord($bytes[$i]); + + if ($index !== 0) { + $result = $this->add($result, ($index === 1) + ? $power + : $this->mul($power, (string) $index) + ); + } + + if ($i !== 0) { + $power = $this->mul($power, '256'); + } + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php new file mode 100644 index 00000000..6632b378 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php @@ -0,0 +1,116 @@ += 0) { + return \bcmod($a, $b, 0); + } + + return \bcmod($a, $b); + } + + /** + * {@inheritdoc} + */ + public function divQR(string $a, string $b) : array + { + $q = \bcdiv($a, $b, 0); + + if (version_compare(PHP_VERSION, '7.2') >= 0) { + $r = \bcmod($a, $b, 0); + } else { + $r = \bcmod($a, $b); + } + + assert($q !== null); + assert($r !== null); + + return [$q, $r]; + } + + /** + * {@inheritdoc} + */ + public function pow(string $a, int $e) : string + { + return \bcpow($a, (string) $e, 0); + } + + /** + * {@inheritdoc} + * + * @psalm-suppress InvalidNullableReturnType + * @psalm-suppress NullableReturnStatement + */ + public function modPow(string $base, string $exp, string $mod) : string + { + return \bcpowmod($base, $exp, $mod, 0); + } + + /** + * {@inheritDoc} + * + * @psalm-suppress NullableReturnStatement + * @psalm-suppress InvalidNullableReturnType + */ + public function sqrt(string $n) : string + { + return \bcsqrt($n, 0); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php new file mode 100644 index 00000000..52d18800 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php @@ -0,0 +1,156 @@ +maxDigits = 9; + break; + + case 8: + $this->maxDigits = 18; + break; + + default: + throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.'); + } + } + + /** + * {@inheritdoc} + */ + public function add(string $a, string $b) : string + { + /** + * @psalm-var numeric-string $a + * @psalm-var numeric-string $b + */ + $result = $a + $b; + + if (is_int($result)) { + return (string) $result; + } + + if ($a === '0') { + return $b; + } + + if ($b === '0') { + return $a; + } + + [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); + + $result = $aNeg === $bNeg ? $this->doAdd($aDig, $bDig) : $this->doSub($aDig, $bDig); + + if ($aNeg) { + $result = $this->neg($result); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function sub(string $a, string $b) : string + { + return $this->add($a, $this->neg($b)); + } + + /** + * {@inheritdoc} + */ + public function mul(string $a, string $b) : string + { + /** + * @psalm-var numeric-string $a + * @psalm-var numeric-string $b + */ + $result = $a * $b; + + if (is_int($result)) { + return (string) $result; + } + + if ($a === '0' || $b === '0') { + return '0'; + } + + if ($a === '1') { + return $b; + } + + if ($b === '1') { + return $a; + } + + if ($a === '-1') { + return $this->neg($b); + } + + if ($b === '-1') { + return $this->neg($a); + } + + [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); + + $result = $this->doMul($aDig, $bDig); + + if ($aNeg !== $bNeg) { + $result = $this->neg($result); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function divQ(string $a, string $b) : string + { + return $this->divQR($a, $b)[0]; + } + + /** + * {@inheritdoc} + */ + public function divR(string $a, string $b): string + { + return $this->divQR($a, $b)[1]; + } + + /** + * {@inheritdoc} + */ + public function divQR(string $a, string $b) : array + { + if ($a === '0') { + return ['0', '0']; + } + + if ($a === $b) { + return ['1', '0']; + } + + if ($b === '1') { + return [$a, '0']; + } + + if ($b === '-1') { + return [$this->neg($a), '0']; + } + + /** @psalm-var numeric-string $a */ + $na = $a * 1; // cast to number + + if (is_int($na)) { + /** @psalm-var numeric-string $b */ + $nb = $b * 1; + + if (is_int($nb)) { + // the only division that may overflow is PHP_INT_MIN / -1, + // which cannot happen here as we've already handled a divisor of -1 above. + $r = $na % $nb; + $q = ($na - $r) / $nb; + + assert(is_int($q)); + + return [ + (string) $q, + (string) $r + ]; + } + } + + [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); + + [$q, $r] = $this->doDiv($aDig, $bDig); + + if ($aNeg !== $bNeg) { + $q = $this->neg($q); + } + + if ($aNeg) { + $r = $this->neg($r); + } + + return [$q, $r]; + } + + /** + * {@inheritdoc} + */ + public function pow(string $a, int $e) : string + { + if ($e === 0) { + return '1'; + } + + if ($e === 1) { + return $a; + } + + $odd = $e % 2; + $e -= $odd; + + $aa = $this->mul($a, $a); + + /** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */ + $result = $this->pow($aa, $e / 2); + + if ($odd === 1) { + $result = $this->mul($result, $a); + } + + return $result; + } + + /** + * Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/ + * + * {@inheritdoc} + */ + public function modPow(string $base, string $exp, string $mod) : string + { + // special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0) + if ($base === '0' && $exp === '0' && $mod === '1') { + return '0'; + } + + // special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0) + if ($exp === '0' && $mod === '1') { + return '0'; + } + + $x = $base; + + $res = '1'; + + // numbers are positive, so we can use remainder instead of modulo + $x = $this->divR($x, $mod); + + while ($exp !== '0') { + if (in_array($exp[-1], ['1', '3', '5', '7', '9'])) { // odd + $res = $this->divR($this->mul($res, $x), $mod); + } + + $exp = $this->divQ($exp, '2'); + $x = $this->divR($this->mul($x, $x), $mod); + } + + return $res; + } + + /** + * Adapted from https://cp-algorithms.com/num_methods/roots_newton.html + * + * {@inheritDoc} + */ + public function sqrt(string $n) : string + { + if ($n === '0') { + return '0'; + } + + // initial approximation + $x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1); + + $decreased = false; + + for (;;) { + $nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2'); + + if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) { + break; + } + + $decreased = $this->cmp($nx, $x) < 0; + $x = $nx; + } + + return $x; + } + + /** + * Performs the addition of two non-signed large integers. + * + * @param string $a The first operand. + * @param string $b The second operand. + * + * @return string + */ + private function doAdd(string $a, string $b) : string + { + [$a, $b, $length] = $this->pad($a, $b); + + $carry = 0; + $result = ''; + + for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) { + $blockLength = $this->maxDigits; + + if ($i < 0) { + $blockLength += $i; + /** @psalm-suppress LoopInvalidation */ + $i = 0; + } + + /** @psalm-var numeric-string $blockA */ + $blockA = \substr($a, $i, $blockLength); + + /** @psalm-var numeric-string $blockB */ + $blockB = \substr($b, $i, $blockLength); + + $sum = (string) ($blockA + $blockB + $carry); + $sumLength = \strlen($sum); + + if ($sumLength > $blockLength) { + $sum = \substr($sum, 1); + $carry = 1; + } else { + if ($sumLength < $blockLength) { + $sum = \str_repeat('0', $blockLength - $sumLength) . $sum; + } + $carry = 0; + } + + $result = $sum . $result; + + if ($i === 0) { + break; + } + } + + if ($carry === 1) { + $result = '1' . $result; + } + + return $result; + } + + /** + * Performs the subtraction of two non-signed large integers. + * + * @param string $a The first operand. + * @param string $b The second operand. + * + * @return string + */ + private function doSub(string $a, string $b) : string + { + if ($a === $b) { + return '0'; + } + + // Ensure that we always subtract to a positive result: biggest minus smallest. + $cmp = $this->doCmp($a, $b); + + $invert = ($cmp === -1); + + if ($invert) { + $c = $a; + $a = $b; + $b = $c; + } + + [$a, $b, $length] = $this->pad($a, $b); + + $carry = 0; + $result = ''; + + $complement = 10 ** $this->maxDigits; + + for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) { + $blockLength = $this->maxDigits; + + if ($i < 0) { + $blockLength += $i; + /** @psalm-suppress LoopInvalidation */ + $i = 0; + } + + /** @psalm-var numeric-string $blockA */ + $blockA = \substr($a, $i, $blockLength); + + /** @psalm-var numeric-string $blockB */ + $blockB = \substr($b, $i, $blockLength); + + $sum = $blockA - $blockB - $carry; + + if ($sum < 0) { + $sum += $complement; + $carry = 1; + } else { + $carry = 0; + } + + $sum = (string) $sum; + $sumLength = \strlen($sum); + + if ($sumLength < $blockLength) { + $sum = \str_repeat('0', $blockLength - $sumLength) . $sum; + } + + $result = $sum . $result; + + if ($i === 0) { + break; + } + } + + // Carry cannot be 1 when the loop ends, as a > b + assert($carry === 0); + + $result = \ltrim($result, '0'); + + if ($invert) { + $result = $this->neg($result); + } + + return $result; + } + + /** + * Performs the multiplication of two non-signed large integers. + * + * @param string $a The first operand. + * @param string $b The second operand. + * + * @return string + */ + private function doMul(string $a, string $b) : string + { + $x = \strlen($a); + $y = \strlen($b); + + $maxDigits = \intdiv($this->maxDigits, 2); + $complement = 10 ** $maxDigits; + + $result = '0'; + + for ($i = $x - $maxDigits;; $i -= $maxDigits) { + $blockALength = $maxDigits; + + if ($i < 0) { + $blockALength += $i; + /** @psalm-suppress LoopInvalidation */ + $i = 0; + } + + $blockA = (int) \substr($a, $i, $blockALength); + + $line = ''; + $carry = 0; + + for ($j = $y - $maxDigits;; $j -= $maxDigits) { + $blockBLength = $maxDigits; + + if ($j < 0) { + $blockBLength += $j; + /** @psalm-suppress LoopInvalidation */ + $j = 0; + } + + $blockB = (int) \substr($b, $j, $blockBLength); + + $mul = $blockA * $blockB + $carry; + $value = $mul % $complement; + $carry = ($mul - $value) / $complement; + + $value = (string) $value; + $value = \str_pad($value, $maxDigits, '0', STR_PAD_LEFT); + + $line = $value . $line; + + if ($j === 0) { + break; + } + } + + if ($carry !== 0) { + $line = $carry . $line; + } + + $line = \ltrim($line, '0'); + + if ($line !== '') { + $line .= \str_repeat('0', $x - $blockALength - $i); + $result = $this->add($result, $line); + } + + if ($i === 0) { + break; + } + } + + return $result; + } + + /** + * Performs the division of two non-signed large integers. + * + * @param string $a The first operand. + * @param string $b The second operand. + * + * @return string[] The quotient and remainder. + */ + private function doDiv(string $a, string $b) : array + { + $cmp = $this->doCmp($a, $b); + + if ($cmp === -1) { + return ['0', $a]; + } + + $x = \strlen($a); + $y = \strlen($b); + + // we now know that a >= b && x >= y + + $q = '0'; // quotient + $r = $a; // remainder + $z = $y; // focus length, always $y or $y+1 + + for (;;) { + $focus = \substr($a, 0, $z); + + $cmp = $this->doCmp($focus, $b); + + if ($cmp === -1) { + if ($z === $x) { // remainder < dividend + break; + } + + $z++; + } + + $zeros = \str_repeat('0', $x - $z); + + $q = $this->add($q, '1' . $zeros); + $a = $this->sub($a, $b . $zeros); + + $r = $a; + + if ($r === '0') { // remainder == 0 + break; + } + + $x = \strlen($a); + + if ($x < $y) { // remainder < dividend + break; + } + + $z = $y; + } + + return [$q, $r]; + } + + /** + * Compares two non-signed large numbers. + * + * @param string $a The first operand. + * @param string $b The second operand. + * + * @return int [-1, 0, 1] + */ + private function doCmp(string $a, string $b) : int + { + $x = \strlen($a); + $y = \strlen($b); + + $cmp = $x <=> $y; + + if ($cmp !== 0) { + return $cmp; + } + + return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1] + } + + /** + * Pads the left of one of the given numbers with zeros if necessary to make both numbers the same length. + * + * The numbers must only consist of digits, without leading minus sign. + * + * @param string $a The first operand. + * @param string $b The second operand. + * + * @return array{string, string, int} + */ + private function pad(string $a, string $b) : array + { + $x = \strlen($a); + $y = \strlen($b); + + if ($x > $y) { + $b = \str_repeat('0', $x - $y) . $b; + + return [$a, $b, $x]; + } + + if ($x < $y) { + $a = \str_repeat('0', $y - $x) . $a; + + return [$a, $b, $y]; + } + + return [$a, $b, $x]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/brick/math/src/RoundingMode.php b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/RoundingMode.php new file mode 100644 index 00000000..06936d8d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/brick/math/src/RoundingMode.php @@ -0,0 +1,107 @@ += 0.5; otherwise, behaves as for DOWN. + * Note that this is the rounding mode commonly taught at school. + */ + public const HALF_UP = 5; + + /** + * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. + * + * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN. + */ + public const HALF_DOWN = 6; + + /** + * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity. + * + * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN. + */ + public const HALF_CEILING = 7; + + /** + * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity. + * + * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP. + */ + public const HALF_FLOOR = 8; + + /** + * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor. + * + * Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd; + * behaves as for HALF_DOWN if it's even. + * + * Note that this is the rounding mode that statistically minimizes + * cumulative error when applied repeatedly over a sequence of calculations. + * It is sometimes known as "Banker's rounding", and is chiefly used in the USA. + */ + public const HALF_EVEN = 9; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/ClassLoader.php b/wp-content/plugins/wp-webauthn/vendor/composer/ClassLoader.php new file mode 100644 index 00000000..afef3fa2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/ClassLoader.php @@ -0,0 +1,572 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var ?string */ + private $vendorDir; + + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ + private $missingClasses = array(); + + /** @var ?string */ + private $apcuPrefix; + + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + } + + /** + * @return string[] + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array[] + * @psalm-return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return string[] Array of classname => path + * @psalm-return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + * + * @return void + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private + */ +function includeFile($file) +{ + include $file; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/InstalledVersions.php b/wp-content/plugins/wp-webauthn/vendor/composer/InstalledVersions.php new file mode 100644 index 00000000..41bc143c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/InstalledVersions.php @@ -0,0 +1,352 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/LICENSE b/wp-content/plugins/wp-webauthn/vendor/composer/LICENSE new file mode 100644 index 00000000..f27399a0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/autoload_classmap.php b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_classmap.php new file mode 100644 index 00000000..13811eda --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_classmap.php @@ -0,0 +1,673 @@ + $vendorDir . '/beberlei/assert/lib/Assert/Assert.php', + 'Assert\\Assertion' => $vendorDir . '/beberlei/assert/lib/Assert/Assertion.php', + 'Assert\\AssertionChain' => $vendorDir . '/beberlei/assert/lib/Assert/AssertionChain.php', + 'Assert\\AssertionFailedException' => $vendorDir . '/beberlei/assert/lib/Assert/AssertionFailedException.php', + 'Assert\\InvalidArgumentException' => $vendorDir . '/beberlei/assert/lib/Assert/InvalidArgumentException.php', + 'Assert\\LazyAssertion' => $vendorDir . '/beberlei/assert/lib/Assert/LazyAssertion.php', + 'Assert\\LazyAssertionException' => $vendorDir . '/beberlei/assert/lib/Assert/LazyAssertionException.php', + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Base64Url\\Base64Url' => $vendorDir . '/spomky-labs/base64url/src/Base64Url.php', + 'Brick\\Math\\BigDecimal' => $vendorDir . '/brick/math/src/BigDecimal.php', + 'Brick\\Math\\BigInteger' => $vendorDir . '/brick/math/src/BigInteger.php', + 'Brick\\Math\\BigNumber' => $vendorDir . '/brick/math/src/BigNumber.php', + 'Brick\\Math\\BigRational' => $vendorDir . '/brick/math/src/BigRational.php', + 'Brick\\Math\\Exception\\DivisionByZeroException' => $vendorDir . '/brick/math/src/Exception/DivisionByZeroException.php', + 'Brick\\Math\\Exception\\IntegerOverflowException' => $vendorDir . '/brick/math/src/Exception/IntegerOverflowException.php', + 'Brick\\Math\\Exception\\MathException' => $vendorDir . '/brick/math/src/Exception/MathException.php', + 'Brick\\Math\\Exception\\NegativeNumberException' => $vendorDir . '/brick/math/src/Exception/NegativeNumberException.php', + 'Brick\\Math\\Exception\\NumberFormatException' => $vendorDir . '/brick/math/src/Exception/NumberFormatException.php', + 'Brick\\Math\\Exception\\RoundingNecessaryException' => $vendorDir . '/brick/math/src/Exception/RoundingNecessaryException.php', + 'Brick\\Math\\Internal\\Calculator' => $vendorDir . '/brick/math/src/Internal/Calculator.php', + 'Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/BcMathCalculator.php', + 'Brick\\Math\\Internal\\Calculator\\GmpCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/GmpCalculator.php', + 'Brick\\Math\\Internal\\Calculator\\NativeCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/NativeCalculator.php', + 'Brick\\Math\\RoundingMode' => $vendorDir . '/brick/math/src/RoundingMode.php', + 'CBOR\\AbstractCBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/AbstractCBORObject.php', + 'CBOR\\ByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/ByteStringObject.php', + 'CBOR\\ByteStringWithChunkObject' => $vendorDir . '/spomky-labs/cbor-php/src/ByteStringWithChunkObject.php', + 'CBOR\\CBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/CBORObject.php', + 'CBOR\\Decoder' => $vendorDir . '/spomky-labs/cbor-php/src/Decoder.php', + 'CBOR\\DecoderInterface' => $vendorDir . '/spomky-labs/cbor-php/src/DecoderInterface.php', + 'CBOR\\IndefiniteLengthByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php', + 'CBOR\\IndefiniteLengthListObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php', + 'CBOR\\IndefiniteLengthMapObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php', + 'CBOR\\IndefiniteLengthTextStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php', + 'CBOR\\InfiniteListObject' => $vendorDir . '/spomky-labs/cbor-php/src/InfiniteListObject.php', + 'CBOR\\InfiniteMapObject' => $vendorDir . '/spomky-labs/cbor-php/src/InfiniteMapObject.php', + 'CBOR\\LengthCalculator' => $vendorDir . '/spomky-labs/cbor-php/src/LengthCalculator.php', + 'CBOR\\ListObject' => $vendorDir . '/spomky-labs/cbor-php/src/ListObject.php', + 'CBOR\\MapItem' => $vendorDir . '/spomky-labs/cbor-php/src/MapItem.php', + 'CBOR\\MapObject' => $vendorDir . '/spomky-labs/cbor-php/src/MapObject.php', + 'CBOR\\NegativeIntegerObject' => $vendorDir . '/spomky-labs/cbor-php/src/NegativeIntegerObject.php', + 'CBOR\\Normalizable' => $vendorDir . '/spomky-labs/cbor-php/src/Normalizable.php', + 'CBOR\\OtherObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject.php', + 'CBOR\\OtherObject\\BreakObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/BreakObject.php', + 'CBOR\\OtherObject\\DoublePrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php', + 'CBOR\\OtherObject\\FalseObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/FalseObject.php', + 'CBOR\\OtherObject\\GenericObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/GenericObject.php', + 'CBOR\\OtherObject\\HalfPrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php', + 'CBOR\\OtherObject\\NullObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/NullObject.php', + 'CBOR\\OtherObject\\OtherObjectManager' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php', + 'CBOR\\OtherObject\\OtherObjectManagerInterface' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php', + 'CBOR\\OtherObject\\SimpleObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php', + 'CBOR\\OtherObject\\SinglePrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php', + 'CBOR\\OtherObject\\TrueObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/TrueObject.php', + 'CBOR\\OtherObject\\UndefinedObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php', + 'CBOR\\SignedIntegerObject' => $vendorDir . '/spomky-labs/cbor-php/src/SignedIntegerObject.php', + 'CBOR\\Stream' => $vendorDir . '/spomky-labs/cbor-php/src/Stream.php', + 'CBOR\\StringStream' => $vendorDir . '/spomky-labs/cbor-php/src/StringStream.php', + 'CBOR\\Tag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag.php', + 'CBOR\\TagObject' => $vendorDir . '/spomky-labs/cbor-php/src/TagObject.php', + 'CBOR\\Tag\\Base16EncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php', + 'CBOR\\Tag\\Base64EncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php', + 'CBOR\\Tag\\Base64Tag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64Tag.php', + 'CBOR\\Tag\\Base64UrlEncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php', + 'CBOR\\Tag\\Base64UrlTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php', + 'CBOR\\Tag\\BigFloatTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/BigFloatTag.php', + 'CBOR\\Tag\\CBOREncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php', + 'CBOR\\Tag\\CBORTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/CBORTag.php', + 'CBOR\\Tag\\DatetimeTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/DatetimeTag.php', + 'CBOR\\Tag\\DecimalFractionTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php', + 'CBOR\\Tag\\EpochTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/EpochTag.php', + 'CBOR\\Tag\\GenericTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/GenericTag.php', + 'CBOR\\Tag\\MimeTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/MimeTag.php', + 'CBOR\\Tag\\NegativeBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php', + 'CBOR\\Tag\\PositiveBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/PositiveBigIntegerTag.php', + 'CBOR\\Tag\\TagManager' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManager.php', + 'CBOR\\Tag\\TagManagerInterface' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php', + 'CBOR\\Tag\\TagObjectManager' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagObjectManager.php', + 'CBOR\\Tag\\TimestampTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TimestampTag.php', + 'CBOR\\Tag\\UnsignedBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php', + 'CBOR\\Tag\\UriTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/UriTag.php', + 'CBOR\\TextStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/TextStringObject.php', + 'CBOR\\TextStringWithChunkObject' => $vendorDir . '/spomky-labs/cbor-php/src/TextStringWithChunkObject.php', + 'CBOR\\UnsignedIntegerObject' => $vendorDir . '/spomky-labs/cbor-php/src/UnsignedIntegerObject.php', + 'CBOR\\Utils' => $vendorDir . '/spomky-labs/cbor-php/src/Utils.php', + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'Cose\\Algorithm\\Algorithm' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Algorithm.php', + 'Cose\\Algorithm\\Mac\\HS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS256.php', + 'Cose\\Algorithm\\Mac\\HS256Truncated64' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php', + 'Cose\\Algorithm\\Mac\\HS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS384.php', + 'Cose\\Algorithm\\Mac\\HS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS512.php', + 'Cose\\Algorithm\\Mac\\Hmac' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php', + 'Cose\\Algorithm\\Mac\\Mac' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/Mac.php', + 'Cose\\Algorithm\\Manager' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Manager.php', + 'Cose\\Algorithm\\ManagerFactory' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/ManagerFactory.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ECDSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ECSignature' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES256K' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\ED256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED256.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\ED512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED512.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\Ed25519' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\EdDSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php', + 'Cose\\Algorithm\\Signature\\RSA\\PS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php', + 'Cose\\Algorithm\\Signature\\RSA\\PS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php', + 'Cose\\Algorithm\\Signature\\RSA\\PS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php', + 'Cose\\Algorithm\\Signature\\RSA\\PSSRSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS1' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php', + 'Cose\\Algorithm\\Signature\\RSA\\RSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php', + 'Cose\\Algorithm\\Signature\\Signature' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php', + 'Cose\\Algorithms' => $vendorDir . '/web-auth/cose-lib/src/Algorithms.php', + 'Cose\\BigInteger' => $vendorDir . '/web-auth/cose-lib/src/BigInteger.php', + 'Cose\\Hash' => $vendorDir . '/web-auth/cose-lib/src/Hash.php', + 'Cose\\Key\\Ec2Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Ec2Key.php', + 'Cose\\Key\\Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Key.php', + 'Cose\\Key\\OkpKey' => $vendorDir . '/web-auth/cose-lib/src/Key/OkpKey.php', + 'Cose\\Key\\RsaKey' => $vendorDir . '/web-auth/cose-lib/src/Key/RsaKey.php', + 'Cose\\Key\\SymmetricKey' => $vendorDir . '/web-auth/cose-lib/src/Key/SymmetricKey.php', + 'Cose\\Verifier' => $vendorDir . '/web-auth/cose-lib/src/Verifier.php', + 'FG\\ASN1\\ASNObject' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/ASNObject.php', + 'FG\\ASN1\\AbstractString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/AbstractString.php', + 'FG\\ASN1\\AbstractTime' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/AbstractTime.php', + 'FG\\ASN1\\Base128' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Base128.php', + 'FG\\ASN1\\Composite\\AttributeTypeAndValue' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php', + 'FG\\ASN1\\Composite\\RDNString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php', + 'FG\\ASN1\\Composite\\RelativeDistinguishedName' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php', + 'FG\\ASN1\\Construct' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Construct.php', + 'FG\\ASN1\\Exception\\NotImplementedException' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php', + 'FG\\ASN1\\Exception\\ParserException' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php', + 'FG\\ASN1\\ExplicitlyTaggedObject' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php', + 'FG\\ASN1\\Identifier' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Identifier.php', + 'FG\\ASN1\\OID' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/OID.php', + 'FG\\ASN1\\Parsable' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Parsable.php', + 'FG\\ASN1\\TemplateParser' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/TemplateParser.php', + 'FG\\ASN1\\Universal\\BMPString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php', + 'FG\\ASN1\\Universal\\BitString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php', + 'FG\\ASN1\\Universal\\Boolean' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php', + 'FG\\ASN1\\Universal\\CharacterString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php', + 'FG\\ASN1\\Universal\\Enumerated' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php', + 'FG\\ASN1\\Universal\\GeneralString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php', + 'FG\\ASN1\\Universal\\GeneralizedTime' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php', + 'FG\\ASN1\\Universal\\GraphicString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php', + 'FG\\ASN1\\Universal\\IA5String' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php', + 'FG\\ASN1\\Universal\\Integer' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php', + 'FG\\ASN1\\Universal\\NullObject' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php', + 'FG\\ASN1\\Universal\\NumericString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php', + 'FG\\ASN1\\Universal\\ObjectDescriptor' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php', + 'FG\\ASN1\\Universal\\ObjectIdentifier' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php', + 'FG\\ASN1\\Universal\\OctetString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php', + 'FG\\ASN1\\Universal\\PrintableString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php', + 'FG\\ASN1\\Universal\\RelativeObjectIdentifier' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php', + 'FG\\ASN1\\Universal\\Sequence' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php', + 'FG\\ASN1\\Universal\\Set' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/Set.php', + 'FG\\ASN1\\Universal\\T61String' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php', + 'FG\\ASN1\\Universal\\UTCTime' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php', + 'FG\\ASN1\\Universal\\UTF8String' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php', + 'FG\\ASN1\\Universal\\UniversalString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php', + 'FG\\ASN1\\Universal\\VisibleString' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php', + 'FG\\ASN1\\UnknownConstructedObject' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php', + 'FG\\ASN1\\UnknownObject' => $vendorDir . '/fgrosse/phpasn1/lib/ASN1/UnknownObject.php', + 'FG\\Utility\\BigInteger' => $vendorDir . '/fgrosse/phpasn1/lib/Utility/BigInteger.php', + 'FG\\Utility\\BigIntegerBcmath' => $vendorDir . '/fgrosse/phpasn1/lib/Utility/BigIntegerBcmath.php', + 'FG\\Utility\\BigIntegerGmp' => $vendorDir . '/fgrosse/phpasn1/lib/Utility/BigIntegerGmp.php', + 'FG\\X509\\AlgorithmIdentifier' => $vendorDir . '/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php', + 'FG\\X509\\CSR\\Attributes' => $vendorDir . '/fgrosse/phpasn1/lib/X509/CSR/Attributes.php', + 'FG\\X509\\CSR\\CSR' => $vendorDir . '/fgrosse/phpasn1/lib/X509/CSR/CSR.php', + 'FG\\X509\\CertificateExtensions' => $vendorDir . '/fgrosse/phpasn1/lib/X509/CertificateExtensions.php', + 'FG\\X509\\CertificateSubject' => $vendorDir . '/fgrosse/phpasn1/lib/X509/CertificateSubject.php', + 'FG\\X509\\PrivateKey' => $vendorDir . '/fgrosse/phpasn1/lib/X509/PrivateKey.php', + 'FG\\X509\\PublicKey' => $vendorDir . '/fgrosse/phpasn1/lib/X509/PublicKey.php', + 'FG\\X509\\SAN\\DNSName' => $vendorDir . '/fgrosse/phpasn1/lib/X509/SAN/DNSName.php', + 'FG\\X509\\SAN\\IPAddress' => $vendorDir . '/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php', + 'FG\\X509\\SAN\\SubjectAlternativeNames' => $vendorDir . '/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php', + 'Http\\Message\\MessageFactory' => $vendorDir . '/php-http/message-factory/src/MessageFactory.php', + 'Http\\Message\\RequestFactory' => $vendorDir . '/php-http/message-factory/src/RequestFactory.php', + 'Http\\Message\\ResponseFactory' => $vendorDir . '/php-http/message-factory/src/ResponseFactory.php', + 'Http\\Message\\StreamFactory' => $vendorDir . '/php-http/message-factory/src/StreamFactory.php', + 'Http\\Message\\UriFactory' => $vendorDir . '/php-http/message-factory/src/UriFactory.php', + 'Jose\\Component\\Core\\Algorithm' => $vendorDir . '/web-token/jwt-core/Algorithm.php', + 'Jose\\Component\\Core\\AlgorithmManager' => $vendorDir . '/web-token/jwt-core/AlgorithmManager.php', + 'Jose\\Component\\Core\\AlgorithmManagerFactory' => $vendorDir . '/web-token/jwt-core/AlgorithmManagerFactory.php', + 'Jose\\Component\\Core\\JWK' => $vendorDir . '/web-token/jwt-core/JWK.php', + 'Jose\\Component\\Core\\JWKSet' => $vendorDir . '/web-token/jwt-core/JWKSet.php', + 'Jose\\Component\\Core\\JWT' => $vendorDir . '/web-token/jwt-core/JWT.php', + 'Jose\\Component\\Core\\Util\\BigInteger' => $vendorDir . '/web-token/jwt-core/Util/BigInteger.php', + 'Jose\\Component\\Core\\Util\\ECKey' => $vendorDir . '/web-token/jwt-core/Util/ECKey.php', + 'Jose\\Component\\Core\\Util\\ECSignature' => $vendorDir . '/web-token/jwt-core/Util/ECSignature.php', + 'Jose\\Component\\Core\\Util\\Hash' => $vendorDir . '/web-token/jwt-core/Util/Hash.php', + 'Jose\\Component\\Core\\Util\\JsonConverter' => $vendorDir . '/web-token/jwt-core/Util/JsonConverter.php', + 'Jose\\Component\\Core\\Util\\KeyChecker' => $vendorDir . '/web-token/jwt-core/Util/KeyChecker.php', + 'Jose\\Component\\Core\\Util\\RSAKey' => $vendorDir . '/web-token/jwt-core/Util/RSAKey.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\AlgorithmAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/AlgorithmAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ES256KeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/ES256KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ES384KeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/ES384KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ES512KeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/ES512KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\HS256KeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/HS256KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\HS384KeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/HS384KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\HS512KeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/HS512KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeyAnalyzerManager' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzerManager.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeyIdentifierAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/KeyIdentifierAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeysetAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeysetAnalyzerManager' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzerManager.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\Message' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/Message.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\MessageBag' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/MessageBag.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\MixedKeyTypes' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/MixedKeyTypes.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\MixedPublicAndPrivateKeys' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/MixedPublicAndPrivateKeys.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\NoneAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/NoneAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\OctAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/OctAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\RsaAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/RsaAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\UsageAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/UsageAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ZxcvbnKeyAnalyzer' => $vendorDir . '/web-token/jwt-key-mgmt/Analyzer/ZxcvbnKeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\JKUFactory' => $vendorDir . '/web-token/jwt-key-mgmt/JKUFactory.php', + 'Jose\\Component\\KeyManagement\\JWKFactory' => $vendorDir . '/web-token/jwt-key-mgmt/JWKFactory.php', + 'Jose\\Component\\KeyManagement\\KeyConverter\\ECKey' => $vendorDir . '/web-token/jwt-key-mgmt/KeyConverter/ECKey.php', + 'Jose\\Component\\KeyManagement\\KeyConverter\\KeyConverter' => $vendorDir . '/web-token/jwt-key-mgmt/KeyConverter/KeyConverter.php', + 'Jose\\Component\\KeyManagement\\KeyConverter\\RSAKey' => $vendorDir . '/web-token/jwt-key-mgmt/KeyConverter/RSAKey.php', + 'Jose\\Component\\KeyManagement\\UrlKeySetFactory' => $vendorDir . '/web-token/jwt-key-mgmt/UrlKeySetFactory.php', + 'Jose\\Component\\KeyManagement\\X5UFactory' => $vendorDir . '/web-token/jwt-key-mgmt/X5UFactory.php', + 'Jose\\Component\\Signature\\Algorithm\\ECDSA' => $vendorDir . '/web-token/jwt-signature-algorithm-ecdsa/ECDSA.php', + 'Jose\\Component\\Signature\\Algorithm\\ES256' => $vendorDir . '/web-token/jwt-signature-algorithm-ecdsa/ES256.php', + 'Jose\\Component\\Signature\\Algorithm\\ES384' => $vendorDir . '/web-token/jwt-signature-algorithm-ecdsa/ES384.php', + 'Jose\\Component\\Signature\\Algorithm\\ES512' => $vendorDir . '/web-token/jwt-signature-algorithm-ecdsa/ES512.php', + 'Jose\\Component\\Signature\\Algorithm\\EdDSA' => $vendorDir . '/web-token/jwt-signature-algorithm-eddsa/EdDSA.php', + 'Jose\\Component\\Signature\\Algorithm\\MacAlgorithm' => $vendorDir . '/web-token/jwt-signature/Algorithm/MacAlgorithm.php', + 'Jose\\Component\\Signature\\Algorithm\\PS256' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/PS256.php', + 'Jose\\Component\\Signature\\Algorithm\\PS384' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/PS384.php', + 'Jose\\Component\\Signature\\Algorithm\\PS512' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/PS512.php', + 'Jose\\Component\\Signature\\Algorithm\\RS256' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/RS256.php', + 'Jose\\Component\\Signature\\Algorithm\\RS384' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/RS384.php', + 'Jose\\Component\\Signature\\Algorithm\\RS512' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/RS512.php', + 'Jose\\Component\\Signature\\Algorithm\\RSA' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/RSA.php', + 'Jose\\Component\\Signature\\Algorithm\\RSAPKCS1' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/RSAPKCS1.php', + 'Jose\\Component\\Signature\\Algorithm\\RSAPSS' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/RSAPSS.php', + 'Jose\\Component\\Signature\\Algorithm\\SignatureAlgorithm' => $vendorDir . '/web-token/jwt-signature/Algorithm/SignatureAlgorithm.php', + 'Jose\\Component\\Signature\\Algorithm\\Util\\RSA' => $vendorDir . '/web-token/jwt-signature-algorithm-rsa/Util/RSA.php', + 'Jose\\Component\\Signature\\JWS' => $vendorDir . '/web-token/jwt-signature/JWS.php', + 'Jose\\Component\\Signature\\JWSBuilder' => $vendorDir . '/web-token/jwt-signature/JWSBuilder.php', + 'Jose\\Component\\Signature\\JWSBuilderFactory' => $vendorDir . '/web-token/jwt-signature/JWSBuilderFactory.php', + 'Jose\\Component\\Signature\\JWSLoader' => $vendorDir . '/web-token/jwt-signature/JWSLoader.php', + 'Jose\\Component\\Signature\\JWSLoaderFactory' => $vendorDir . '/web-token/jwt-signature/JWSLoaderFactory.php', + 'Jose\\Component\\Signature\\JWSTokenSupport' => $vendorDir . '/web-token/jwt-signature/JWSTokenSupport.php', + 'Jose\\Component\\Signature\\JWSVerifier' => $vendorDir . '/web-token/jwt-signature/JWSVerifier.php', + 'Jose\\Component\\Signature\\JWSVerifierFactory' => $vendorDir . '/web-token/jwt-signature/JWSVerifierFactory.php', + 'Jose\\Component\\Signature\\Serializer\\CompactSerializer' => $vendorDir . '/web-token/jwt-signature/Serializer/CompactSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JSONFlattenedSerializer' => $vendorDir . '/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JSONGeneralSerializer' => $vendorDir . '/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JWSSerializer' => $vendorDir . '/web-token/jwt-signature/Serializer/JWSSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JWSSerializerManager' => $vendorDir . '/web-token/jwt-signature/Serializer/JWSSerializerManager.php', + 'Jose\\Component\\Signature\\Serializer\\JWSSerializerManagerFactory' => $vendorDir . '/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php', + 'Jose\\Component\\Signature\\Serializer\\Serializer' => $vendorDir . '/web-token/jwt-signature/Serializer/Serializer.php', + 'Jose\\Component\\Signature\\Signature' => $vendorDir . '/web-token/jwt-signature/Signature.php', + 'League\\Uri\\Contracts\\AuthorityInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/AuthorityInterface.php', + 'League\\Uri\\Contracts\\DataPathInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/DataPathInterface.php', + 'League\\Uri\\Contracts\\DomainHostInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/DomainHostInterface.php', + 'League\\Uri\\Contracts\\FragmentInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/FragmentInterface.php', + 'League\\Uri\\Contracts\\HostInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/HostInterface.php', + 'League\\Uri\\Contracts\\IpHostInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/IpHostInterface.php', + 'League\\Uri\\Contracts\\PathInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/PathInterface.php', + 'League\\Uri\\Contracts\\PortInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/PortInterface.php', + 'League\\Uri\\Contracts\\QueryInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/QueryInterface.php', + 'League\\Uri\\Contracts\\SegmentedPathInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php', + 'League\\Uri\\Contracts\\UriComponentInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/UriComponentInterface.php', + 'League\\Uri\\Contracts\\UriException' => $vendorDir . '/league/uri-interfaces/src/Contracts/UriException.php', + 'League\\Uri\\Contracts\\UriInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/UriInterface.php', + 'League\\Uri\\Contracts\\UserInfoInterface' => $vendorDir . '/league/uri-interfaces/src/Contracts/UserInfoInterface.php', + 'League\\Uri\\Exceptions\\FileinfoSupportMissing' => $vendorDir . '/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php', + 'League\\Uri\\Exceptions\\IdnSupportMissing' => $vendorDir . '/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php', + 'League\\Uri\\Exceptions\\IdnaConversionFailed' => $vendorDir . '/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php', + 'League\\Uri\\Exceptions\\SyntaxError' => $vendorDir . '/league/uri-interfaces/src/Exceptions/SyntaxError.php', + 'League\\Uri\\Exceptions\\TemplateCanNotBeExpanded' => $vendorDir . '/league/uri/src/Exceptions/TemplateCanNotBeExpanded.php', + 'League\\Uri\\Http' => $vendorDir . '/league/uri/src/Http.php', + 'League\\Uri\\HttpFactory' => $vendorDir . '/league/uri/src/HttpFactory.php', + 'League\\Uri\\Idna\\Idna' => $vendorDir . '/league/uri-interfaces/src/Idna/Idna.php', + 'League\\Uri\\Idna\\IdnaInfo' => $vendorDir . '/league/uri-interfaces/src/Idna/IdnaInfo.php', + 'League\\Uri\\Uri' => $vendorDir . '/league/uri/src/Uri.php', + 'League\\Uri\\UriInfo' => $vendorDir . '/league/uri/src/UriInfo.php', + 'League\\Uri\\UriResolver' => $vendorDir . '/league/uri/src/UriResolver.php', + 'League\\Uri\\UriString' => $vendorDir . '/league/uri/src/UriString.php', + 'League\\Uri\\UriTemplate' => $vendorDir . '/league/uri/src/UriTemplate.php', + 'League\\Uri\\UriTemplate\\Expression' => $vendorDir . '/league/uri/src/UriTemplate/Expression.php', + 'League\\Uri\\UriTemplate\\Template' => $vendorDir . '/league/uri/src/UriTemplate/Template.php', + 'League\\Uri\\UriTemplate\\VarSpecifier' => $vendorDir . '/league/uri/src/UriTemplate/VarSpecifier.php', + 'League\\Uri\\UriTemplate\\VariableBag' => $vendorDir . '/league/uri/src/UriTemplate/VariableBag.php', + 'Nyholm\\Psr7Server\\ServerRequestCreator' => $vendorDir . '/nyholm/psr7-server/src/ServerRequestCreator.php', + 'Nyholm\\Psr7Server\\ServerRequestCreatorInterface' => $vendorDir . '/nyholm/psr7-server/src/ServerRequestCreatorInterface.php', + 'Nyholm\\Psr7\\Factory\\HttplugFactory' => $vendorDir . '/nyholm/psr7/src/Factory/HttplugFactory.php', + 'Nyholm\\Psr7\\Factory\\Psr17Factory' => $vendorDir . '/nyholm/psr7/src/Factory/Psr17Factory.php', + 'Nyholm\\Psr7\\MessageTrait' => $vendorDir . '/nyholm/psr7/src/MessageTrait.php', + 'Nyholm\\Psr7\\Request' => $vendorDir . '/nyholm/psr7/src/Request.php', + 'Nyholm\\Psr7\\RequestTrait' => $vendorDir . '/nyholm/psr7/src/RequestTrait.php', + 'Nyholm\\Psr7\\Response' => $vendorDir . '/nyholm/psr7/src/Response.php', + 'Nyholm\\Psr7\\ServerRequest' => $vendorDir . '/nyholm/psr7/src/ServerRequest.php', + 'Nyholm\\Psr7\\Stream' => $vendorDir . '/nyholm/psr7/src/Stream.php', + 'Nyholm\\Psr7\\UploadedFile' => $vendorDir . '/nyholm/psr7/src/UploadedFile.php', + 'Nyholm\\Psr7\\Uri' => $vendorDir . '/nyholm/psr7/src/Uri.php', + 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'Psr\\Http\\Client\\ClientExceptionInterface' => $vendorDir . '/psr/http-client/src/ClientExceptionInterface.php', + 'Psr\\Http\\Client\\ClientInterface' => $vendorDir . '/psr/http-client/src/ClientInterface.php', + 'Psr\\Http\\Client\\NetworkExceptionInterface' => $vendorDir . '/psr/http-client/src/NetworkExceptionInterface.php', + 'Psr\\Http\\Client\\RequestExceptionInterface' => $vendorDir . '/psr/http-client/src/RequestExceptionInterface.php', + 'Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php', + 'Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/RequestFactoryInterface.php', + 'Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php', + 'Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/psr/http-factory/src/ResponseFactoryInterface.php', + 'Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php', + 'Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/ServerRequestFactoryInterface.php', + 'Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php', + 'Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/psr/http-factory/src/StreamFactoryInterface.php', + 'Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php', + 'Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/psr/http-factory/src/UploadedFileFactoryInterface.php', + 'Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php', + 'Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/psr/http-factory/src/UriFactoryInterface.php', + 'Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php', + 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php', + 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php', + 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php', + 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php', + 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php', + 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', + 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', + 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/DummyTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', + 'Ramsey\\Collection\\AbstractArray' => $vendorDir . '/ramsey/collection/src/AbstractArray.php', + 'Ramsey\\Collection\\AbstractCollection' => $vendorDir . '/ramsey/collection/src/AbstractCollection.php', + 'Ramsey\\Collection\\AbstractSet' => $vendorDir . '/ramsey/collection/src/AbstractSet.php', + 'Ramsey\\Collection\\ArrayInterface' => $vendorDir . '/ramsey/collection/src/ArrayInterface.php', + 'Ramsey\\Collection\\Collection' => $vendorDir . '/ramsey/collection/src/Collection.php', + 'Ramsey\\Collection\\CollectionInterface' => $vendorDir . '/ramsey/collection/src/CollectionInterface.php', + 'Ramsey\\Collection\\DoubleEndedQueue' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueue.php', + 'Ramsey\\Collection\\DoubleEndedQueueInterface' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueueInterface.php', + 'Ramsey\\Collection\\Exception\\CollectionMismatchException' => $vendorDir . '/ramsey/collection/src/Exception/CollectionMismatchException.php', + 'Ramsey\\Collection\\Exception\\InvalidArgumentException' => $vendorDir . '/ramsey/collection/src/Exception/InvalidArgumentException.php', + 'Ramsey\\Collection\\Exception\\InvalidSortOrderException' => $vendorDir . '/ramsey/collection/src/Exception/InvalidSortOrderException.php', + 'Ramsey\\Collection\\Exception\\NoSuchElementException' => $vendorDir . '/ramsey/collection/src/Exception/NoSuchElementException.php', + 'Ramsey\\Collection\\Exception\\OutOfBoundsException' => $vendorDir . '/ramsey/collection/src/Exception/OutOfBoundsException.php', + 'Ramsey\\Collection\\Exception\\UnsupportedOperationException' => $vendorDir . '/ramsey/collection/src/Exception/UnsupportedOperationException.php', + 'Ramsey\\Collection\\Exception\\ValueExtractionException' => $vendorDir . '/ramsey/collection/src/Exception/ValueExtractionException.php', + 'Ramsey\\Collection\\GenericArray' => $vendorDir . '/ramsey/collection/src/GenericArray.php', + 'Ramsey\\Collection\\Map\\AbstractMap' => $vendorDir . '/ramsey/collection/src/Map/AbstractMap.php', + 'Ramsey\\Collection\\Map\\AbstractTypedMap' => $vendorDir . '/ramsey/collection/src/Map/AbstractTypedMap.php', + 'Ramsey\\Collection\\Map\\AssociativeArrayMap' => $vendorDir . '/ramsey/collection/src/Map/AssociativeArrayMap.php', + 'Ramsey\\Collection\\Map\\MapInterface' => $vendorDir . '/ramsey/collection/src/Map/MapInterface.php', + 'Ramsey\\Collection\\Map\\NamedParameterMap' => $vendorDir . '/ramsey/collection/src/Map/NamedParameterMap.php', + 'Ramsey\\Collection\\Map\\TypedMap' => $vendorDir . '/ramsey/collection/src/Map/TypedMap.php', + 'Ramsey\\Collection\\Map\\TypedMapInterface' => $vendorDir . '/ramsey/collection/src/Map/TypedMapInterface.php', + 'Ramsey\\Collection\\Queue' => $vendorDir . '/ramsey/collection/src/Queue.php', + 'Ramsey\\Collection\\QueueInterface' => $vendorDir . '/ramsey/collection/src/QueueInterface.php', + 'Ramsey\\Collection\\Set' => $vendorDir . '/ramsey/collection/src/Set.php', + 'Ramsey\\Collection\\Tool\\TypeTrait' => $vendorDir . '/ramsey/collection/src/Tool/TypeTrait.php', + 'Ramsey\\Collection\\Tool\\ValueExtractorTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueExtractorTrait.php', + 'Ramsey\\Collection\\Tool\\ValueToStringTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueToStringTrait.php', + 'Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php', + 'Ramsey\\Uuid\\Builder\\BuilderCollection' => $vendorDir . '/ramsey/uuid/src/Builder/BuilderCollection.php', + 'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', + 'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', + 'Ramsey\\Uuid\\Builder\\FallbackBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/FallbackBuilder.php', + 'Ramsey\\Uuid\\Builder\\UuidBuilderInterface' => $vendorDir . '/ramsey/uuid/src/Builder/UuidBuilderInterface.php', + 'Ramsey\\Uuid\\Codec\\CodecInterface' => $vendorDir . '/ramsey/uuid/src/Codec/CodecInterface.php', + 'Ramsey\\Uuid\\Codec\\GuidStringCodec' => $vendorDir . '/ramsey/uuid/src/Codec/GuidStringCodec.php', + 'Ramsey\\Uuid\\Codec\\OrderedTimeCodec' => $vendorDir . '/ramsey/uuid/src/Codec/OrderedTimeCodec.php', + 'Ramsey\\Uuid\\Codec\\StringCodec' => $vendorDir . '/ramsey/uuid/src/Codec/StringCodec.php', + 'Ramsey\\Uuid\\Codec\\TimestampFirstCombCodec' => $vendorDir . '/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php', + 'Ramsey\\Uuid\\Codec\\TimestampLastCombCodec' => $vendorDir . '/ramsey/uuid/src/Codec/TimestampLastCombCodec.php', + 'Ramsey\\Uuid\\Converter\\NumberConverterInterface' => $vendorDir . '/ramsey/uuid/src/Converter/NumberConverterInterface.php', + 'Ramsey\\Uuid\\Converter\\Number\\BigNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/BigNumberConverter.php', + 'Ramsey\\Uuid\\Converter\\Number\\DegradedNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php', + 'Ramsey\\Uuid\\Converter\\Number\\GenericNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php', + 'Ramsey\\Uuid\\Converter\\TimeConverterInterface' => $vendorDir . '/ramsey/uuid/src/Converter/TimeConverterInterface.php', + 'Ramsey\\Uuid\\Converter\\Time\\BigNumberTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php', + 'Ramsey\\Uuid\\Converter\\Time\\DegradedTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php', + 'Ramsey\\Uuid\\Converter\\Time\\GenericTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php', + 'Ramsey\\Uuid\\Converter\\Time\\PhpTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php', + 'Ramsey\\Uuid\\DegradedUuid' => $vendorDir . '/ramsey/uuid/src/DegradedUuid.php', + 'Ramsey\\Uuid\\DeprecatedUuidInterface' => $vendorDir . '/ramsey/uuid/src/DeprecatedUuidInterface.php', + 'Ramsey\\Uuid\\DeprecatedUuidMethodsTrait' => $vendorDir . '/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php', + 'Ramsey\\Uuid\\Exception\\BuilderNotFoundException' => $vendorDir . '/ramsey/uuid/src/Exception/BuilderNotFoundException.php', + 'Ramsey\\Uuid\\Exception\\DateTimeException' => $vendorDir . '/ramsey/uuid/src/Exception/DateTimeException.php', + 'Ramsey\\Uuid\\Exception\\DceSecurityException' => $vendorDir . '/ramsey/uuid/src/Exception/DceSecurityException.php', + 'Ramsey\\Uuid\\Exception\\InvalidArgumentException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidArgumentException.php', + 'Ramsey\\Uuid\\Exception\\InvalidBytesException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidBytesException.php', + 'Ramsey\\Uuid\\Exception\\InvalidUuidStringException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidUuidStringException.php', + 'Ramsey\\Uuid\\Exception\\NameException' => $vendorDir . '/ramsey/uuid/src/Exception/NameException.php', + 'Ramsey\\Uuid\\Exception\\NodeException' => $vendorDir . '/ramsey/uuid/src/Exception/NodeException.php', + 'Ramsey\\Uuid\\Exception\\RandomSourceException' => $vendorDir . '/ramsey/uuid/src/Exception/RandomSourceException.php', + 'Ramsey\\Uuid\\Exception\\TimeSourceException' => $vendorDir . '/ramsey/uuid/src/Exception/TimeSourceException.php', + 'Ramsey\\Uuid\\Exception\\UnableToBuildUuidException' => $vendorDir . '/ramsey/uuid/src/Exception/UnableToBuildUuidException.php', + 'Ramsey\\Uuid\\Exception\\UnsupportedOperationException' => $vendorDir . '/ramsey/uuid/src/Exception/UnsupportedOperationException.php', + 'Ramsey\\Uuid\\Exception\\UuidExceptionInterface' => $vendorDir . '/ramsey/uuid/src/Exception/UuidExceptionInterface.php', + 'Ramsey\\Uuid\\FeatureSet' => $vendorDir . '/ramsey/uuid/src/FeatureSet.php', + 'Ramsey\\Uuid\\Fields\\FieldsInterface' => $vendorDir . '/ramsey/uuid/src/Fields/FieldsInterface.php', + 'Ramsey\\Uuid\\Fields\\SerializableFieldsTrait' => $vendorDir . '/ramsey/uuid/src/Fields/SerializableFieldsTrait.php', + 'Ramsey\\Uuid\\Generator\\CombGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/CombGenerator.php', + 'Ramsey\\Uuid\\Generator\\DceSecurityGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DceSecurityGenerator.php', + 'Ramsey\\Uuid\\Generator\\DceSecurityGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php', + 'Ramsey\\Uuid\\Generator\\DefaultNameGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DefaultNameGenerator.php', + 'Ramsey\\Uuid\\Generator\\DefaultTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DefaultTimeGenerator.php', + 'Ramsey\\Uuid\\Generator\\NameGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/NameGeneratorFactory.php', + 'Ramsey\\Uuid\\Generator\\NameGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/NameGeneratorInterface.php', + 'Ramsey\\Uuid\\Generator\\PeclUuidNameGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php', + 'Ramsey\\Uuid\\Generator\\PeclUuidRandomGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php', + 'Ramsey\\Uuid\\Generator\\PeclUuidTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php', + 'Ramsey\\Uuid\\Generator\\RandomBytesGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/RandomBytesGenerator.php', + 'Ramsey\\Uuid\\Generator\\RandomGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/RandomGeneratorFactory.php', + 'Ramsey\\Uuid\\Generator\\RandomGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/RandomGeneratorInterface.php', + 'Ramsey\\Uuid\\Generator\\RandomLibAdapter' => $vendorDir . '/ramsey/uuid/src/Generator/RandomLibAdapter.php', + 'Ramsey\\Uuid\\Generator\\TimeGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/TimeGeneratorFactory.php', + 'Ramsey\\Uuid\\Generator\\TimeGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/TimeGeneratorInterface.php', + 'Ramsey\\Uuid\\Guid\\Fields' => $vendorDir . '/ramsey/uuid/src/Guid/Fields.php', + 'Ramsey\\Uuid\\Guid\\Guid' => $vendorDir . '/ramsey/uuid/src/Guid/Guid.php', + 'Ramsey\\Uuid\\Guid\\GuidBuilder' => $vendorDir . '/ramsey/uuid/src/Guid/GuidBuilder.php', + 'Ramsey\\Uuid\\Lazy\\LazyUuidFromString' => $vendorDir . '/ramsey/uuid/src/Lazy/LazyUuidFromString.php', + 'Ramsey\\Uuid\\Math\\BrickMathCalculator' => $vendorDir . '/ramsey/uuid/src/Math/BrickMathCalculator.php', + 'Ramsey\\Uuid\\Math\\CalculatorInterface' => $vendorDir . '/ramsey/uuid/src/Math/CalculatorInterface.php', + 'Ramsey\\Uuid\\Math\\RoundingMode' => $vendorDir . '/ramsey/uuid/src/Math/RoundingMode.php', + 'Ramsey\\Uuid\\Nonstandard\\Fields' => $vendorDir . '/ramsey/uuid/src/Nonstandard/Fields.php', + 'Ramsey\\Uuid\\Nonstandard\\Uuid' => $vendorDir . '/ramsey/uuid/src/Nonstandard/Uuid.php', + 'Ramsey\\Uuid\\Nonstandard\\UuidBuilder' => $vendorDir . '/ramsey/uuid/src/Nonstandard/UuidBuilder.php', + 'Ramsey\\Uuid\\Nonstandard\\UuidV6' => $vendorDir . '/ramsey/uuid/src/Nonstandard/UuidV6.php', + 'Ramsey\\Uuid\\Provider\\DceSecurityProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php', + 'Ramsey\\Uuid\\Provider\\Dce\\SystemDceSecurityProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php', + 'Ramsey\\Uuid\\Provider\\NodeProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/NodeProviderInterface.php', + 'Ramsey\\Uuid\\Provider\\Node\\FallbackNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\Node\\NodeProviderCollection' => $vendorDir . '/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php', + 'Ramsey\\Uuid\\Provider\\Node\\RandomNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\Node\\StaticNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\Node\\SystemNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\TimeProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/TimeProviderInterface.php', + 'Ramsey\\Uuid\\Provider\\Time\\FixedTimeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php', + 'Ramsey\\Uuid\\Provider\\Time\\SystemTimeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php', + 'Ramsey\\Uuid\\Rfc4122\\Fields' => $vendorDir . '/ramsey/uuid/src/Rfc4122/Fields.php', + 'Ramsey\\Uuid\\Rfc4122\\FieldsInterface' => $vendorDir . '/ramsey/uuid/src/Rfc4122/FieldsInterface.php', + 'Ramsey\\Uuid\\Rfc4122\\NilTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/NilTrait.php', + 'Ramsey\\Uuid\\Rfc4122\\NilUuid' => $vendorDir . '/ramsey/uuid/src/Rfc4122/NilUuid.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidBuilder' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidBuilder.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidInterface' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidInterface.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV1' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV1.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV2' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV2.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV3' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV3.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV4' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV4.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV5' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV5.php', + 'Ramsey\\Uuid\\Rfc4122\\Validator' => $vendorDir . '/ramsey/uuid/src/Rfc4122/Validator.php', + 'Ramsey\\Uuid\\Rfc4122\\VariantTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/VariantTrait.php', + 'Ramsey\\Uuid\\Rfc4122\\VersionTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/VersionTrait.php', + 'Ramsey\\Uuid\\Type\\Decimal' => $vendorDir . '/ramsey/uuid/src/Type/Decimal.php', + 'Ramsey\\Uuid\\Type\\Hexadecimal' => $vendorDir . '/ramsey/uuid/src/Type/Hexadecimal.php', + 'Ramsey\\Uuid\\Type\\Integer' => $vendorDir . '/ramsey/uuid/src/Type/Integer.php', + 'Ramsey\\Uuid\\Type\\NumberInterface' => $vendorDir . '/ramsey/uuid/src/Type/NumberInterface.php', + 'Ramsey\\Uuid\\Type\\Time' => $vendorDir . '/ramsey/uuid/src/Type/Time.php', + 'Ramsey\\Uuid\\Type\\TypeInterface' => $vendorDir . '/ramsey/uuid/src/Type/TypeInterface.php', + 'Ramsey\\Uuid\\Uuid' => $vendorDir . '/ramsey/uuid/src/Uuid.php', + 'Ramsey\\Uuid\\UuidFactory' => $vendorDir . '/ramsey/uuid/src/UuidFactory.php', + 'Ramsey\\Uuid\\UuidFactoryInterface' => $vendorDir . '/ramsey/uuid/src/UuidFactoryInterface.php', + 'Ramsey\\Uuid\\UuidInterface' => $vendorDir . '/ramsey/uuid/src/UuidInterface.php', + 'Ramsey\\Uuid\\Validator\\GenericValidator' => $vendorDir . '/ramsey/uuid/src/Validator/GenericValidator.php', + 'Ramsey\\Uuid\\Validator\\ValidatorInterface' => $vendorDir . '/ramsey/uuid/src/Validator/ValidatorInterface.php', + 'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', + 'Safe\\DateTime' => $vendorDir . '/thecodingmachine/safe/lib/DateTime.php', + 'Safe\\DateTimeImmutable' => $vendorDir . '/thecodingmachine/safe/lib/DateTimeImmutable.php', + 'Safe\\Exceptions\\ApacheException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ApacheException.php', + 'Safe\\Exceptions\\ApcException' => $vendorDir . '/thecodingmachine/safe/deprecated/Exceptions/ApcException.php', + 'Safe\\Exceptions\\ApcuException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ApcuException.php', + 'Safe\\Exceptions\\ArrayException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ArrayException.php', + 'Safe\\Exceptions\\Bzip2Exception' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/Bzip2Exception.php', + 'Safe\\Exceptions\\CalendarException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/CalendarException.php', + 'Safe\\Exceptions\\ClassobjException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ClassobjException.php', + 'Safe\\Exceptions\\ComException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ComException.php', + 'Safe\\Exceptions\\CubridException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/CubridException.php', + 'Safe\\Exceptions\\CurlException' => $vendorDir . '/thecodingmachine/safe/lib/Exceptions/CurlException.php', + 'Safe\\Exceptions\\DatetimeException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/DatetimeException.php', + 'Safe\\Exceptions\\DirException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/DirException.php', + 'Safe\\Exceptions\\EioException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/EioException.php', + 'Safe\\Exceptions\\ErrorfuncException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ErrorfuncException.php', + 'Safe\\Exceptions\\ExecException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ExecException.php', + 'Safe\\Exceptions\\FileinfoException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/FileinfoException.php', + 'Safe\\Exceptions\\FilesystemException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/FilesystemException.php', + 'Safe\\Exceptions\\FilterException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/FilterException.php', + 'Safe\\Exceptions\\FpmException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/FpmException.php', + 'Safe\\Exceptions\\FtpException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/FtpException.php', + 'Safe\\Exceptions\\FunchandException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/FunchandException.php', + 'Safe\\Exceptions\\GmpException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/GmpException.php', + 'Safe\\Exceptions\\GnupgException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/GnupgException.php', + 'Safe\\Exceptions\\HashException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/HashException.php', + 'Safe\\Exceptions\\IbaseException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/IbaseException.php', + 'Safe\\Exceptions\\IbmDb2Exception' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/IbmDb2Exception.php', + 'Safe\\Exceptions\\IconvException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/IconvException.php', + 'Safe\\Exceptions\\ImageException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ImageException.php', + 'Safe\\Exceptions\\ImapException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ImapException.php', + 'Safe\\Exceptions\\InfoException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/InfoException.php', + 'Safe\\Exceptions\\IngresiiException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/IngresiiException.php', + 'Safe\\Exceptions\\InotifyException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/InotifyException.php', + 'Safe\\Exceptions\\JsonException' => $vendorDir . '/thecodingmachine/safe/lib/Exceptions/JsonException.php', + 'Safe\\Exceptions\\LdapException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/LdapException.php', + 'Safe\\Exceptions\\LibeventException' => $vendorDir . '/thecodingmachine/safe/deprecated/Exceptions/LibeventException.php', + 'Safe\\Exceptions\\LibxmlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/LibxmlException.php', + 'Safe\\Exceptions\\LzfException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/LzfException.php', + 'Safe\\Exceptions\\MailparseException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MailparseException.php', + 'Safe\\Exceptions\\MbstringException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MbstringException.php', + 'Safe\\Exceptions\\MiscException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MiscException.php', + 'Safe\\Exceptions\\MsqlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MsqlException.php', + 'Safe\\Exceptions\\MssqlException' => $vendorDir . '/thecodingmachine/safe/deprecated/Exceptions/MssqlException.php', + 'Safe\\Exceptions\\MysqlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MysqlException.php', + 'Safe\\Exceptions\\MysqliException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MysqliException.php', + 'Safe\\Exceptions\\MysqlndMsException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MysqlndMsException.php', + 'Safe\\Exceptions\\MysqlndQcException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/MysqlndQcException.php', + 'Safe\\Exceptions\\NetworkException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/NetworkException.php', + 'Safe\\Exceptions\\Oci8Exception' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/Oci8Exception.php', + 'Safe\\Exceptions\\OpcacheException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/OpcacheException.php', + 'Safe\\Exceptions\\OpensslException' => $vendorDir . '/thecodingmachine/safe/lib/Exceptions/OpensslException.php', + 'Safe\\Exceptions\\OutcontrolException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/OutcontrolException.php', + 'Safe\\Exceptions\\PasswordException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/PasswordException.php', + 'Safe\\Exceptions\\PcntlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/PcntlException.php', + 'Safe\\Exceptions\\PcreException' => $vendorDir . '/thecodingmachine/safe/lib/Exceptions/PcreException.php', + 'Safe\\Exceptions\\PdfException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/PdfException.php', + 'Safe\\Exceptions\\PgsqlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/PgsqlException.php', + 'Safe\\Exceptions\\PosixException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/PosixException.php', + 'Safe\\Exceptions\\PsException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/PsException.php', + 'Safe\\Exceptions\\PspellException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/PspellException.php', + 'Safe\\Exceptions\\ReadlineException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ReadlineException.php', + 'Safe\\Exceptions\\RpminfoException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/RpminfoException.php', + 'Safe\\Exceptions\\RrdException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/RrdException.php', + 'Safe\\Exceptions\\SafeExceptionInterface' => $vendorDir . '/thecodingmachine/safe/lib/Exceptions/SafeExceptionInterface.php', + 'Safe\\Exceptions\\SemException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SemException.php', + 'Safe\\Exceptions\\SessionException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SessionException.php', + 'Safe\\Exceptions\\ShmopException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ShmopException.php', + 'Safe\\Exceptions\\SimplexmlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SimplexmlException.php', + 'Safe\\Exceptions\\SocketsException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SocketsException.php', + 'Safe\\Exceptions\\SodiumException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SodiumException.php', + 'Safe\\Exceptions\\SolrException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SolrException.php', + 'Safe\\Exceptions\\SplException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SplException.php', + 'Safe\\Exceptions\\SqlsrvException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SqlsrvException.php', + 'Safe\\Exceptions\\SsdeepException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SsdeepException.php', + 'Safe\\Exceptions\\Ssh2Exception' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/Ssh2Exception.php', + 'Safe\\Exceptions\\StatsException' => $vendorDir . '/thecodingmachine/safe/deprecated/Exceptions/StatsException.php', + 'Safe\\Exceptions\\StreamException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/StreamException.php', + 'Safe\\Exceptions\\StringsException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/StringsException.php', + 'Safe\\Exceptions\\SwooleException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/SwooleException.php', + 'Safe\\Exceptions\\UodbcException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/UodbcException.php', + 'Safe\\Exceptions\\UopzException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/UopzException.php', + 'Safe\\Exceptions\\UrlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/UrlException.php', + 'Safe\\Exceptions\\VarException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/VarException.php', + 'Safe\\Exceptions\\XdiffException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/XdiffException.php', + 'Safe\\Exceptions\\XmlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/XmlException.php', + 'Safe\\Exceptions\\XmlrpcException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/XmlrpcException.php', + 'Safe\\Exceptions\\YamlException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/YamlException.php', + 'Safe\\Exceptions\\YazException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/YazException.php', + 'Safe\\Exceptions\\ZipException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ZipException.php', + 'Safe\\Exceptions\\ZlibException' => $vendorDir . '/thecodingmachine/safe/generated/Exceptions/ZlibException.php', + 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/process/Exception/ExceptionInterface.php', + 'Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/process/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php', + 'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php', + 'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/symfony/process/Exception/ProcessSignaledException.php', + 'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php', + 'Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php', + 'Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/symfony/process/ExecutableFinder.php', + 'Symfony\\Component\\Process\\InputStream' => $vendorDir . '/symfony/process/InputStream.php', + 'Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/symfony/process/PhpExecutableFinder.php', + 'Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/symfony/process/PhpProcess.php', + 'Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/symfony/process/Pipes/AbstractPipes.php', + 'Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/symfony/process/Pipes/PipesInterface.php', + 'Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/symfony/process/Pipes/UnixPipes.php', + 'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Pipes/WindowsPipes.php', + 'Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Process.php', + 'Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/ProcessUtils.php', + 'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php', + 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', + 'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php', + 'Symfony\\Polyfill\\Php81\\Php81' => $vendorDir . '/symfony/polyfill-php81/Php81.php', + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', + 'Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AttestationObject' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php', + 'Webauthn\\AttestationStatement\\AttestationObjectLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php', + 'Webauthn\\AttestationStatement\\AttestationStatement' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php', + 'Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php', + 'Webauthn\\AttestedCredentialData' => $vendorDir . '/web-auth/webauthn-lib/src/AttestedCredentialData.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php', + 'Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php', + 'Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php', + 'Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php', + 'Webauthn\\AuthenticatorAssertionResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php', + 'Webauthn\\AuthenticatorAssertionResponseValidator' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php', + 'Webauthn\\AuthenticatorAttestationResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php', + 'Webauthn\\AuthenticatorAttestationResponseValidator' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php', + 'Webauthn\\AuthenticatorData' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorData.php', + 'Webauthn\\AuthenticatorResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorResponse.php', + 'Webauthn\\AuthenticatorSelectionCriteria' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php', + 'Webauthn\\CertificateChainChecker\\CertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php', + 'Webauthn\\CertificateChainChecker\\OpenSSLCertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/OpenSSLCertificateChainChecker.php', + 'Webauthn\\CertificateToolbox' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateToolbox.php', + 'Webauthn\\CollectedClientData' => $vendorDir . '/web-auth/webauthn-lib/src/CollectedClientData.php', + 'Webauthn\\Counter\\CounterChecker' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php', + 'Webauthn\\Counter\\ThrowExceptionIfInvalid' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php', + 'Webauthn\\Credential' => $vendorDir . '/web-auth/webauthn-lib/src/Credential.php', + 'Webauthn\\MetadataService\\AbstractDescriptor' => $vendorDir . '/web-auth/metadata-service/src/AbstractDescriptor.php', + 'Webauthn\\MetadataService\\AuthenticatorStatus' => $vendorDir . '/web-auth/metadata-service/src/AuthenticatorStatus.php', + 'Webauthn\\MetadataService\\BiometricAccuracyDescriptor' => $vendorDir . '/web-auth/metadata-service/src/BiometricAccuracyDescriptor.php', + 'Webauthn\\MetadataService\\BiometricStatusReport' => $vendorDir . '/web-auth/metadata-service/src/BiometricStatusReport.php', + 'Webauthn\\MetadataService\\CodeAccuracyDescriptor' => $vendorDir . '/web-auth/metadata-service/src/CodeAccuracyDescriptor.php', + 'Webauthn\\MetadataService\\DisplayPNGCharacteristicsDescriptor' => $vendorDir . '/web-auth/metadata-service/src/DisplayPNGCharacteristicsDescriptor.php', + 'Webauthn\\MetadataService\\DistantSingleMetadata' => $vendorDir . '/web-auth/metadata-service/src/DistantSingleMetadata.php', + 'Webauthn\\MetadataService\\EcdaaTrustAnchor' => $vendorDir . '/web-auth/metadata-service/src/EcdaaTrustAnchor.php', + 'Webauthn\\MetadataService\\ExtensionDescriptor' => $vendorDir . '/web-auth/metadata-service/src/ExtensionDescriptor.php', + 'Webauthn\\MetadataService\\MetadataService' => $vendorDir . '/web-auth/metadata-service/src/MetadataService.php', + 'Webauthn\\MetadataService\\MetadataStatement' => $vendorDir . '/web-auth/metadata-service/src/MetadataStatement.php', + 'Webauthn\\MetadataService\\MetadataStatementFetcher' => $vendorDir . '/web-auth/metadata-service/src/MetadataStatementFetcher.php', + 'Webauthn\\MetadataService\\MetadataStatementRepository' => $vendorDir . '/web-auth/metadata-service/src/MetadataStatementRepository.php', + 'Webauthn\\MetadataService\\MetadataTOCPayload' => $vendorDir . '/web-auth/metadata-service/src/MetadataTOCPayload.php', + 'Webauthn\\MetadataService\\MetadataTOCPayloadEntry' => $vendorDir . '/web-auth/metadata-service/src/MetadataTOCPayloadEntry.php', + 'Webauthn\\MetadataService\\PatternAccuracyDescriptor' => $vendorDir . '/web-auth/metadata-service/src/PatternAccuracyDescriptor.php', + 'Webauthn\\MetadataService\\RgbPaletteEntry' => $vendorDir . '/web-auth/metadata-service/src/RgbPaletteEntry.php', + 'Webauthn\\MetadataService\\RogueListEntry' => $vendorDir . '/web-auth/metadata-service/src/RogueListEntry.php', + 'Webauthn\\MetadataService\\SingleMetadata' => $vendorDir . '/web-auth/metadata-service/src/SingleMetadata.php', + 'Webauthn\\MetadataService\\StatusReport' => $vendorDir . '/web-auth/metadata-service/src/StatusReport.php', + 'Webauthn\\MetadataService\\Utils' => $vendorDir . '/web-auth/metadata-service/src/Utils.php', + 'Webauthn\\MetadataService\\VerificationMethodANDCombinations' => $vendorDir . '/web-auth/metadata-service/src/VerificationMethodANDCombinations.php', + 'Webauthn\\MetadataService\\VerificationMethodDescriptor' => $vendorDir . '/web-auth/metadata-service/src/VerificationMethodDescriptor.php', + 'Webauthn\\MetadataService\\Version' => $vendorDir . '/web-auth/metadata-service/src/Version.php', + 'Webauthn\\PublicKeyCredential' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredential.php', + 'Webauthn\\PublicKeyCredentialCreationOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php', + 'Webauthn\\PublicKeyCredentialDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php', + 'Webauthn\\PublicKeyCredentialDescriptorCollection' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php', + 'Webauthn\\PublicKeyCredentialEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php', + 'Webauthn\\PublicKeyCredentialLoader' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php', + 'Webauthn\\PublicKeyCredentialOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php', + 'Webauthn\\PublicKeyCredentialParameters' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php', + 'Webauthn\\PublicKeyCredentialRequestOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php', + 'Webauthn\\PublicKeyCredentialRpEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php', + 'Webauthn\\PublicKeyCredentialSource' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php', + 'Webauthn\\PublicKeyCredentialSourceRepository' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php', + 'Webauthn\\PublicKeyCredentialUserEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php', + 'Webauthn\\Server' => $vendorDir . '/web-auth/webauthn-lib/src/Server.php', + 'Webauthn\\StringStream' => $vendorDir . '/web-auth/webauthn-lib/src/StringStream.php', + 'Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php', + 'Webauthn\\TokenBinding\\SecTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php', + 'Webauthn\\TokenBinding\\TokenBinding' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php', + 'Webauthn\\TokenBinding\\TokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php', + 'Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php', + 'Webauthn\\TrustPath\\CertificateTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php', + 'Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php', + 'Webauthn\\TrustPath\\EmptyTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php', + 'Webauthn\\TrustPath\\TrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php', + 'Webauthn\\TrustPath\\TrustPathLoader' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php', + 'Webauthn\\U2FPublicKey' => $vendorDir . '/web-auth/webauthn-lib/src/U2FPublicKey.php', + 'Webauthn\\Util\\CoseSignatureFixer' => $vendorDir . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php', +); diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/autoload_files.php b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_files.php new file mode 100644 index 00000000..5d68d9a9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_files.php @@ -0,0 +1,103 @@ + $vendorDir . '/beberlei/assert/lib/Assert/functions.php', + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', + '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', + 'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php', + '51fcf4e06c07cc00c920b44bcd900e7a' => $vendorDir . '/thecodingmachine/safe/deprecated/apc.php', + '47f619d9197b36cf5ab70738d7743fe2' => $vendorDir . '/thecodingmachine/safe/deprecated/libevent.php', + 'ea6bb8a12ef9b68f6ada99058e530760' => $vendorDir . '/thecodingmachine/safe/deprecated/mssql.php', + '9a29089eb3ce41a446744c68a00f118c' => $vendorDir . '/thecodingmachine/safe/deprecated/stats.php', + '72243e5536b63e298acb6476f01f1aff' => $vendorDir . '/thecodingmachine/safe/lib/special_cases.php', + '3f648889e687f31c52f949ba8a9d0873' => $vendorDir . '/thecodingmachine/safe/generated/apache.php', + 'eeb4581d958421a4244aaa4167c6a575' => $vendorDir . '/thecodingmachine/safe/generated/apcu.php', + '04cb0b3c1dac5b5ddb23c14e3d66dbe9' => $vendorDir . '/thecodingmachine/safe/generated/array.php', + '450b332a74a9a21e043c5e953485a791' => $vendorDir . '/thecodingmachine/safe/generated/bzip2.php', + '6e9b7954ecfd7cbb9ca239319d1acdb6' => $vendorDir . '/thecodingmachine/safe/generated/calendar.php', + '2c6d7e8bd2de9a272a9d4d43b0a4304a' => $vendorDir . '/thecodingmachine/safe/generated/classobj.php', + '0b8231c1ad0865447c988a4c16b4001f' => $vendorDir . '/thecodingmachine/safe/generated/com.php', + '7643a71fe1c3256058c8fee234cb86e5' => $vendorDir . '/thecodingmachine/safe/generated/cubrid.php', + '68e1365710575942efc1d55000032cee' => $vendorDir . '/thecodingmachine/safe/generated/curl.php', + '02fd26bca803106c5b942a7197c3ad8b' => $vendorDir . '/thecodingmachine/safe/generated/datetime.php', + 'f4817dcbd956cd221b1c31f6fbd5749c' => $vendorDir . '/thecodingmachine/safe/generated/dir.php', + '51c3f2d10ca61a70dbcea0e38d8e902d' => $vendorDir . '/thecodingmachine/safe/generated/eio.php', + '1d34f34327ca3e81535963016e3be2c3' => $vendorDir . '/thecodingmachine/safe/generated/errorfunc.php', + '4fd0ba2d3717b0424d474bebfdafa2b4' => $vendorDir . '/thecodingmachine/safe/generated/exec.php', + '98f4dae054bc7fb19c13be14935cbdd3' => $vendorDir . '/thecodingmachine/safe/generated/fileinfo.php', + '5530ae063ba88323eaf0a07904efdf85' => $vendorDir . '/thecodingmachine/safe/generated/filesystem.php', + '633f4f134975d70e97bddad83348e91a' => $vendorDir . '/thecodingmachine/safe/generated/filter.php', + 'fbd163fc68c5faf73d5ed4002ffd836d' => $vendorDir . '/thecodingmachine/safe/generated/fpm.php', + '21b511999d61411fab0692ff8795bbed' => $vendorDir . '/thecodingmachine/safe/generated/ftp.php', + '85fbd73fc92365cd90526b0ea03cae3a' => $vendorDir . '/thecodingmachine/safe/generated/funchand.php', + '51df9c146e0b7dcbdf358d8abd24dbdc' => $vendorDir . '/thecodingmachine/safe/generated/gmp.php', + '93bb7fe678d7dcfb1322f8e3475a48b0' => $vendorDir . '/thecodingmachine/safe/generated/gnupg.php', + 'c171ba99cf316379ff66468392bf4950' => $vendorDir . '/thecodingmachine/safe/generated/hash.php', + '5ab4aad4c28e468209fbfcceb2e5e6a5' => $vendorDir . '/thecodingmachine/safe/generated/ibase.php', + '4d57409c5e8e576b0c64c08d9d731cfb' => $vendorDir . '/thecodingmachine/safe/generated/ibmDb2.php', + 'eeb246d5403972a9d62106e4a4883496' => $vendorDir . '/thecodingmachine/safe/generated/iconv.php', + 'c28a05f498c01b810a714f7214b7a8da' => $vendorDir . '/thecodingmachine/safe/generated/image.php', + '8063cd92acdf00fd978b5599eb7cc142' => $vendorDir . '/thecodingmachine/safe/generated/imap.php', + '8bd26dbe768e9c9599edad7b198e5446' => $vendorDir . '/thecodingmachine/safe/generated/info.php', + '0c577fe603b029d4b65c84376b15dbd5' => $vendorDir . '/thecodingmachine/safe/generated/ingres-ii.php', + 'd4362910bde43c0f956b52527effd7d4' => $vendorDir . '/thecodingmachine/safe/generated/inotify.php', + '696ba49197d9b55f0428a12bb5a818e1' => $vendorDir . '/thecodingmachine/safe/generated/json.php', + '9818aaa99c8647c63f8ef62b7a368160' => $vendorDir . '/thecodingmachine/safe/generated/ldap.php', + 'bcf523ff2a195eb08e0fbb668ed784d0' => $vendorDir . '/thecodingmachine/safe/generated/libxml.php', + '68be68a9a8b95bb56cab6109ff03bc88' => $vendorDir . '/thecodingmachine/safe/generated/lzf.php', + 'bdca804bb0904ea9f53f328dfc0bb8a5' => $vendorDir . '/thecodingmachine/safe/generated/mailparse.php', + 'b0a3fcac3eaf55445796d6af26b89366' => $vendorDir . '/thecodingmachine/safe/generated/mbstring.php', + '98de16b8db03eb0cb4d318b4402215a6' => $vendorDir . '/thecodingmachine/safe/generated/misc.php', + 'c112440003b56e243b192c11fa9d836e' => $vendorDir . '/thecodingmachine/safe/generated/msql.php', + '7cefd81607cd21b8b3a15656eb6465f5' => $vendorDir . '/thecodingmachine/safe/generated/mysql.php', + 'aaf438b080089c6d0686679cd34aa72e' => $vendorDir . '/thecodingmachine/safe/generated/mysqli.php', + 'df0ef890e9afbf95f3924feb1c7a89f3' => $vendorDir . '/thecodingmachine/safe/generated/mysqlndMs.php', + 'db595fee5972867e45c5327010d78735' => $vendorDir . '/thecodingmachine/safe/generated/mysqlndQc.php', + 'cbac956836b72483dcff1ac39d5c0a0f' => $vendorDir . '/thecodingmachine/safe/generated/network.php', + '6c8f89dfbdc117d7871f572269363f25' => $vendorDir . '/thecodingmachine/safe/generated/oci8.php', + '169a669966a45c06bf55ed029122729b' => $vendorDir . '/thecodingmachine/safe/generated/opcache.php', + 'def61bf4fecd4d4bca7354919cd69302' => $vendorDir . '/thecodingmachine/safe/generated/openssl.php', + '26bb010649a6d32d4120181458aa6ef2' => $vendorDir . '/thecodingmachine/safe/generated/outcontrol.php', + '1212c201fe43c7492a085b2c71505e0f' => $vendorDir . '/thecodingmachine/safe/generated/password.php', + '002ebcb842e2c0d5b7f67fe64cc93158' => $vendorDir . '/thecodingmachine/safe/generated/pcntl.php', + '86df38612982dade72c7085ce7eca81f' => $vendorDir . '/thecodingmachine/safe/generated/pcre.php', + '1cacc3e65f82a473fbd5507c7ce4385d' => $vendorDir . '/thecodingmachine/safe/generated/pdf.php', + '1fc22f445c69ea8706e82fce301c0831' => $vendorDir . '/thecodingmachine/safe/generated/pgsql.php', + 'c70b42561584f7144bff38cd63c4eef3' => $vendorDir . '/thecodingmachine/safe/generated/posix.php', + '9923214639c32ca5173db03a177d3b63' => $vendorDir . '/thecodingmachine/safe/generated/ps.php', + '7e9c3f8eae2b5bf42205c4f1295cb7a7' => $vendorDir . '/thecodingmachine/safe/generated/pspell.php', + '91aa91f6245c349c2e2e88bd0025f199' => $vendorDir . '/thecodingmachine/safe/generated/readline.php', + 'd43773cacb9e5e8e897aa255e32007d1' => $vendorDir . '/thecodingmachine/safe/generated/rpminfo.php', + 'f053a3849e9e8383762b34b91db0320b' => $vendorDir . '/thecodingmachine/safe/generated/rrd.php', + '775b964f72f827a1bf87c65ab5b10800' => $vendorDir . '/thecodingmachine/safe/generated/sem.php', + '816428bd69c29ab5e1ed622af5dca0cd' => $vendorDir . '/thecodingmachine/safe/generated/session.php', + '5093e233bedbefaef0df262bfbab0a5c' => $vendorDir . '/thecodingmachine/safe/generated/shmop.php', + '01352920b0151f17e671266e44b52536' => $vendorDir . '/thecodingmachine/safe/generated/simplexml.php', + 'b080617b1d949683c2e37f8f01dc0e15' => $vendorDir . '/thecodingmachine/safe/generated/sockets.php', + '2708aa182ddcfe6ce27c96acaaa40f69' => $vendorDir . '/thecodingmachine/safe/generated/sodium.php', + 'f1b96cb260a5baeea9a7285cda82a1ec' => $vendorDir . '/thecodingmachine/safe/generated/solr.php', + '3fd8853757d0fe3557c179efb807afeb' => $vendorDir . '/thecodingmachine/safe/generated/spl.php', + '9312ce96a51c846913fcda5f186d58dd' => $vendorDir . '/thecodingmachine/safe/generated/sqlsrv.php', + 'd3eb383ad0b8b962b29dc4afd29d6715' => $vendorDir . '/thecodingmachine/safe/generated/ssdeep.php', + '42a09bc448f441a0b9f9367ea975c0bf' => $vendorDir . '/thecodingmachine/safe/generated/ssh2.php', + 'ef711077d356d1b33ca0b10b67b0be8f' => $vendorDir . '/thecodingmachine/safe/generated/stream.php', + '764b09f6df081cbb2807b97c6ace3866' => $vendorDir . '/thecodingmachine/safe/generated/strings.php', + 'ef241678769fee4a44aaa288f3b78aa1' => $vendorDir . '/thecodingmachine/safe/generated/swoole.php', + '0efc8f6778cba932b9e2a89e28de2452' => $vendorDir . '/thecodingmachine/safe/generated/uodbc.php', + 'd383d32907b98af53ee9208c62204fd0' => $vendorDir . '/thecodingmachine/safe/generated/uopz.php', + '2fd2e4060f7fe772660f002ce38f0b71' => $vendorDir . '/thecodingmachine/safe/generated/url.php', + '782249e03deebeaf57b9991ff5493aa0' => $vendorDir . '/thecodingmachine/safe/generated/var.php', + '344440cd1cd7200fdb4f12af0d3c587f' => $vendorDir . '/thecodingmachine/safe/generated/xdiff.php', + '3599f369219c658a5fb6c4fe66832f62' => $vendorDir . '/thecodingmachine/safe/generated/xml.php', + '7fcd313da9fae337051b091b3492c21b' => $vendorDir . '/thecodingmachine/safe/generated/xmlrpc.php', + 'd668c74cfa92d893b582356733d9a80e' => $vendorDir . '/thecodingmachine/safe/generated/yaml.php', + '4af1dca6db8c527c6eed27bff85ff0e5' => $vendorDir . '/thecodingmachine/safe/generated/yaz.php', + 'fe43ca06499ac37bc2dedd823af71eb5' => $vendorDir . '/thecodingmachine/safe/generated/zip.php', + '356736db98a6834f0a886b8d509b0ecd' => $vendorDir . '/thecodingmachine/safe/generated/zlib.php', +); diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/autoload_namespaces.php b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_namespaces.php new file mode 100644 index 00000000..15a2ff3a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($vendorDir . '/web-auth/metadata-service/src'), + 'Webauthn\\' => array($vendorDir . '/web-auth/webauthn-lib/src'), + 'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'), + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), + 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), + 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), + 'Safe\\' => array($vendorDir . '/thecodingmachine/safe/lib', $vendorDir . '/thecodingmachine/safe/deprecated', $vendorDir . '/thecodingmachine/safe/generated'), + 'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'), + 'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'), + 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'), + 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), + 'Nyholm\\Psr7\\' => array($vendorDir . '/nyholm/psr7/src'), + 'Nyholm\\Psr7Server\\' => array($vendorDir . '/nyholm/psr7-server/src'), + 'League\\Uri\\' => array($vendorDir . '/league/uri-interfaces/src', $vendorDir . '/league/uri/src'), + 'Jose\\Component\\Signature\\Algorithm\\' => array($vendorDir . '/web-token/jwt-signature-algorithm-ecdsa', $vendorDir . '/web-token/jwt-signature-algorithm-eddsa', $vendorDir . '/web-token/jwt-signature-algorithm-rsa'), + 'Jose\\Component\\Signature\\' => array($vendorDir . '/web-token/jwt-signature'), + 'Jose\\Component\\KeyManagement\\' => array($vendorDir . '/web-token/jwt-key-mgmt'), + 'Jose\\Component\\Core\\' => array($vendorDir . '/web-token/jwt-core'), + 'Http\\Message\\' => array($vendorDir . '/php-http/message-factory/src'), + 'FG\\' => array($vendorDir . '/fgrosse/phpasn1/lib'), + 'Cose\\' => array($vendorDir . '/web-auth/cose-lib/src'), + 'CBOR\\' => array($vendorDir . '/spomky-labs/cbor-php/src'), + 'Brick\\Math\\' => array($vendorDir . '/brick/math/src'), + 'Base64Url\\' => array($vendorDir . '/spomky-labs/base64url/src'), + 'Assert\\' => array($vendorDir . '/beberlei/assert/lib/Assert'), +); diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/autoload_real.php b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_real.php new file mode 100644 index 00000000..ccec2823 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_real.php @@ -0,0 +1,55 @@ +register(true); + + $includeFiles = \Composer\Autoload\ComposerStaticInit8c7684b956de574bcb0eefe2be31e0ab::$files; + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequire8c7684b956de574bcb0eefe2be31e0ab($fileIdentifier, $file); + } + + return $loader; + } +} + +/** + * @param string $fileIdentifier + * @param string $file + * @return void + */ +function composerRequire8c7684b956de574bcb0eefe2be31e0ab($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/autoload_static.php b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_static.php new file mode 100644 index 00000000..b485ae14 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/autoload_static.php @@ -0,0 +1,960 @@ + __DIR__ . '/..' . '/beberlei/assert/lib/Assert/functions.php', + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', + '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', + 'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php', + '51fcf4e06c07cc00c920b44bcd900e7a' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/apc.php', + '47f619d9197b36cf5ab70738d7743fe2' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/libevent.php', + 'ea6bb8a12ef9b68f6ada99058e530760' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/mssql.php', + '9a29089eb3ce41a446744c68a00f118c' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/stats.php', + '72243e5536b63e298acb6476f01f1aff' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/special_cases.php', + '3f648889e687f31c52f949ba8a9d0873' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/apache.php', + 'eeb4581d958421a4244aaa4167c6a575' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/apcu.php', + '04cb0b3c1dac5b5ddb23c14e3d66dbe9' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/array.php', + '450b332a74a9a21e043c5e953485a791' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/bzip2.php', + '6e9b7954ecfd7cbb9ca239319d1acdb6' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/calendar.php', + '2c6d7e8bd2de9a272a9d4d43b0a4304a' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/classobj.php', + '0b8231c1ad0865447c988a4c16b4001f' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/com.php', + '7643a71fe1c3256058c8fee234cb86e5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/cubrid.php', + '68e1365710575942efc1d55000032cee' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/curl.php', + '02fd26bca803106c5b942a7197c3ad8b' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/datetime.php', + 'f4817dcbd956cd221b1c31f6fbd5749c' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/dir.php', + '51c3f2d10ca61a70dbcea0e38d8e902d' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/eio.php', + '1d34f34327ca3e81535963016e3be2c3' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/errorfunc.php', + '4fd0ba2d3717b0424d474bebfdafa2b4' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/exec.php', + '98f4dae054bc7fb19c13be14935cbdd3' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/fileinfo.php', + '5530ae063ba88323eaf0a07904efdf85' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/filesystem.php', + '633f4f134975d70e97bddad83348e91a' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/filter.php', + 'fbd163fc68c5faf73d5ed4002ffd836d' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/fpm.php', + '21b511999d61411fab0692ff8795bbed' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ftp.php', + '85fbd73fc92365cd90526b0ea03cae3a' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/funchand.php', + '51df9c146e0b7dcbdf358d8abd24dbdc' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/gmp.php', + '93bb7fe678d7dcfb1322f8e3475a48b0' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/gnupg.php', + 'c171ba99cf316379ff66468392bf4950' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/hash.php', + '5ab4aad4c28e468209fbfcceb2e5e6a5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ibase.php', + '4d57409c5e8e576b0c64c08d9d731cfb' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ibmDb2.php', + 'eeb246d5403972a9d62106e4a4883496' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/iconv.php', + 'c28a05f498c01b810a714f7214b7a8da' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/image.php', + '8063cd92acdf00fd978b5599eb7cc142' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/imap.php', + '8bd26dbe768e9c9599edad7b198e5446' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/info.php', + '0c577fe603b029d4b65c84376b15dbd5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ingres-ii.php', + 'd4362910bde43c0f956b52527effd7d4' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/inotify.php', + '696ba49197d9b55f0428a12bb5a818e1' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/json.php', + '9818aaa99c8647c63f8ef62b7a368160' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ldap.php', + 'bcf523ff2a195eb08e0fbb668ed784d0' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/libxml.php', + '68be68a9a8b95bb56cab6109ff03bc88' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/lzf.php', + 'bdca804bb0904ea9f53f328dfc0bb8a5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/mailparse.php', + 'b0a3fcac3eaf55445796d6af26b89366' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/mbstring.php', + '98de16b8db03eb0cb4d318b4402215a6' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/misc.php', + 'c112440003b56e243b192c11fa9d836e' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/msql.php', + '7cefd81607cd21b8b3a15656eb6465f5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/mysql.php', + 'aaf438b080089c6d0686679cd34aa72e' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/mysqli.php', + 'df0ef890e9afbf95f3924feb1c7a89f3' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/mysqlndMs.php', + 'db595fee5972867e45c5327010d78735' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/mysqlndQc.php', + 'cbac956836b72483dcff1ac39d5c0a0f' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/network.php', + '6c8f89dfbdc117d7871f572269363f25' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/oci8.php', + '169a669966a45c06bf55ed029122729b' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/opcache.php', + 'def61bf4fecd4d4bca7354919cd69302' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/openssl.php', + '26bb010649a6d32d4120181458aa6ef2' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/outcontrol.php', + '1212c201fe43c7492a085b2c71505e0f' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/password.php', + '002ebcb842e2c0d5b7f67fe64cc93158' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/pcntl.php', + '86df38612982dade72c7085ce7eca81f' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/pcre.php', + '1cacc3e65f82a473fbd5507c7ce4385d' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/pdf.php', + '1fc22f445c69ea8706e82fce301c0831' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/pgsql.php', + 'c70b42561584f7144bff38cd63c4eef3' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/posix.php', + '9923214639c32ca5173db03a177d3b63' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ps.php', + '7e9c3f8eae2b5bf42205c4f1295cb7a7' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/pspell.php', + '91aa91f6245c349c2e2e88bd0025f199' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/readline.php', + 'd43773cacb9e5e8e897aa255e32007d1' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/rpminfo.php', + 'f053a3849e9e8383762b34b91db0320b' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/rrd.php', + '775b964f72f827a1bf87c65ab5b10800' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/sem.php', + '816428bd69c29ab5e1ed622af5dca0cd' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/session.php', + '5093e233bedbefaef0df262bfbab0a5c' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/shmop.php', + '01352920b0151f17e671266e44b52536' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/simplexml.php', + 'b080617b1d949683c2e37f8f01dc0e15' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/sockets.php', + '2708aa182ddcfe6ce27c96acaaa40f69' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/sodium.php', + 'f1b96cb260a5baeea9a7285cda82a1ec' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/solr.php', + '3fd8853757d0fe3557c179efb807afeb' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/spl.php', + '9312ce96a51c846913fcda5f186d58dd' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/sqlsrv.php', + 'd3eb383ad0b8b962b29dc4afd29d6715' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ssdeep.php', + '42a09bc448f441a0b9f9367ea975c0bf' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/ssh2.php', + 'ef711077d356d1b33ca0b10b67b0be8f' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/stream.php', + '764b09f6df081cbb2807b97c6ace3866' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/strings.php', + 'ef241678769fee4a44aaa288f3b78aa1' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/swoole.php', + '0efc8f6778cba932b9e2a89e28de2452' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/uodbc.php', + 'd383d32907b98af53ee9208c62204fd0' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/uopz.php', + '2fd2e4060f7fe772660f002ce38f0b71' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/url.php', + '782249e03deebeaf57b9991ff5493aa0' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/var.php', + '344440cd1cd7200fdb4f12af0d3c587f' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/xdiff.php', + '3599f369219c658a5fb6c4fe66832f62' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/xml.php', + '7fcd313da9fae337051b091b3492c21b' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/xmlrpc.php', + 'd668c74cfa92d893b582356733d9a80e' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/yaml.php', + '4af1dca6db8c527c6eed27bff85ff0e5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/yaz.php', + 'fe43ca06499ac37bc2dedd823af71eb5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/zip.php', + '356736db98a6834f0a886b8d509b0ecd' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/zlib.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'W' => + array ( + 'Webauthn\\MetadataService\\' => 25, + 'Webauthn\\' => 9, + ), + 'S' => + array ( + 'Symfony\\Polyfill\\Php81\\' => 23, + 'Symfony\\Polyfill\\Php80\\' => 23, + 'Symfony\\Polyfill\\Ctype\\' => 23, + 'Symfony\\Component\\Process\\' => 26, + 'Safe\\' => 5, + ), + 'R' => + array ( + 'Ramsey\\Uuid\\' => 12, + 'Ramsey\\Collection\\' => 18, + ), + 'P' => + array ( + 'Psr\\Log\\' => 8, + 'Psr\\Http\\Message\\' => 17, + 'Psr\\Http\\Client\\' => 16, + ), + 'N' => + array ( + 'Nyholm\\Psr7\\' => 12, + 'Nyholm\\Psr7Server\\' => 18, + ), + 'L' => + array ( + 'League\\Uri\\' => 11, + ), + 'J' => + array ( + 'Jose\\Component\\Signature\\Algorithm\\' => 35, + 'Jose\\Component\\Signature\\' => 25, + 'Jose\\Component\\KeyManagement\\' => 29, + 'Jose\\Component\\Core\\' => 20, + ), + 'H' => + array ( + 'Http\\Message\\' => 13, + ), + 'F' => + array ( + 'FG\\' => 3, + ), + 'C' => + array ( + 'Cose\\' => 5, + 'CBOR\\' => 5, + ), + 'B' => + array ( + 'Brick\\Math\\' => 11, + 'Base64Url\\' => 10, + ), + 'A' => + array ( + 'Assert\\' => 7, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Webauthn\\MetadataService\\' => + array ( + 0 => __DIR__ . '/..' . '/web-auth/metadata-service/src', + ), + 'Webauthn\\' => + array ( + 0 => __DIR__ . '/..' . '/web-auth/webauthn-lib/src', + ), + 'Symfony\\Polyfill\\Php81\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php81', + ), + 'Symfony\\Polyfill\\Php80\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', + ), + 'Symfony\\Polyfill\\Ctype\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', + ), + 'Symfony\\Component\\Process\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/process', + ), + 'Safe\\' => + array ( + 0 => __DIR__ . '/..' . '/thecodingmachine/safe/lib', + 1 => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated', + 2 => __DIR__ . '/..' . '/thecodingmachine/safe/generated', + ), + 'Ramsey\\Uuid\\' => + array ( + 0 => __DIR__ . '/..' . '/ramsey/uuid/src', + ), + 'Ramsey\\Collection\\' => + array ( + 0 => __DIR__ . '/..' . '/ramsey/collection/src', + ), + 'Psr\\Log\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', + ), + 'Psr\\Http\\Message\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-message/src', + 1 => __DIR__ . '/..' . '/psr/http-factory/src', + ), + 'Psr\\Http\\Client\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-client/src', + ), + 'Nyholm\\Psr7\\' => + array ( + 0 => __DIR__ . '/..' . '/nyholm/psr7/src', + ), + 'Nyholm\\Psr7Server\\' => + array ( + 0 => __DIR__ . '/..' . '/nyholm/psr7-server/src', + ), + 'League\\Uri\\' => + array ( + 0 => __DIR__ . '/..' . '/league/uri-interfaces/src', + 1 => __DIR__ . '/..' . '/league/uri/src', + ), + 'Jose\\Component\\Signature\\Algorithm\\' => + array ( + 0 => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-ecdsa', + 1 => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-eddsa', + 2 => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa', + ), + 'Jose\\Component\\Signature\\' => + array ( + 0 => __DIR__ . '/..' . '/web-token/jwt-signature', + ), + 'Jose\\Component\\KeyManagement\\' => + array ( + 0 => __DIR__ . '/..' . '/web-token/jwt-key-mgmt', + ), + 'Jose\\Component\\Core\\' => + array ( + 0 => __DIR__ . '/..' . '/web-token/jwt-core', + ), + 'Http\\Message\\' => + array ( + 0 => __DIR__ . '/..' . '/php-http/message-factory/src', + ), + 'FG\\' => + array ( + 0 => __DIR__ . '/..' . '/fgrosse/phpasn1/lib', + ), + 'Cose\\' => + array ( + 0 => __DIR__ . '/..' . '/web-auth/cose-lib/src', + ), + 'CBOR\\' => + array ( + 0 => __DIR__ . '/..' . '/spomky-labs/cbor-php/src', + ), + 'Brick\\Math\\' => + array ( + 0 => __DIR__ . '/..' . '/brick/math/src', + ), + 'Base64Url\\' => + array ( + 0 => __DIR__ . '/..' . '/spomky-labs/base64url/src', + ), + 'Assert\\' => + array ( + 0 => __DIR__ . '/..' . '/beberlei/assert/lib/Assert', + ), + ); + + public static $classMap = array ( + 'Assert\\Assert' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/Assert.php', + 'Assert\\Assertion' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/Assertion.php', + 'Assert\\AssertionChain' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/AssertionChain.php', + 'Assert\\AssertionFailedException' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/AssertionFailedException.php', + 'Assert\\InvalidArgumentException' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/InvalidArgumentException.php', + 'Assert\\LazyAssertion' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/LazyAssertion.php', + 'Assert\\LazyAssertionException' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/LazyAssertionException.php', + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Base64Url\\Base64Url' => __DIR__ . '/..' . '/spomky-labs/base64url/src/Base64Url.php', + 'Brick\\Math\\BigDecimal' => __DIR__ . '/..' . '/brick/math/src/BigDecimal.php', + 'Brick\\Math\\BigInteger' => __DIR__ . '/..' . '/brick/math/src/BigInteger.php', + 'Brick\\Math\\BigNumber' => __DIR__ . '/..' . '/brick/math/src/BigNumber.php', + 'Brick\\Math\\BigRational' => __DIR__ . '/..' . '/brick/math/src/BigRational.php', + 'Brick\\Math\\Exception\\DivisionByZeroException' => __DIR__ . '/..' . '/brick/math/src/Exception/DivisionByZeroException.php', + 'Brick\\Math\\Exception\\IntegerOverflowException' => __DIR__ . '/..' . '/brick/math/src/Exception/IntegerOverflowException.php', + 'Brick\\Math\\Exception\\MathException' => __DIR__ . '/..' . '/brick/math/src/Exception/MathException.php', + 'Brick\\Math\\Exception\\NegativeNumberException' => __DIR__ . '/..' . '/brick/math/src/Exception/NegativeNumberException.php', + 'Brick\\Math\\Exception\\NumberFormatException' => __DIR__ . '/..' . '/brick/math/src/Exception/NumberFormatException.php', + 'Brick\\Math\\Exception\\RoundingNecessaryException' => __DIR__ . '/..' . '/brick/math/src/Exception/RoundingNecessaryException.php', + 'Brick\\Math\\Internal\\Calculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator.php', + 'Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/BcMathCalculator.php', + 'Brick\\Math\\Internal\\Calculator\\GmpCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/GmpCalculator.php', + 'Brick\\Math\\Internal\\Calculator\\NativeCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/NativeCalculator.php', + 'Brick\\Math\\RoundingMode' => __DIR__ . '/..' . '/brick/math/src/RoundingMode.php', + 'CBOR\\AbstractCBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/AbstractCBORObject.php', + 'CBOR\\ByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ByteStringObject.php', + 'CBOR\\ByteStringWithChunkObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ByteStringWithChunkObject.php', + 'CBOR\\CBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/CBORObject.php', + 'CBOR\\Decoder' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Decoder.php', + 'CBOR\\DecoderInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/DecoderInterface.php', + 'CBOR\\IndefiniteLengthByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php', + 'CBOR\\IndefiniteLengthListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php', + 'CBOR\\IndefiniteLengthMapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php', + 'CBOR\\IndefiniteLengthTextStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php', + 'CBOR\\InfiniteListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/InfiniteListObject.php', + 'CBOR\\InfiniteMapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/InfiniteMapObject.php', + 'CBOR\\LengthCalculator' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/LengthCalculator.php', + 'CBOR\\ListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ListObject.php', + 'CBOR\\MapItem' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/MapItem.php', + 'CBOR\\MapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/MapObject.php', + 'CBOR\\NegativeIntegerObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/NegativeIntegerObject.php', + 'CBOR\\Normalizable' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Normalizable.php', + 'CBOR\\OtherObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject.php', + 'CBOR\\OtherObject\\BreakObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/BreakObject.php', + 'CBOR\\OtherObject\\DoublePrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php', + 'CBOR\\OtherObject\\FalseObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/FalseObject.php', + 'CBOR\\OtherObject\\GenericObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/GenericObject.php', + 'CBOR\\OtherObject\\HalfPrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php', + 'CBOR\\OtherObject\\NullObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/NullObject.php', + 'CBOR\\OtherObject\\OtherObjectManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php', + 'CBOR\\OtherObject\\OtherObjectManagerInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php', + 'CBOR\\OtherObject\\SimpleObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php', + 'CBOR\\OtherObject\\SinglePrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php', + 'CBOR\\OtherObject\\TrueObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/TrueObject.php', + 'CBOR\\OtherObject\\UndefinedObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php', + 'CBOR\\SignedIntegerObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/SignedIntegerObject.php', + 'CBOR\\Stream' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Stream.php', + 'CBOR\\StringStream' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/StringStream.php', + 'CBOR\\Tag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag.php', + 'CBOR\\TagObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/TagObject.php', + 'CBOR\\Tag\\Base16EncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php', + 'CBOR\\Tag\\Base64EncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php', + 'CBOR\\Tag\\Base64Tag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64Tag.php', + 'CBOR\\Tag\\Base64UrlEncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php', + 'CBOR\\Tag\\Base64UrlTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php', + 'CBOR\\Tag\\BigFloatTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/BigFloatTag.php', + 'CBOR\\Tag\\CBOREncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php', + 'CBOR\\Tag\\CBORTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/CBORTag.php', + 'CBOR\\Tag\\DatetimeTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/DatetimeTag.php', + 'CBOR\\Tag\\DecimalFractionTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php', + 'CBOR\\Tag\\EpochTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/EpochTag.php', + 'CBOR\\Tag\\GenericTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/GenericTag.php', + 'CBOR\\Tag\\MimeTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/MimeTag.php', + 'CBOR\\Tag\\NegativeBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php', + 'CBOR\\Tag\\PositiveBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/PositiveBigIntegerTag.php', + 'CBOR\\Tag\\TagManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManager.php', + 'CBOR\\Tag\\TagManagerInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php', + 'CBOR\\Tag\\TagObjectManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagObjectManager.php', + 'CBOR\\Tag\\TimestampTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TimestampTag.php', + 'CBOR\\Tag\\UnsignedBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php', + 'CBOR\\Tag\\UriTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/UriTag.php', + 'CBOR\\TextStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/TextStringObject.php', + 'CBOR\\TextStringWithChunkObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/TextStringWithChunkObject.php', + 'CBOR\\UnsignedIntegerObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/UnsignedIntegerObject.php', + 'CBOR\\Utils' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Utils.php', + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'Cose\\Algorithm\\Algorithm' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Algorithm.php', + 'Cose\\Algorithm\\Mac\\HS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS256.php', + 'Cose\\Algorithm\\Mac\\HS256Truncated64' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php', + 'Cose\\Algorithm\\Mac\\HS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS384.php', + 'Cose\\Algorithm\\Mac\\HS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS512.php', + 'Cose\\Algorithm\\Mac\\Hmac' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php', + 'Cose\\Algorithm\\Mac\\Mac' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/Mac.php', + 'Cose\\Algorithm\\Manager' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Manager.php', + 'Cose\\Algorithm\\ManagerFactory' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/ManagerFactory.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ECDSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ECSignature' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES256K' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php', + 'Cose\\Algorithm\\Signature\\ECDSA\\ES512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\ED256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED256.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\ED512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED512.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\Ed25519' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php', + 'Cose\\Algorithm\\Signature\\EdDSA\\EdDSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php', + 'Cose\\Algorithm\\Signature\\RSA\\PS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php', + 'Cose\\Algorithm\\Signature\\RSA\\PS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php', + 'Cose\\Algorithm\\Signature\\RSA\\PS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php', + 'Cose\\Algorithm\\Signature\\RSA\\PSSRSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS1' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php', + 'Cose\\Algorithm\\Signature\\RSA\\RS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php', + 'Cose\\Algorithm\\Signature\\RSA\\RSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php', + 'Cose\\Algorithm\\Signature\\Signature' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php', + 'Cose\\Algorithms' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithms.php', + 'Cose\\BigInteger' => __DIR__ . '/..' . '/web-auth/cose-lib/src/BigInteger.php', + 'Cose\\Hash' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Hash.php', + 'Cose\\Key\\Ec2Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Ec2Key.php', + 'Cose\\Key\\Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Key.php', + 'Cose\\Key\\OkpKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/OkpKey.php', + 'Cose\\Key\\RsaKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/RsaKey.php', + 'Cose\\Key\\SymmetricKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/SymmetricKey.php', + 'Cose\\Verifier' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Verifier.php', + 'FG\\ASN1\\ASNObject' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/ASNObject.php', + 'FG\\ASN1\\AbstractString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/AbstractString.php', + 'FG\\ASN1\\AbstractTime' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/AbstractTime.php', + 'FG\\ASN1\\Base128' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Base128.php', + 'FG\\ASN1\\Composite\\AttributeTypeAndValue' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php', + 'FG\\ASN1\\Composite\\RDNString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php', + 'FG\\ASN1\\Composite\\RelativeDistinguishedName' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php', + 'FG\\ASN1\\Construct' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Construct.php', + 'FG\\ASN1\\Exception\\NotImplementedException' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php', + 'FG\\ASN1\\Exception\\ParserException' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php', + 'FG\\ASN1\\ExplicitlyTaggedObject' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php', + 'FG\\ASN1\\Identifier' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Identifier.php', + 'FG\\ASN1\\OID' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/OID.php', + 'FG\\ASN1\\Parsable' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Parsable.php', + 'FG\\ASN1\\TemplateParser' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/TemplateParser.php', + 'FG\\ASN1\\Universal\\BMPString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php', + 'FG\\ASN1\\Universal\\BitString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php', + 'FG\\ASN1\\Universal\\Boolean' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php', + 'FG\\ASN1\\Universal\\CharacterString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php', + 'FG\\ASN1\\Universal\\Enumerated' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php', + 'FG\\ASN1\\Universal\\GeneralString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php', + 'FG\\ASN1\\Universal\\GeneralizedTime' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php', + 'FG\\ASN1\\Universal\\GraphicString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php', + 'FG\\ASN1\\Universal\\IA5String' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php', + 'FG\\ASN1\\Universal\\Integer' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php', + 'FG\\ASN1\\Universal\\NullObject' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php', + 'FG\\ASN1\\Universal\\NumericString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php', + 'FG\\ASN1\\Universal\\ObjectDescriptor' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php', + 'FG\\ASN1\\Universal\\ObjectIdentifier' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php', + 'FG\\ASN1\\Universal\\OctetString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php', + 'FG\\ASN1\\Universal\\PrintableString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php', + 'FG\\ASN1\\Universal\\RelativeObjectIdentifier' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php', + 'FG\\ASN1\\Universal\\Sequence' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php', + 'FG\\ASN1\\Universal\\Set' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/Set.php', + 'FG\\ASN1\\Universal\\T61String' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php', + 'FG\\ASN1\\Universal\\UTCTime' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php', + 'FG\\ASN1\\Universal\\UTF8String' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php', + 'FG\\ASN1\\Universal\\UniversalString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php', + 'FG\\ASN1\\Universal\\VisibleString' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php', + 'FG\\ASN1\\UnknownConstructedObject' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php', + 'FG\\ASN1\\UnknownObject' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/ASN1/UnknownObject.php', + 'FG\\Utility\\BigInteger' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/Utility/BigInteger.php', + 'FG\\Utility\\BigIntegerBcmath' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/Utility/BigIntegerBcmath.php', + 'FG\\Utility\\BigIntegerGmp' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/Utility/BigIntegerGmp.php', + 'FG\\X509\\AlgorithmIdentifier' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php', + 'FG\\X509\\CSR\\Attributes' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/CSR/Attributes.php', + 'FG\\X509\\CSR\\CSR' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/CSR/CSR.php', + 'FG\\X509\\CertificateExtensions' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/CertificateExtensions.php', + 'FG\\X509\\CertificateSubject' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/CertificateSubject.php', + 'FG\\X509\\PrivateKey' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/PrivateKey.php', + 'FG\\X509\\PublicKey' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/PublicKey.php', + 'FG\\X509\\SAN\\DNSName' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/SAN/DNSName.php', + 'FG\\X509\\SAN\\IPAddress' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php', + 'FG\\X509\\SAN\\SubjectAlternativeNames' => __DIR__ . '/..' . '/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php', + 'Http\\Message\\MessageFactory' => __DIR__ . '/..' . '/php-http/message-factory/src/MessageFactory.php', + 'Http\\Message\\RequestFactory' => __DIR__ . '/..' . '/php-http/message-factory/src/RequestFactory.php', + 'Http\\Message\\ResponseFactory' => __DIR__ . '/..' . '/php-http/message-factory/src/ResponseFactory.php', + 'Http\\Message\\StreamFactory' => __DIR__ . '/..' . '/php-http/message-factory/src/StreamFactory.php', + 'Http\\Message\\UriFactory' => __DIR__ . '/..' . '/php-http/message-factory/src/UriFactory.php', + 'Jose\\Component\\Core\\Algorithm' => __DIR__ . '/..' . '/web-token/jwt-core/Algorithm.php', + 'Jose\\Component\\Core\\AlgorithmManager' => __DIR__ . '/..' . '/web-token/jwt-core/AlgorithmManager.php', + 'Jose\\Component\\Core\\AlgorithmManagerFactory' => __DIR__ . '/..' . '/web-token/jwt-core/AlgorithmManagerFactory.php', + 'Jose\\Component\\Core\\JWK' => __DIR__ . '/..' . '/web-token/jwt-core/JWK.php', + 'Jose\\Component\\Core\\JWKSet' => __DIR__ . '/..' . '/web-token/jwt-core/JWKSet.php', + 'Jose\\Component\\Core\\JWT' => __DIR__ . '/..' . '/web-token/jwt-core/JWT.php', + 'Jose\\Component\\Core\\Util\\BigInteger' => __DIR__ . '/..' . '/web-token/jwt-core/Util/BigInteger.php', + 'Jose\\Component\\Core\\Util\\ECKey' => __DIR__ . '/..' . '/web-token/jwt-core/Util/ECKey.php', + 'Jose\\Component\\Core\\Util\\ECSignature' => __DIR__ . '/..' . '/web-token/jwt-core/Util/ECSignature.php', + 'Jose\\Component\\Core\\Util\\Hash' => __DIR__ . '/..' . '/web-token/jwt-core/Util/Hash.php', + 'Jose\\Component\\Core\\Util\\JsonConverter' => __DIR__ . '/..' . '/web-token/jwt-core/Util/JsonConverter.php', + 'Jose\\Component\\Core\\Util\\KeyChecker' => __DIR__ . '/..' . '/web-token/jwt-core/Util/KeyChecker.php', + 'Jose\\Component\\Core\\Util\\RSAKey' => __DIR__ . '/..' . '/web-token/jwt-core/Util/RSAKey.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\AlgorithmAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/AlgorithmAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ES256KeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/ES256KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ES384KeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/ES384KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ES512KeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/ES512KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\HS256KeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/HS256KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\HS384KeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/HS384KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\HS512KeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/HS512KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeyAnalyzerManager' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzerManager.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeyIdentifierAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/KeyIdentifierAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeysetAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\KeysetAnalyzerManager' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzerManager.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\Message' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/Message.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\MessageBag' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/MessageBag.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\MixedKeyTypes' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/MixedKeyTypes.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\MixedPublicAndPrivateKeys' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/MixedPublicAndPrivateKeys.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\NoneAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/NoneAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\OctAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/OctAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\RsaAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/RsaAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\UsageAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/UsageAnalyzer.php', + 'Jose\\Component\\KeyManagement\\Analyzer\\ZxcvbnKeyAnalyzer' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/Analyzer/ZxcvbnKeyAnalyzer.php', + 'Jose\\Component\\KeyManagement\\JKUFactory' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/JKUFactory.php', + 'Jose\\Component\\KeyManagement\\JWKFactory' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/JWKFactory.php', + 'Jose\\Component\\KeyManagement\\KeyConverter\\ECKey' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/KeyConverter/ECKey.php', + 'Jose\\Component\\KeyManagement\\KeyConverter\\KeyConverter' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/KeyConverter/KeyConverter.php', + 'Jose\\Component\\KeyManagement\\KeyConverter\\RSAKey' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/KeyConverter/RSAKey.php', + 'Jose\\Component\\KeyManagement\\UrlKeySetFactory' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/UrlKeySetFactory.php', + 'Jose\\Component\\KeyManagement\\X5UFactory' => __DIR__ . '/..' . '/web-token/jwt-key-mgmt/X5UFactory.php', + 'Jose\\Component\\Signature\\Algorithm\\ECDSA' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-ecdsa/ECDSA.php', + 'Jose\\Component\\Signature\\Algorithm\\ES256' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-ecdsa/ES256.php', + 'Jose\\Component\\Signature\\Algorithm\\ES384' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-ecdsa/ES384.php', + 'Jose\\Component\\Signature\\Algorithm\\ES512' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-ecdsa/ES512.php', + 'Jose\\Component\\Signature\\Algorithm\\EdDSA' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-eddsa/EdDSA.php', + 'Jose\\Component\\Signature\\Algorithm\\MacAlgorithm' => __DIR__ . '/..' . '/web-token/jwt-signature/Algorithm/MacAlgorithm.php', + 'Jose\\Component\\Signature\\Algorithm\\PS256' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/PS256.php', + 'Jose\\Component\\Signature\\Algorithm\\PS384' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/PS384.php', + 'Jose\\Component\\Signature\\Algorithm\\PS512' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/PS512.php', + 'Jose\\Component\\Signature\\Algorithm\\RS256' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/RS256.php', + 'Jose\\Component\\Signature\\Algorithm\\RS384' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/RS384.php', + 'Jose\\Component\\Signature\\Algorithm\\RS512' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/RS512.php', + 'Jose\\Component\\Signature\\Algorithm\\RSA' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/RSA.php', + 'Jose\\Component\\Signature\\Algorithm\\RSAPKCS1' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/RSAPKCS1.php', + 'Jose\\Component\\Signature\\Algorithm\\RSAPSS' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/RSAPSS.php', + 'Jose\\Component\\Signature\\Algorithm\\SignatureAlgorithm' => __DIR__ . '/..' . '/web-token/jwt-signature/Algorithm/SignatureAlgorithm.php', + 'Jose\\Component\\Signature\\Algorithm\\Util\\RSA' => __DIR__ . '/..' . '/web-token/jwt-signature-algorithm-rsa/Util/RSA.php', + 'Jose\\Component\\Signature\\JWS' => __DIR__ . '/..' . '/web-token/jwt-signature/JWS.php', + 'Jose\\Component\\Signature\\JWSBuilder' => __DIR__ . '/..' . '/web-token/jwt-signature/JWSBuilder.php', + 'Jose\\Component\\Signature\\JWSBuilderFactory' => __DIR__ . '/..' . '/web-token/jwt-signature/JWSBuilderFactory.php', + 'Jose\\Component\\Signature\\JWSLoader' => __DIR__ . '/..' . '/web-token/jwt-signature/JWSLoader.php', + 'Jose\\Component\\Signature\\JWSLoaderFactory' => __DIR__ . '/..' . '/web-token/jwt-signature/JWSLoaderFactory.php', + 'Jose\\Component\\Signature\\JWSTokenSupport' => __DIR__ . '/..' . '/web-token/jwt-signature/JWSTokenSupport.php', + 'Jose\\Component\\Signature\\JWSVerifier' => __DIR__ . '/..' . '/web-token/jwt-signature/JWSVerifier.php', + 'Jose\\Component\\Signature\\JWSVerifierFactory' => __DIR__ . '/..' . '/web-token/jwt-signature/JWSVerifierFactory.php', + 'Jose\\Component\\Signature\\Serializer\\CompactSerializer' => __DIR__ . '/..' . '/web-token/jwt-signature/Serializer/CompactSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JSONFlattenedSerializer' => __DIR__ . '/..' . '/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JSONGeneralSerializer' => __DIR__ . '/..' . '/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JWSSerializer' => __DIR__ . '/..' . '/web-token/jwt-signature/Serializer/JWSSerializer.php', + 'Jose\\Component\\Signature\\Serializer\\JWSSerializerManager' => __DIR__ . '/..' . '/web-token/jwt-signature/Serializer/JWSSerializerManager.php', + 'Jose\\Component\\Signature\\Serializer\\JWSSerializerManagerFactory' => __DIR__ . '/..' . '/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php', + 'Jose\\Component\\Signature\\Serializer\\Serializer' => __DIR__ . '/..' . '/web-token/jwt-signature/Serializer/Serializer.php', + 'Jose\\Component\\Signature\\Signature' => __DIR__ . '/..' . '/web-token/jwt-signature/Signature.php', + 'League\\Uri\\Contracts\\AuthorityInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/AuthorityInterface.php', + 'League\\Uri\\Contracts\\DataPathInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/DataPathInterface.php', + 'League\\Uri\\Contracts\\DomainHostInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/DomainHostInterface.php', + 'League\\Uri\\Contracts\\FragmentInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/FragmentInterface.php', + 'League\\Uri\\Contracts\\HostInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/HostInterface.php', + 'League\\Uri\\Contracts\\IpHostInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/IpHostInterface.php', + 'League\\Uri\\Contracts\\PathInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/PathInterface.php', + 'League\\Uri\\Contracts\\PortInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/PortInterface.php', + 'League\\Uri\\Contracts\\QueryInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/QueryInterface.php', + 'League\\Uri\\Contracts\\SegmentedPathInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php', + 'League\\Uri\\Contracts\\UriComponentInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/UriComponentInterface.php', + 'League\\Uri\\Contracts\\UriException' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/UriException.php', + 'League\\Uri\\Contracts\\UriInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/UriInterface.php', + 'League\\Uri\\Contracts\\UserInfoInterface' => __DIR__ . '/..' . '/league/uri-interfaces/src/Contracts/UserInfoInterface.php', + 'League\\Uri\\Exceptions\\FileinfoSupportMissing' => __DIR__ . '/..' . '/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php', + 'League\\Uri\\Exceptions\\IdnSupportMissing' => __DIR__ . '/..' . '/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php', + 'League\\Uri\\Exceptions\\IdnaConversionFailed' => __DIR__ . '/..' . '/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php', + 'League\\Uri\\Exceptions\\SyntaxError' => __DIR__ . '/..' . '/league/uri-interfaces/src/Exceptions/SyntaxError.php', + 'League\\Uri\\Exceptions\\TemplateCanNotBeExpanded' => __DIR__ . '/..' . '/league/uri/src/Exceptions/TemplateCanNotBeExpanded.php', + 'League\\Uri\\Http' => __DIR__ . '/..' . '/league/uri/src/Http.php', + 'League\\Uri\\HttpFactory' => __DIR__ . '/..' . '/league/uri/src/HttpFactory.php', + 'League\\Uri\\Idna\\Idna' => __DIR__ . '/..' . '/league/uri-interfaces/src/Idna/Idna.php', + 'League\\Uri\\Idna\\IdnaInfo' => __DIR__ . '/..' . '/league/uri-interfaces/src/Idna/IdnaInfo.php', + 'League\\Uri\\Uri' => __DIR__ . '/..' . '/league/uri/src/Uri.php', + 'League\\Uri\\UriInfo' => __DIR__ . '/..' . '/league/uri/src/UriInfo.php', + 'League\\Uri\\UriResolver' => __DIR__ . '/..' . '/league/uri/src/UriResolver.php', + 'League\\Uri\\UriString' => __DIR__ . '/..' . '/league/uri/src/UriString.php', + 'League\\Uri\\UriTemplate' => __DIR__ . '/..' . '/league/uri/src/UriTemplate.php', + 'League\\Uri\\UriTemplate\\Expression' => __DIR__ . '/..' . '/league/uri/src/UriTemplate/Expression.php', + 'League\\Uri\\UriTemplate\\Template' => __DIR__ . '/..' . '/league/uri/src/UriTemplate/Template.php', + 'League\\Uri\\UriTemplate\\VarSpecifier' => __DIR__ . '/..' . '/league/uri/src/UriTemplate/VarSpecifier.php', + 'League\\Uri\\UriTemplate\\VariableBag' => __DIR__ . '/..' . '/league/uri/src/UriTemplate/VariableBag.php', + 'Nyholm\\Psr7Server\\ServerRequestCreator' => __DIR__ . '/..' . '/nyholm/psr7-server/src/ServerRequestCreator.php', + 'Nyholm\\Psr7Server\\ServerRequestCreatorInterface' => __DIR__ . '/..' . '/nyholm/psr7-server/src/ServerRequestCreatorInterface.php', + 'Nyholm\\Psr7\\Factory\\HttplugFactory' => __DIR__ . '/..' . '/nyholm/psr7/src/Factory/HttplugFactory.php', + 'Nyholm\\Psr7\\Factory\\Psr17Factory' => __DIR__ . '/..' . '/nyholm/psr7/src/Factory/Psr17Factory.php', + 'Nyholm\\Psr7\\MessageTrait' => __DIR__ . '/..' . '/nyholm/psr7/src/MessageTrait.php', + 'Nyholm\\Psr7\\Request' => __DIR__ . '/..' . '/nyholm/psr7/src/Request.php', + 'Nyholm\\Psr7\\RequestTrait' => __DIR__ . '/..' . '/nyholm/psr7/src/RequestTrait.php', + 'Nyholm\\Psr7\\Response' => __DIR__ . '/..' . '/nyholm/psr7/src/Response.php', + 'Nyholm\\Psr7\\ServerRequest' => __DIR__ . '/..' . '/nyholm/psr7/src/ServerRequest.php', + 'Nyholm\\Psr7\\Stream' => __DIR__ . '/..' . '/nyholm/psr7/src/Stream.php', + 'Nyholm\\Psr7\\UploadedFile' => __DIR__ . '/..' . '/nyholm/psr7/src/UploadedFile.php', + 'Nyholm\\Psr7\\Uri' => __DIR__ . '/..' . '/nyholm/psr7/src/Uri.php', + 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'Psr\\Http\\Client\\ClientExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientExceptionInterface.php', + 'Psr\\Http\\Client\\ClientInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientInterface.php', + 'Psr\\Http\\Client\\NetworkExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/NetworkExceptionInterface.php', + 'Psr\\Http\\Client\\RequestExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/RequestExceptionInterface.php', + 'Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php', + 'Psr\\Http\\Message\\RequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/RequestFactoryInterface.php', + 'Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php', + 'Psr\\Http\\Message\\ResponseFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ResponseFactoryInterface.php', + 'Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php', + 'Psr\\Http\\Message\\ServerRequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ServerRequestFactoryInterface.php', + 'Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php', + 'Psr\\Http\\Message\\StreamFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/StreamFactoryInterface.php', + 'Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php', + 'Psr\\Http\\Message\\UploadedFileFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UploadedFileFactoryInterface.php', + 'Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php', + 'Psr\\Http\\Message\\UriFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UriFactoryInterface.php', + 'Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php', + 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php', + 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php', + 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php', + 'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareInterface.php', + 'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareTrait.php', + 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', + 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', + 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/DummyTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', + 'Ramsey\\Collection\\AbstractArray' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractArray.php', + 'Ramsey\\Collection\\AbstractCollection' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractCollection.php', + 'Ramsey\\Collection\\AbstractSet' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractSet.php', + 'Ramsey\\Collection\\ArrayInterface' => __DIR__ . '/..' . '/ramsey/collection/src/ArrayInterface.php', + 'Ramsey\\Collection\\Collection' => __DIR__ . '/..' . '/ramsey/collection/src/Collection.php', + 'Ramsey\\Collection\\CollectionInterface' => __DIR__ . '/..' . '/ramsey/collection/src/CollectionInterface.php', + 'Ramsey\\Collection\\DoubleEndedQueue' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueue.php', + 'Ramsey\\Collection\\DoubleEndedQueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueueInterface.php', + 'Ramsey\\Collection\\Exception\\CollectionMismatchException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/CollectionMismatchException.php', + 'Ramsey\\Collection\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidArgumentException.php', + 'Ramsey\\Collection\\Exception\\InvalidSortOrderException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidSortOrderException.php', + 'Ramsey\\Collection\\Exception\\NoSuchElementException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/NoSuchElementException.php', + 'Ramsey\\Collection\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/OutOfBoundsException.php', + 'Ramsey\\Collection\\Exception\\UnsupportedOperationException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/UnsupportedOperationException.php', + 'Ramsey\\Collection\\Exception\\ValueExtractionException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/ValueExtractionException.php', + 'Ramsey\\Collection\\GenericArray' => __DIR__ . '/..' . '/ramsey/collection/src/GenericArray.php', + 'Ramsey\\Collection\\Map\\AbstractMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AbstractMap.php', + 'Ramsey\\Collection\\Map\\AbstractTypedMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AbstractTypedMap.php', + 'Ramsey\\Collection\\Map\\AssociativeArrayMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AssociativeArrayMap.php', + 'Ramsey\\Collection\\Map\\MapInterface' => __DIR__ . '/..' . '/ramsey/collection/src/Map/MapInterface.php', + 'Ramsey\\Collection\\Map\\NamedParameterMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/NamedParameterMap.php', + 'Ramsey\\Collection\\Map\\TypedMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/TypedMap.php', + 'Ramsey\\Collection\\Map\\TypedMapInterface' => __DIR__ . '/..' . '/ramsey/collection/src/Map/TypedMapInterface.php', + 'Ramsey\\Collection\\Queue' => __DIR__ . '/..' . '/ramsey/collection/src/Queue.php', + 'Ramsey\\Collection\\QueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/QueueInterface.php', + 'Ramsey\\Collection\\Set' => __DIR__ . '/..' . '/ramsey/collection/src/Set.php', + 'Ramsey\\Collection\\Tool\\TypeTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/TypeTrait.php', + 'Ramsey\\Collection\\Tool\\ValueExtractorTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueExtractorTrait.php', + 'Ramsey\\Collection\\Tool\\ValueToStringTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueToStringTrait.php', + 'Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php', + 'Ramsey\\Uuid\\Builder\\BuilderCollection' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/BuilderCollection.php', + 'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', + 'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', + 'Ramsey\\Uuid\\Builder\\FallbackBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/FallbackBuilder.php', + 'Ramsey\\Uuid\\Builder\\UuidBuilderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/UuidBuilderInterface.php', + 'Ramsey\\Uuid\\Codec\\CodecInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/CodecInterface.php', + 'Ramsey\\Uuid\\Codec\\GuidStringCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/GuidStringCodec.php', + 'Ramsey\\Uuid\\Codec\\OrderedTimeCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/OrderedTimeCodec.php', + 'Ramsey\\Uuid\\Codec\\StringCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/StringCodec.php', + 'Ramsey\\Uuid\\Codec\\TimestampFirstCombCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php', + 'Ramsey\\Uuid\\Codec\\TimestampLastCombCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/TimestampLastCombCodec.php', + 'Ramsey\\Uuid\\Converter\\NumberConverterInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/NumberConverterInterface.php', + 'Ramsey\\Uuid\\Converter\\Number\\BigNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/BigNumberConverter.php', + 'Ramsey\\Uuid\\Converter\\Number\\DegradedNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php', + 'Ramsey\\Uuid\\Converter\\Number\\GenericNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php', + 'Ramsey\\Uuid\\Converter\\TimeConverterInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/TimeConverterInterface.php', + 'Ramsey\\Uuid\\Converter\\Time\\BigNumberTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php', + 'Ramsey\\Uuid\\Converter\\Time\\DegradedTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php', + 'Ramsey\\Uuid\\Converter\\Time\\GenericTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php', + 'Ramsey\\Uuid\\Converter\\Time\\PhpTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php', + 'Ramsey\\Uuid\\DegradedUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/DegradedUuid.php', + 'Ramsey\\Uuid\\DeprecatedUuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/DeprecatedUuidInterface.php', + 'Ramsey\\Uuid\\DeprecatedUuidMethodsTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php', + 'Ramsey\\Uuid\\Exception\\BuilderNotFoundException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/BuilderNotFoundException.php', + 'Ramsey\\Uuid\\Exception\\DateTimeException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/DateTimeException.php', + 'Ramsey\\Uuid\\Exception\\DceSecurityException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/DceSecurityException.php', + 'Ramsey\\Uuid\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidArgumentException.php', + 'Ramsey\\Uuid\\Exception\\InvalidBytesException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidBytesException.php', + 'Ramsey\\Uuid\\Exception\\InvalidUuidStringException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidUuidStringException.php', + 'Ramsey\\Uuid\\Exception\\NameException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/NameException.php', + 'Ramsey\\Uuid\\Exception\\NodeException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/NodeException.php', + 'Ramsey\\Uuid\\Exception\\RandomSourceException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/RandomSourceException.php', + 'Ramsey\\Uuid\\Exception\\TimeSourceException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/TimeSourceException.php', + 'Ramsey\\Uuid\\Exception\\UnableToBuildUuidException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UnableToBuildUuidException.php', + 'Ramsey\\Uuid\\Exception\\UnsupportedOperationException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UnsupportedOperationException.php', + 'Ramsey\\Uuid\\Exception\\UuidExceptionInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UuidExceptionInterface.php', + 'Ramsey\\Uuid\\FeatureSet' => __DIR__ . '/..' . '/ramsey/uuid/src/FeatureSet.php', + 'Ramsey\\Uuid\\Fields\\FieldsInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Fields/FieldsInterface.php', + 'Ramsey\\Uuid\\Fields\\SerializableFieldsTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Fields/SerializableFieldsTrait.php', + 'Ramsey\\Uuid\\Generator\\CombGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/CombGenerator.php', + 'Ramsey\\Uuid\\Generator\\DceSecurityGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DceSecurityGenerator.php', + 'Ramsey\\Uuid\\Generator\\DceSecurityGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php', + 'Ramsey\\Uuid\\Generator\\DefaultNameGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DefaultNameGenerator.php', + 'Ramsey\\Uuid\\Generator\\DefaultTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DefaultTimeGenerator.php', + 'Ramsey\\Uuid\\Generator\\NameGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/NameGeneratorFactory.php', + 'Ramsey\\Uuid\\Generator\\NameGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/NameGeneratorInterface.php', + 'Ramsey\\Uuid\\Generator\\PeclUuidNameGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php', + 'Ramsey\\Uuid\\Generator\\PeclUuidRandomGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php', + 'Ramsey\\Uuid\\Generator\\PeclUuidTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php', + 'Ramsey\\Uuid\\Generator\\RandomBytesGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomBytesGenerator.php', + 'Ramsey\\Uuid\\Generator\\RandomGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomGeneratorFactory.php', + 'Ramsey\\Uuid\\Generator\\RandomGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomGeneratorInterface.php', + 'Ramsey\\Uuid\\Generator\\RandomLibAdapter' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomLibAdapter.php', + 'Ramsey\\Uuid\\Generator\\TimeGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/TimeGeneratorFactory.php', + 'Ramsey\\Uuid\\Generator\\TimeGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/TimeGeneratorInterface.php', + 'Ramsey\\Uuid\\Guid\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/Fields.php', + 'Ramsey\\Uuid\\Guid\\Guid' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/Guid.php', + 'Ramsey\\Uuid\\Guid\\GuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/GuidBuilder.php', + 'Ramsey\\Uuid\\Lazy\\LazyUuidFromString' => __DIR__ . '/..' . '/ramsey/uuid/src/Lazy/LazyUuidFromString.php', + 'Ramsey\\Uuid\\Math\\BrickMathCalculator' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/BrickMathCalculator.php', + 'Ramsey\\Uuid\\Math\\CalculatorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/CalculatorInterface.php', + 'Ramsey\\Uuid\\Math\\RoundingMode' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/RoundingMode.php', + 'Ramsey\\Uuid\\Nonstandard\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/Fields.php', + 'Ramsey\\Uuid\\Nonstandard\\Uuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/Uuid.php', + 'Ramsey\\Uuid\\Nonstandard\\UuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/UuidBuilder.php', + 'Ramsey\\Uuid\\Nonstandard\\UuidV6' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/UuidV6.php', + 'Ramsey\\Uuid\\Provider\\DceSecurityProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php', + 'Ramsey\\Uuid\\Provider\\Dce\\SystemDceSecurityProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php', + 'Ramsey\\Uuid\\Provider\\NodeProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/NodeProviderInterface.php', + 'Ramsey\\Uuid\\Provider\\Node\\FallbackNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\Node\\NodeProviderCollection' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php', + 'Ramsey\\Uuid\\Provider\\Node\\RandomNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\Node\\StaticNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\Node\\SystemNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php', + 'Ramsey\\Uuid\\Provider\\TimeProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/TimeProviderInterface.php', + 'Ramsey\\Uuid\\Provider\\Time\\FixedTimeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php', + 'Ramsey\\Uuid\\Provider\\Time\\SystemTimeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php', + 'Ramsey\\Uuid\\Rfc4122\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/Fields.php', + 'Ramsey\\Uuid\\Rfc4122\\FieldsInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/FieldsInterface.php', + 'Ramsey\\Uuid\\Rfc4122\\NilTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/NilTrait.php', + 'Ramsey\\Uuid\\Rfc4122\\NilUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/NilUuid.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidBuilder.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidInterface.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV1' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV1.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV2' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV2.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV3' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV3.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV4' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV4.php', + 'Ramsey\\Uuid\\Rfc4122\\UuidV5' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV5.php', + 'Ramsey\\Uuid\\Rfc4122\\Validator' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/Validator.php', + 'Ramsey\\Uuid\\Rfc4122\\VariantTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/VariantTrait.php', + 'Ramsey\\Uuid\\Rfc4122\\VersionTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/VersionTrait.php', + 'Ramsey\\Uuid\\Type\\Decimal' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Decimal.php', + 'Ramsey\\Uuid\\Type\\Hexadecimal' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Hexadecimal.php', + 'Ramsey\\Uuid\\Type\\Integer' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Integer.php', + 'Ramsey\\Uuid\\Type\\NumberInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/NumberInterface.php', + 'Ramsey\\Uuid\\Type\\Time' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Time.php', + 'Ramsey\\Uuid\\Type\\TypeInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/TypeInterface.php', + 'Ramsey\\Uuid\\Uuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Uuid.php', + 'Ramsey\\Uuid\\UuidFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidFactory.php', + 'Ramsey\\Uuid\\UuidFactoryInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidFactoryInterface.php', + 'Ramsey\\Uuid\\UuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidInterface.php', + 'Ramsey\\Uuid\\Validator\\GenericValidator' => __DIR__ . '/..' . '/ramsey/uuid/src/Validator/GenericValidator.php', + 'Ramsey\\Uuid\\Validator\\ValidatorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Validator/ValidatorInterface.php', + 'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', + 'Safe\\DateTime' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/DateTime.php', + 'Safe\\DateTimeImmutable' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/DateTimeImmutable.php', + 'Safe\\Exceptions\\ApacheException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ApacheException.php', + 'Safe\\Exceptions\\ApcException' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/Exceptions/ApcException.php', + 'Safe\\Exceptions\\ApcuException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ApcuException.php', + 'Safe\\Exceptions\\ArrayException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ArrayException.php', + 'Safe\\Exceptions\\Bzip2Exception' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/Bzip2Exception.php', + 'Safe\\Exceptions\\CalendarException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/CalendarException.php', + 'Safe\\Exceptions\\ClassobjException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ClassobjException.php', + 'Safe\\Exceptions\\ComException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ComException.php', + 'Safe\\Exceptions\\CubridException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/CubridException.php', + 'Safe\\Exceptions\\CurlException' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/Exceptions/CurlException.php', + 'Safe\\Exceptions\\DatetimeException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/DatetimeException.php', + 'Safe\\Exceptions\\DirException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/DirException.php', + 'Safe\\Exceptions\\EioException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/EioException.php', + 'Safe\\Exceptions\\ErrorfuncException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ErrorfuncException.php', + 'Safe\\Exceptions\\ExecException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ExecException.php', + 'Safe\\Exceptions\\FileinfoException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/FileinfoException.php', + 'Safe\\Exceptions\\FilesystemException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/FilesystemException.php', + 'Safe\\Exceptions\\FilterException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/FilterException.php', + 'Safe\\Exceptions\\FpmException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/FpmException.php', + 'Safe\\Exceptions\\FtpException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/FtpException.php', + 'Safe\\Exceptions\\FunchandException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/FunchandException.php', + 'Safe\\Exceptions\\GmpException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/GmpException.php', + 'Safe\\Exceptions\\GnupgException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/GnupgException.php', + 'Safe\\Exceptions\\HashException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/HashException.php', + 'Safe\\Exceptions\\IbaseException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/IbaseException.php', + 'Safe\\Exceptions\\IbmDb2Exception' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/IbmDb2Exception.php', + 'Safe\\Exceptions\\IconvException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/IconvException.php', + 'Safe\\Exceptions\\ImageException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ImageException.php', + 'Safe\\Exceptions\\ImapException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ImapException.php', + 'Safe\\Exceptions\\InfoException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/InfoException.php', + 'Safe\\Exceptions\\IngresiiException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/IngresiiException.php', + 'Safe\\Exceptions\\InotifyException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/InotifyException.php', + 'Safe\\Exceptions\\JsonException' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/Exceptions/JsonException.php', + 'Safe\\Exceptions\\LdapException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/LdapException.php', + 'Safe\\Exceptions\\LibeventException' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/Exceptions/LibeventException.php', + 'Safe\\Exceptions\\LibxmlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/LibxmlException.php', + 'Safe\\Exceptions\\LzfException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/LzfException.php', + 'Safe\\Exceptions\\MailparseException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MailparseException.php', + 'Safe\\Exceptions\\MbstringException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MbstringException.php', + 'Safe\\Exceptions\\MiscException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MiscException.php', + 'Safe\\Exceptions\\MsqlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MsqlException.php', + 'Safe\\Exceptions\\MssqlException' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/Exceptions/MssqlException.php', + 'Safe\\Exceptions\\MysqlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MysqlException.php', + 'Safe\\Exceptions\\MysqliException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MysqliException.php', + 'Safe\\Exceptions\\MysqlndMsException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MysqlndMsException.php', + 'Safe\\Exceptions\\MysqlndQcException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/MysqlndQcException.php', + 'Safe\\Exceptions\\NetworkException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/NetworkException.php', + 'Safe\\Exceptions\\Oci8Exception' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/Oci8Exception.php', + 'Safe\\Exceptions\\OpcacheException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/OpcacheException.php', + 'Safe\\Exceptions\\OpensslException' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/Exceptions/OpensslException.php', + 'Safe\\Exceptions\\OutcontrolException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/OutcontrolException.php', + 'Safe\\Exceptions\\PasswordException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/PasswordException.php', + 'Safe\\Exceptions\\PcntlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/PcntlException.php', + 'Safe\\Exceptions\\PcreException' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/Exceptions/PcreException.php', + 'Safe\\Exceptions\\PdfException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/PdfException.php', + 'Safe\\Exceptions\\PgsqlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/PgsqlException.php', + 'Safe\\Exceptions\\PosixException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/PosixException.php', + 'Safe\\Exceptions\\PsException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/PsException.php', + 'Safe\\Exceptions\\PspellException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/PspellException.php', + 'Safe\\Exceptions\\ReadlineException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ReadlineException.php', + 'Safe\\Exceptions\\RpminfoException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/RpminfoException.php', + 'Safe\\Exceptions\\RrdException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/RrdException.php', + 'Safe\\Exceptions\\SafeExceptionInterface' => __DIR__ . '/..' . '/thecodingmachine/safe/lib/Exceptions/SafeExceptionInterface.php', + 'Safe\\Exceptions\\SemException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SemException.php', + 'Safe\\Exceptions\\SessionException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SessionException.php', + 'Safe\\Exceptions\\ShmopException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ShmopException.php', + 'Safe\\Exceptions\\SimplexmlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SimplexmlException.php', + 'Safe\\Exceptions\\SocketsException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SocketsException.php', + 'Safe\\Exceptions\\SodiumException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SodiumException.php', + 'Safe\\Exceptions\\SolrException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SolrException.php', + 'Safe\\Exceptions\\SplException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SplException.php', + 'Safe\\Exceptions\\SqlsrvException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SqlsrvException.php', + 'Safe\\Exceptions\\SsdeepException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SsdeepException.php', + 'Safe\\Exceptions\\Ssh2Exception' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/Ssh2Exception.php', + 'Safe\\Exceptions\\StatsException' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/Exceptions/StatsException.php', + 'Safe\\Exceptions\\StreamException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/StreamException.php', + 'Safe\\Exceptions\\StringsException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/StringsException.php', + 'Safe\\Exceptions\\SwooleException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/SwooleException.php', + 'Safe\\Exceptions\\UodbcException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/UodbcException.php', + 'Safe\\Exceptions\\UopzException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/UopzException.php', + 'Safe\\Exceptions\\UrlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/UrlException.php', + 'Safe\\Exceptions\\VarException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/VarException.php', + 'Safe\\Exceptions\\XdiffException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/XdiffException.php', + 'Safe\\Exceptions\\XmlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/XmlException.php', + 'Safe\\Exceptions\\XmlrpcException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/XmlrpcException.php', + 'Safe\\Exceptions\\YamlException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/YamlException.php', + 'Safe\\Exceptions\\YazException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/YazException.php', + 'Safe\\Exceptions\\ZipException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ZipException.php', + 'Safe\\Exceptions\\ZlibException' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/Exceptions/ZlibException.php', + 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'Symfony\\Component\\Process\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/process/Exception/ExceptionInterface.php', + 'Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/process/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/process/Exception/LogicException.php', + 'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessFailedException.php', + 'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessSignaledException.php', + 'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessTimedOutException.php', + 'Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/process/Exception/RuntimeException.php', + 'Symfony\\Component\\Process\\ExecutableFinder' => __DIR__ . '/..' . '/symfony/process/ExecutableFinder.php', + 'Symfony\\Component\\Process\\InputStream' => __DIR__ . '/..' . '/symfony/process/InputStream.php', + 'Symfony\\Component\\Process\\PhpExecutableFinder' => __DIR__ . '/..' . '/symfony/process/PhpExecutableFinder.php', + 'Symfony\\Component\\Process\\PhpProcess' => __DIR__ . '/..' . '/symfony/process/PhpProcess.php', + 'Symfony\\Component\\Process\\Pipes\\AbstractPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/AbstractPipes.php', + 'Symfony\\Component\\Process\\Pipes\\PipesInterface' => __DIR__ . '/..' . '/symfony/process/Pipes/PipesInterface.php', + 'Symfony\\Component\\Process\\Pipes\\UnixPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/UnixPipes.php', + 'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/WindowsPipes.php', + 'Symfony\\Component\\Process\\Process' => __DIR__ . '/..' . '/symfony/process/Process.php', + 'Symfony\\Component\\Process\\ProcessUtils' => __DIR__ . '/..' . '/symfony/process/ProcessUtils.php', + 'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php', + 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', + 'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php', + 'Symfony\\Polyfill\\Php81\\Php81' => __DIR__ . '/..' . '/symfony/polyfill-php81/Php81.php', + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', + 'Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AttestationObject' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php', + 'Webauthn\\AttestationStatement\\AttestationObjectLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php', + 'Webauthn\\AttestationStatement\\AttestationStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php', + 'Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php', + 'Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php', + 'Webauthn\\AttestedCredentialData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestedCredentialData.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php', + 'Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php', + 'Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php', + 'Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php', + 'Webauthn\\AuthenticatorAssertionResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php', + 'Webauthn\\AuthenticatorAssertionResponseValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php', + 'Webauthn\\AuthenticatorAttestationResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php', + 'Webauthn\\AuthenticatorAttestationResponseValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php', + 'Webauthn\\AuthenticatorData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorData.php', + 'Webauthn\\AuthenticatorResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorResponse.php', + 'Webauthn\\AuthenticatorSelectionCriteria' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php', + 'Webauthn\\CertificateChainChecker\\CertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php', + 'Webauthn\\CertificateChainChecker\\OpenSSLCertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/OpenSSLCertificateChainChecker.php', + 'Webauthn\\CertificateToolbox' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateToolbox.php', + 'Webauthn\\CollectedClientData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CollectedClientData.php', + 'Webauthn\\Counter\\CounterChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php', + 'Webauthn\\Counter\\ThrowExceptionIfInvalid' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php', + 'Webauthn\\Credential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Credential.php', + 'Webauthn\\MetadataService\\AbstractDescriptor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/AbstractDescriptor.php', + 'Webauthn\\MetadataService\\AuthenticatorStatus' => __DIR__ . '/..' . '/web-auth/metadata-service/src/AuthenticatorStatus.php', + 'Webauthn\\MetadataService\\BiometricAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/BiometricAccuracyDescriptor.php', + 'Webauthn\\MetadataService\\BiometricStatusReport' => __DIR__ . '/..' . '/web-auth/metadata-service/src/BiometricStatusReport.php', + 'Webauthn\\MetadataService\\CodeAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/CodeAccuracyDescriptor.php', + 'Webauthn\\MetadataService\\DisplayPNGCharacteristicsDescriptor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/DisplayPNGCharacteristicsDescriptor.php', + 'Webauthn\\MetadataService\\DistantSingleMetadata' => __DIR__ . '/..' . '/web-auth/metadata-service/src/DistantSingleMetadata.php', + 'Webauthn\\MetadataService\\EcdaaTrustAnchor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/EcdaaTrustAnchor.php', + 'Webauthn\\MetadataService\\ExtensionDescriptor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/ExtensionDescriptor.php', + 'Webauthn\\MetadataService\\MetadataService' => __DIR__ . '/..' . '/web-auth/metadata-service/src/MetadataService.php', + 'Webauthn\\MetadataService\\MetadataStatement' => __DIR__ . '/..' . '/web-auth/metadata-service/src/MetadataStatement.php', + 'Webauthn\\MetadataService\\MetadataStatementFetcher' => __DIR__ . '/..' . '/web-auth/metadata-service/src/MetadataStatementFetcher.php', + 'Webauthn\\MetadataService\\MetadataStatementRepository' => __DIR__ . '/..' . '/web-auth/metadata-service/src/MetadataStatementRepository.php', + 'Webauthn\\MetadataService\\MetadataTOCPayload' => __DIR__ . '/..' . '/web-auth/metadata-service/src/MetadataTOCPayload.php', + 'Webauthn\\MetadataService\\MetadataTOCPayloadEntry' => __DIR__ . '/..' . '/web-auth/metadata-service/src/MetadataTOCPayloadEntry.php', + 'Webauthn\\MetadataService\\PatternAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/PatternAccuracyDescriptor.php', + 'Webauthn\\MetadataService\\RgbPaletteEntry' => __DIR__ . '/..' . '/web-auth/metadata-service/src/RgbPaletteEntry.php', + 'Webauthn\\MetadataService\\RogueListEntry' => __DIR__ . '/..' . '/web-auth/metadata-service/src/RogueListEntry.php', + 'Webauthn\\MetadataService\\SingleMetadata' => __DIR__ . '/..' . '/web-auth/metadata-service/src/SingleMetadata.php', + 'Webauthn\\MetadataService\\StatusReport' => __DIR__ . '/..' . '/web-auth/metadata-service/src/StatusReport.php', + 'Webauthn\\MetadataService\\Utils' => __DIR__ . '/..' . '/web-auth/metadata-service/src/Utils.php', + 'Webauthn\\MetadataService\\VerificationMethodANDCombinations' => __DIR__ . '/..' . '/web-auth/metadata-service/src/VerificationMethodANDCombinations.php', + 'Webauthn\\MetadataService\\VerificationMethodDescriptor' => __DIR__ . '/..' . '/web-auth/metadata-service/src/VerificationMethodDescriptor.php', + 'Webauthn\\MetadataService\\Version' => __DIR__ . '/..' . '/web-auth/metadata-service/src/Version.php', + 'Webauthn\\PublicKeyCredential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredential.php', + 'Webauthn\\PublicKeyCredentialCreationOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php', + 'Webauthn\\PublicKeyCredentialDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php', + 'Webauthn\\PublicKeyCredentialDescriptorCollection' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php', + 'Webauthn\\PublicKeyCredentialEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php', + 'Webauthn\\PublicKeyCredentialLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php', + 'Webauthn\\PublicKeyCredentialOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php', + 'Webauthn\\PublicKeyCredentialParameters' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php', + 'Webauthn\\PublicKeyCredentialRequestOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php', + 'Webauthn\\PublicKeyCredentialRpEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php', + 'Webauthn\\PublicKeyCredentialSource' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php', + 'Webauthn\\PublicKeyCredentialSourceRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php', + 'Webauthn\\PublicKeyCredentialUserEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php', + 'Webauthn\\Server' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Server.php', + 'Webauthn\\StringStream' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/StringStream.php', + 'Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php', + 'Webauthn\\TokenBinding\\SecTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php', + 'Webauthn\\TokenBinding\\TokenBinding' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php', + 'Webauthn\\TokenBinding\\TokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php', + 'Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php', + 'Webauthn\\TrustPath\\CertificateTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php', + 'Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php', + 'Webauthn\\TrustPath\\EmptyTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php', + 'Webauthn\\TrustPath\\TrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php', + 'Webauthn\\TrustPath\\TrustPathLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php', + 'Webauthn\\U2FPublicKey' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/U2FPublicKey.php', + 'Webauthn\\Util\\CoseSignatureFixer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit8c7684b956de574bcb0eefe2be31e0ab::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit8c7684b956de574bcb0eefe2be31e0ab::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit8c7684b956de574bcb0eefe2be31e0ab::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/installed.json b/wp-content/plugins/wp-webauthn/vendor/composer/installed.json new file mode 100644 index 00000000..93d6831d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/installed.json @@ -0,0 +1,2474 @@ +{ + "packages": [ + { + "name": "beberlei/assert", + "version": "v3.3.2", + "version_normalized": "3.3.2.0", + "source": { + "type": "git", + "url": "https://github.com/beberlei/assert.git", + "reference": "cb70015c04be1baee6f5f5c953703347c0ac1655" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beberlei/assert/zipball/cb70015c04be1baee6f5f5c953703347c0ac1655", + "reference": "cb70015c04be1baee6f5f5c953703347c0ac1655", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "php": "^7.0 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan": "*", + "phpunit/phpunit": ">=6.0.0", + "yoast/phpunit-polyfills": "^0.1.0" + }, + "suggest": { + "ext-intl": "Needed to allow Assertion::count(), Assertion::isCountable(), Assertion::minCount(), and Assertion::maxCount() to operate on ResourceBundles" + }, + "time": "2021-12-16T21:41:27+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "lib/Assert/functions.php" + ], + "psr-4": { + "Assert\\": "lib/Assert" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Collaborator" + } + ], + "description": "Thin assertion library for input validation in business models.", + "keywords": [ + "assert", + "assertion", + "validation" + ], + "support": { + "issues": "https://github.com/beberlei/assert/issues", + "source": "https://github.com/beberlei/assert/tree/v3.3.2" + }, + "install-path": "../beberlei/assert" + }, + { + "name": "brick/math", + "version": "0.9.3", + "version_normalized": "0.9.3.0", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", + "vimeo/psalm": "4.9.2" + }, + "time": "2021-08-15T20:50:18+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.9.3" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/brick/math", + "type": "tidelift" + } + ], + "install-path": "../brick/math" + }, + { + "name": "fgrosse/phpasn1", + "version": "v2.4.0", + "version_normalized": "2.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/fgrosse/PHPASN1.git", + "reference": "eef488991d53e58e60c9554b09b1201ca5ba9296" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fgrosse/PHPASN1/zipball/eef488991d53e58e60c9554b09b1201ca5ba9296", + "reference": "eef488991d53e58e60c9554b09b1201ca5ba9296", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "~2.0", + "phpunit/phpunit": "^6.3 || ^7.0 || ^8.0" + }, + "suggest": { + "ext-bcmath": "BCmath is the fallback extension for big integer calculations", + "ext-curl": "For loading OID information from the web if they have not bee defined statically", + "ext-gmp": "GMP is the preferred extension for big integer calculations", + "phpseclib/bcmath_compat": "BCmath polyfill for servers where neither GMP nor BCmath is available" + }, + "time": "2021-12-11T12:41:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "FG\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Friedrich Große", + "email": "friedrich.grosse@gmail.com", + "homepage": "https://github.com/FGrosse", + "role": "Author" + }, + { + "name": "All contributors", + "homepage": "https://github.com/FGrosse/PHPASN1/contributors" + } + ], + "description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.", + "homepage": "https://github.com/FGrosse/PHPASN1", + "keywords": [ + "DER", + "asn.1", + "asn1", + "ber", + "binary", + "decoding", + "encoding", + "x.509", + "x.690", + "x509", + "x690" + ], + "support": { + "issues": "https://github.com/fgrosse/PHPASN1/issues", + "source": "https://github.com/fgrosse/PHPASN1/tree/v2.4.0" + }, + "install-path": "../fgrosse/phpasn1" + }, + { + "name": "league/uri", + "version": "6.5.0", + "version_normalized": "6.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "c68ca445abb04817d740ddd6d0b3551826ef0c5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/c68ca445abb04817d740ddd6d0b3551826ef0c5a", + "reference": "c68ca445abb04817d740ddd6d0b3551826ef0c5a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "league/uri-interfaces": "^2.3", + "php": "^7.3 || ^8.0", + "psr/http-message": "^1.0" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.19 || ^3.0", + "phpstan/phpstan": "^0.12.90", + "phpstan/phpstan-phpunit": "^0.12.22", + "phpstan/phpstan-strict-rules": "^0.12.11", + "phpunit/phpunit": "^8.0 || ^9.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-fileinfo": "Needed to create Data URI from a filepath", + "ext-intl": "Needed to improve host validation", + "league/uri-components": "Needed to easily manipulate URI objects", + "psr/http-factory": "Needed to use the URI factory" + }, + "time": "2021-08-27T09:54:07+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "League\\Uri\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "http://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri/issues", + "source": "https://github.com/thephpleague/uri/tree/6.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "install-path": "../league/uri" + }, + { + "name": "league/uri-interfaces", + "version": "2.3.0", + "version_normalized": "2.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", + "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.19", + "phpstan/phpstan": "^0.12.90", + "phpstan/phpstan-phpunit": "^0.12.19", + "phpstan/phpstan-strict-rules": "^0.12.9", + "phpunit/phpunit": "^8.5.15 || ^9.5" + }, + "suggest": { + "ext-intl": "to use the IDNA feature", + "symfony/intl": "to use the IDNA feature via Symfony Polyfill" + }, + "time": "2021-06-28T04:27:21+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "League\\Uri\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interface for URI representation", + "homepage": "http://github.com/thephpleague/uri-interfaces", + "keywords": [ + "rfc3986", + "rfc3987", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/thephpleague/uri-interfaces/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "install-path": "../league/uri-interfaces" + }, + { + "name": "nyholm/psr7", + "version": "1.5.0", + "version_normalized": "1.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "1461e07a0f2a975a52082ca3b769ca912b816226" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/1461e07a0f2a975a52082ca3b769ca912b816226", + "reference": "1461e07a0f2a975a52082ca3b769ca912b816226", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1", + "php-http/message-factory": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.9", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || 8.5 || 9.4", + "symfony/error-handler": "^4.4" + }, + "time": "2022-02-02T18:37:57+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.5.0" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "install-path": "../nyholm/psr7" + }, + { + "name": "nyholm/psr7-server", + "version": "0.4.2", + "version_normalized": "0.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7-server.git", + "reference": "aab2962c970a1776447894e4fd3825a3d69dee61" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/aab2962c970a1776447894e4fd3825a3d69dee61", + "reference": "aab2962c970a1776447894e4fd3825a3d69dee61", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "nyholm/nsa": "^1.1", + "nyholm/psr7": "^1.3", + "phpunit/phpunit": "^7.0" + }, + "time": "2020-06-06T10:33:29+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nyholm\\Psr7Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "Helper classes to handle PSR-7 server requests", + "homepage": "http://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7-server/issues", + "source": "https://github.com/Nyholm/psr7-server/tree/master" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "install-path": "../nyholm/psr7-server" + }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "time": "2015-12-19T14:08:53+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "support": { + "issues": "https://github.com/php-http/message-factory/issues", + "source": "https://github.com/php-http/message-factory/tree/master" + }, + "install-path": "../php-http/message-factory" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "time": "2020-06-29T06:28:15+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "install-path": "../psr/http-client" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "time": "2019-04-30T12:38:16+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "install-path": "../psr/http-factory" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2016-08-06T14:39:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "install-path": "../psr/http-message" + }, + { + "name": "psr/log", + "version": "1.1.4", + "version_normalized": "1.1.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2021-05-03T11:20:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "install-path": "../psr/log" + }, + { + "name": "ramsey/collection", + "version": "1.2.2", + "version_normalized": "1.2.2.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a", + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.3 || ^8", + "symfony/polyfill-php81": "^1.23" + }, + "require-dev": { + "captainhook/captainhook": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "ergebnis/composer-normalize": "^2.6", + "fakerphp/faker": "^1.5", + "hamcrest/hamcrest-php": "^2", + "jangregor/phpstan-prophecy": "^0.8", + "mockery/mockery": "^1.3", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12.32", + "phpstan/phpstan-mockery": "^0.12.5", + "phpstan/phpstan-phpunit": "^0.12.11", + "phpunit/phpunit": "^8.5 || ^9", + "psy/psysh": "^0.10.4", + "slevomat/coding-standard": "^6.3", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.4" + }, + "time": "2021-10-10T03:01:02+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/1.2.2" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "install-path": "../ramsey/collection" + }, + { + "name": "ramsey/uuid", + "version": "4.2.3", + "version_normalized": "4.2.3.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "brick/math": "^0.8 || ^0.9", + "ext-json": "*", + "php": "^7.2 || ^8.0", + "ramsey/collection": "^1.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php80": "^1.14" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "moontoast/math": "^1.1", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5 || ^9", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-ctype": "Enables faster processing of character classification using ctype functions.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "time": "2021-09-25T23:10:38+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.x-dev" + }, + "captainhook": { + "force-install": true + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.2.3" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "install-path": "../ramsey/uuid" + }, + { + "name": "spomky-labs/base64url", + "version": "v2.0.4", + "version_normalized": "2.0.4.0", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/base64url.git", + "reference": "7752ce931ec285da4ed1f4c5aa27e45e097be61d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/base64url/zipball/7752ce931ec285da4ed1f4c5aa27e45e097be61d", + "reference": "7752ce931ec285da4ed1f4c5aa27e45e097be61d", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.11|^0.12", + "phpstan/phpstan-beberlei-assert": "^0.11|^0.12", + "phpstan/phpstan-deprecation-rules": "^0.11|^0.12", + "phpstan/phpstan-phpunit": "^0.11|^0.12", + "phpstan/phpstan-strict-rules": "^0.11|^0.12" + }, + "time": "2020-11-03T09:10:25+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Base64Url\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky-Labs/base64url/contributors" + } + ], + "description": "Base 64 URL Safe Encoding/Decoding PHP Library", + "homepage": "https://github.com/Spomky-Labs/base64url", + "keywords": [ + "base64", + "rfc4648", + "safe", + "url" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/base64url/issues", + "source": "https://github.com/Spomky-Labs/base64url/tree/v2.0.4" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../spomky-labs/base64url" + }, + { + "name": "spomky-labs/cbor-php", + "version": "v2.1.0", + "version_normalized": "2.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/cbor-php.git", + "reference": "28e2712cfc0b48fae661a48ffc6896d7abe83684" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/28e2712cfc0b48fae661a48ffc6896d7abe83684", + "reference": "28e2712cfc0b48fae661a48ffc6896d7abe83684", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "brick/math": "^0.8.15|^0.9.0", + "ext-mbstring": "*", + "php": ">=7.3" + }, + "require-dev": { + "ekino/phpstan-banned-code": "^1.0", + "ext-json": "*", + "infection/infection": "^0.18|^0.25", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-beberlei-assert": "^1.0", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.12", + "roave/security-advisories": "dev-latest", + "symplify/easy-coding-standard": "^10.0" + }, + "suggest": { + "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", + "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance" + }, + "time": "2021-12-13T12:46:26+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "CBOR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/cbor-php/contributors" + } + ], + "description": "CBOR Encoder/Decoder for PHP", + "keywords": [ + "Concise Binary Object Representation", + "RFC7049", + "cbor" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/cbor-php/issues", + "source": "https://github.com/Spomky-Labs/cbor-php/tree/v2.1.0" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../spomky-labs/cbor-php" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "30885182c981ab175d4d034db0f6f469898070ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "time": "2021-10-20T20:35:02+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-ctype" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-03-04T08:16:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php80" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", + "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "time": "2021-09-13T13:58:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php81" + }, + { + "name": "symfony/process", + "version": "v5.4.8", + "version_normalized": "5.4.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/597f3fff8e3e91836bb0bd38f5718b56ddbde2f3", + "reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "time": "2022-04-08T05:07:18+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/process" + }, + { + "name": "thecodingmachine/safe", + "version": "v1.3.3", + "version_normalized": "1.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "a8ab0876305a4cdaef31b2350fcb9811b5608dbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/a8ab0876305a4cdaef31b2350fcb9811b5608dbc", + "reference": "a8ab0876305a4cdaef31b2350fcb9811b5608dbc", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "phpstan/phpstan": "^0.12", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^0.12" + }, + "time": "2020-10-28T17:51:34+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "deprecated/apc.php", + "deprecated/libevent.php", + "deprecated/mssql.php", + "deprecated/stats.php", + "lib/special_cases.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/ingres-ii.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/msql.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/mysqlndMs.php", + "generated/mysqlndQc.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/password.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pdf.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/simplexml.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "psr-4": { + "Safe\\": [ + "lib/", + "deprecated/", + "generated/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v1.3.3" + }, + "install-path": "../thecodingmachine/safe" + }, + { + "name": "web-auth/cose-lib", + "version": "v3.3.12", + "version_normalized": "3.3.12.0", + "source": { + "type": "git", + "url": "https://github.com/web-auth/cose-lib.git", + "reference": "efa6ec2ba4e840bc1316a493973c9916028afeeb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/efa6ec2ba4e840bc1316a493973c9916028afeeb", + "reference": "efa6ec2ba4e840bc1316a493973c9916028afeeb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "beberlei/assert": "^3.2", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "fgrosse/phpasn1": "^2.1", + "php": ">=7.2" + }, + "time": "2021-12-04T12:13:35+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Cose\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/cose/contributors" + } + ], + "description": "CBOR Object Signing and Encryption (COSE) For PHP", + "homepage": "https://github.com/web-auth", + "keywords": [ + "COSE", + "RFC8152" + ], + "support": { + "source": "https://github.com/web-auth/cose-lib/tree/v3.3.12" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-auth/cose-lib" + }, + { + "name": "web-auth/metadata-service", + "version": "v3.3.12", + "version_normalized": "3.3.12.0", + "source": { + "type": "git", + "url": "https://github.com/web-auth/webauthn-metadata-service.git", + "reference": "ef40d2b7b68c4964247d13fab52e2fa8dbd65246" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/webauthn-metadata-service/zipball/ef40d2b7b68c4964247d13fab52e2fa8dbd65246", + "reference": "ef40d2b7b68c4964247d13fab52e2fa8dbd65246", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "beberlei/assert": "^3.2", + "ext-json": "*", + "league/uri": "^6.0", + "php": ">=7.2", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/log": "^1.1" + }, + "suggest": { + "web-token/jwt-key-mgmt": "Mandatory for fetching Metadata Statement from distant sources", + "web-token/jwt-signature-algorithm-ecdsa": "Mandatory for fetching Metadata Statement from distant sources" + }, + "time": "2021-11-21T11:14:31+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Webauthn\\MetadataService\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/metadata-service/contributors" + } + ], + "description": "Metadata Service for FIDO2/Webauthn", + "homepage": "https://github.com/web-auth", + "keywords": [ + "FIDO2", + "fido", + "webauthn" + ], + "support": { + "source": "https://github.com/web-auth/webauthn-metadata-service/tree/v3.3.12" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-auth/metadata-service" + }, + { + "name": "web-auth/webauthn-lib", + "version": "v3.3.12", + "version_normalized": "3.3.12.0", + "source": { + "type": "git", + "url": "https://github.com/web-auth/webauthn-lib.git", + "reference": "5ef9b21c8e9f8a817e524ac93290d08a9f065b33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/5ef9b21c8e9f8a817e524ac93290d08a9f065b33", + "reference": "5ef9b21c8e9f8a817e524ac93290d08a9f065b33", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "beberlei/assert": "^3.2", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "fgrosse/phpasn1": "^2.1", + "php": ">=7.2", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "psr/log": "^1.1", + "ramsey/uuid": "^3.8|^4.0", + "spomky-labs/base64url": "^2.0", + "spomky-labs/cbor-php": "^1.0|^2.0", + "symfony/process": "^3.0|^4.0|^5.0", + "thecodingmachine/safe": "^1.1", + "web-auth/cose-lib": "self.version", + "web-auth/metadata-service": "self.version" + }, + "suggest": { + "psr/log-implementation": "Recommended to receive logs from the library", + "web-token/jwt-key-mgmt": "Mandatory for the AndroidSafetyNet Attestation Statement support", + "web-token/jwt-signature-algorithm-ecdsa": "Recommended for the AndroidSafetyNet Attestation Statement support", + "web-token/jwt-signature-algorithm-eddsa": "Recommended for the AndroidSafetyNet Attestation Statement support", + "web-token/jwt-signature-algorithm-rsa": "Mandatory for the AndroidSafetyNet Attestation Statement support" + }, + "time": "2022-02-18T07:13:44+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Webauthn\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/webauthn-library/contributors" + } + ], + "description": "FIDO2/Webauthn Support For PHP", + "homepage": "https://github.com/web-auth", + "keywords": [ + "FIDO2", + "fido", + "webauthn" + ], + "support": { + "source": "https://github.com/web-auth/webauthn-lib/tree/v3.3.12" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-auth/webauthn-lib" + }, + { + "name": "web-token/jwt-core", + "version": "v2.2.11", + "version_normalized": "2.2.11.0", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-core.git", + "reference": "53beb6f6c1eec4fa93c1c3e5d9e5701e71fa1678" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-core/zipball/53beb6f6c1eec4fa93c1c3e5d9e5701e71fa1678", + "reference": "53beb6f6c1eec4fa93c1c3e5d9e5701e71fa1678", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "brick/math": "^0.8.17|^0.9", + "ext-json": "*", + "ext-mbstring": "*", + "fgrosse/phpasn1": "^2.0", + "php": ">=7.2", + "spomky-labs/base64url": "^1.0|^2.0" + }, + "conflict": { + "spomky-labs/jose": "*" + }, + "time": "2021-03-17T14:55:52+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Jose\\Component\\Core\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "description": "Core component of the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "support": { + "source": "https://github.com/web-token/jwt-core/tree/v2.2.11" + }, + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-token/jwt-core" + }, + { + "name": "web-token/jwt-key-mgmt", + "version": "v2.2.11", + "version_normalized": "2.2.11.0", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-key-mgmt.git", + "reference": "0b116379515700d237b4e5de86879078ccb09d8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-key-mgmt/zipball/0b116379515700d237b4e5de86879078ccb09d8a", + "reference": "0b116379515700d237b4e5de86879078ccb09d8a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-openssl": "*", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "web-token/jwt-core": "^2.0" + }, + "suggest": { + "ext-sodium": "Sodium is required for OKP key creation, EdDSA signature algorithm and ECDH-ES key encryption with OKP keys", + "php-http/httplug": "To enable JKU/X5U support.", + "php-http/message-factory": "To enable JKU/X5U support.", + "web-token/jwt-util-ecc": "To use EC key analyzers." + }, + "time": "2021-03-17T14:55:52+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Jose\\Component\\KeyManagement\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-key-mgmt/contributors" + } + ], + "description": "Key Management component of the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "support": { + "source": "https://github.com/web-token/jwt-key-mgmt/tree/v2.2.11" + }, + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-token/jwt-key-mgmt" + }, + { + "name": "web-token/jwt-signature", + "version": "v2.2.11", + "version_normalized": "2.2.11.0", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-signature.git", + "reference": "015b59aaf3b6e8fb9f5bd1338845b7464c7d8103" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-signature/zipball/015b59aaf3b6e8fb9f5bd1338845b7464c7d8103", + "reference": "015b59aaf3b6e8fb9f5bd1338845b7464c7d8103", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "web-token/jwt-core": "^2.1" + }, + "suggest": { + "web-token/jwt-signature-algorithm-ecdsa": "ECDSA Based Signature Algorithms", + "web-token/jwt-signature-algorithm-eddsa": "EdDSA Based Signature Algorithms", + "web-token/jwt-signature-algorithm-experimental": "Experimental Signature Algorithms", + "web-token/jwt-signature-algorithm-hmac": "HMAC Based Signature Algorithms", + "web-token/jwt-signature-algorithm-none": "None Signature Algorithm", + "web-token/jwt-signature-algorithm-rsa": "RSA Based Signature Algorithms" + }, + "time": "2021-03-01T19:55:28+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-signature/contributors" + } + ], + "description": "Signature component of the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "support": { + "source": "https://github.com/web-token/jwt-signature/tree/v2.2.11" + }, + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-token/jwt-signature" + }, + { + "name": "web-token/jwt-signature-algorithm-ecdsa", + "version": "v2.2.11", + "version_normalized": "2.2.11.0", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-signature-algorithm-ecdsa.git", + "reference": "44cbbb4374c51f1cf48b82ae761efbf24e1a8591" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-signature-algorithm-ecdsa/zipball/44cbbb4374c51f1cf48b82ae761efbf24e1a8591", + "reference": "44cbbb4374c51f1cf48b82ae761efbf24e1a8591", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-openssl": "*", + "web-token/jwt-signature": "^2.0" + }, + "time": "2021-01-21T19:18:03+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\Algorithm\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "description": "ECDSA Based Signature Algorithms the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "support": { + "source": "https://github.com/web-token/jwt-signature-algorithm-ecdsa/tree/v2.2.11" + }, + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-token/jwt-signature-algorithm-ecdsa" + }, + { + "name": "web-token/jwt-signature-algorithm-eddsa", + "version": "v2.2.11", + "version_normalized": "2.2.11.0", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-signature-algorithm-eddsa.git", + "reference": "b805ecca593c56e60e0463bd2cacc9b1341910f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-signature-algorithm-eddsa/zipball/b805ecca593c56e60e0463bd2cacc9b1341910f6", + "reference": "b805ecca593c56e60e0463bd2cacc9b1341910f6", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-sodium": "*", + "web-token/jwt-signature": "^2.1" + }, + "time": "2021-01-21T19:18:03+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\Algorithm\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "description": "EdDSA Signature Algorithm the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "support": { + "source": "https://github.com/web-token/jwt-signature-algorithm-eddsa/tree/v2.2.11" + }, + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-token/jwt-signature-algorithm-eddsa" + }, + { + "name": "web-token/jwt-signature-algorithm-rsa", + "version": "v2.2.11", + "version_normalized": "2.2.11.0", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-signature-algorithm-rsa.git", + "reference": "513ad90eb5ef1886ff176727a769bda4618141b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-signature-algorithm-rsa/zipball/513ad90eb5ef1886ff176727a769bda4618141b0", + "reference": "513ad90eb5ef1886ff176727a769bda4618141b0", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "brick/math": "^0.8.17|^0.9", + "ext-openssl": "*", + "web-token/jwt-signature": "^2.1" + }, + "suggest": { + "ext-bcmath": "GMP or BCMath is highly recommended to improve the library performance", + "ext-gmp": "GMP or BCMath is highly recommended to improve the library performance" + }, + "time": "2021-01-21T19:18:03+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\Algorithm\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "description": "RSA Based Signature Algorithms the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "support": { + "source": "https://github.com/web-token/jwt-signature-algorithm-rsa/tree/v2.2.11" + }, + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../web-token/jwt-signature-algorithm-rsa" + } + ], + "dev": false, + "dev-package-names": [] +} diff --git a/wp-content/plugins/wp-webauthn/vendor/composer/installed.php b/wp-content/plugins/wp-webauthn/vendor/composer/installed.php new file mode 100644 index 00000000..6e728eaa --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/composer/installed.php @@ -0,0 +1,311 @@ + array( + 'pretty_version' => '1.2.8', + 'version' => '1.2.8.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '7ee9e75e82e4c783157494b6ea3e4c29b9bc1d3f', + 'name' => '__root__', + 'dev' => false, + ), + 'versions' => array( + '__root__' => array( + 'pretty_version' => '1.2.8', + 'version' => '1.2.8.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '7ee9e75e82e4c783157494b6ea3e4c29b9bc1d3f', + 'dev_requirement' => false, + ), + 'beberlei/assert' => array( + 'pretty_version' => 'v3.3.2', + 'version' => '3.3.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../beberlei/assert', + 'aliases' => array(), + 'reference' => 'cb70015c04be1baee6f5f5c953703347c0ac1655', + 'dev_requirement' => false, + ), + 'brick/math' => array( + 'pretty_version' => '0.9.3', + 'version' => '0.9.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../brick/math', + 'aliases' => array(), + 'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae', + 'dev_requirement' => false, + ), + 'fgrosse/phpasn1' => array( + 'pretty_version' => 'v2.4.0', + 'version' => '2.4.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../fgrosse/phpasn1', + 'aliases' => array(), + 'reference' => 'eef488991d53e58e60c9554b09b1201ca5ba9296', + 'dev_requirement' => false, + ), + 'league/uri' => array( + 'pretty_version' => '6.5.0', + 'version' => '6.5.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../league/uri', + 'aliases' => array(), + 'reference' => 'c68ca445abb04817d740ddd6d0b3551826ef0c5a', + 'dev_requirement' => false, + ), + 'league/uri-interfaces' => array( + 'pretty_version' => '2.3.0', + 'version' => '2.3.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../league/uri-interfaces', + 'aliases' => array(), + 'reference' => '00e7e2943f76d8cb50c7dfdc2f6dee356e15e383', + 'dev_requirement' => false, + ), + 'nyholm/psr7' => array( + 'pretty_version' => '1.5.0', + 'version' => '1.5.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nyholm/psr7', + 'aliases' => array(), + 'reference' => '1461e07a0f2a975a52082ca3b769ca912b816226', + 'dev_requirement' => false, + ), + 'nyholm/psr7-server' => array( + 'pretty_version' => '0.4.2', + 'version' => '0.4.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nyholm/psr7-server', + 'aliases' => array(), + 'reference' => 'aab2962c970a1776447894e4fd3825a3d69dee61', + 'dev_requirement' => false, + ), + 'php-http/message-factory' => array( + 'pretty_version' => 'v1.0.2', + 'version' => '1.0.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../php-http/message-factory', + 'aliases' => array(), + 'reference' => 'a478cb11f66a6ac48d8954216cfed9aa06a501a1', + 'dev_requirement' => false, + ), + 'psr/http-client' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-client', + 'aliases' => array(), + 'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621', + 'dev_requirement' => false, + ), + 'psr/http-factory' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-factory', + 'aliases' => array(), + 'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be', + 'dev_requirement' => false, + ), + 'psr/http-factory-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), + 'psr/http-message' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-message', + 'aliases' => array(), + 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363', + 'dev_requirement' => false, + ), + 'psr/http-message-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), + 'psr/log' => array( + 'pretty_version' => '1.1.4', + 'version' => '1.1.4.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/log', + 'aliases' => array(), + 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', + 'dev_requirement' => false, + ), + 'ramsey/collection' => array( + 'pretty_version' => '1.2.2', + 'version' => '1.2.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../ramsey/collection', + 'aliases' => array(), + 'reference' => 'cccc74ee5e328031b15640b51056ee8d3bb66c0a', + 'dev_requirement' => false, + ), + 'ramsey/uuid' => array( + 'pretty_version' => '4.2.3', + 'version' => '4.2.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../ramsey/uuid', + 'aliases' => array(), + 'reference' => 'fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df', + 'dev_requirement' => false, + ), + 'rhumsaa/uuid' => array( + 'dev_requirement' => false, + 'replaced' => array( + 0 => '4.2.3', + ), + ), + 'spomky-labs/base64url' => array( + 'pretty_version' => 'v2.0.4', + 'version' => '2.0.4.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../spomky-labs/base64url', + 'aliases' => array(), + 'reference' => '7752ce931ec285da4ed1f4c5aa27e45e097be61d', + 'dev_requirement' => false, + ), + 'spomky-labs/cbor-php' => array( + 'pretty_version' => 'v2.1.0', + 'version' => '2.1.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../spomky-labs/cbor-php', + 'aliases' => array(), + 'reference' => '28e2712cfc0b48fae661a48ffc6896d7abe83684', + 'dev_requirement' => false, + ), + 'symfony/polyfill-ctype' => array( + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', + 'aliases' => array(), + 'reference' => '30885182c981ab175d4d034db0f6f469898070ab', + 'dev_requirement' => false, + ), + 'symfony/polyfill-php80' => array( + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php80', + 'aliases' => array(), + 'reference' => '4407588e0d3f1f52efb65fbe92babe41f37fe50c', + 'dev_requirement' => false, + ), + 'symfony/polyfill-php81' => array( + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php81', + 'aliases' => array(), + 'reference' => '5de4ba2d41b15f9bd0e19b2ab9674135813ec98f', + 'dev_requirement' => false, + ), + 'symfony/process' => array( + 'pretty_version' => 'v5.4.8', + 'version' => '5.4.8.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/process', + 'aliases' => array(), + 'reference' => '597f3fff8e3e91836bb0bd38f5718b56ddbde2f3', + 'dev_requirement' => false, + ), + 'thecodingmachine/safe' => array( + 'pretty_version' => 'v1.3.3', + 'version' => '1.3.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../thecodingmachine/safe', + 'aliases' => array(), + 'reference' => 'a8ab0876305a4cdaef31b2350fcb9811b5608dbc', + 'dev_requirement' => false, + ), + 'web-auth/cose-lib' => array( + 'pretty_version' => 'v3.3.12', + 'version' => '3.3.12.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-auth/cose-lib', + 'aliases' => array(), + 'reference' => 'efa6ec2ba4e840bc1316a493973c9916028afeeb', + 'dev_requirement' => false, + ), + 'web-auth/metadata-service' => array( + 'pretty_version' => 'v3.3.12', + 'version' => '3.3.12.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-auth/metadata-service', + 'aliases' => array(), + 'reference' => 'ef40d2b7b68c4964247d13fab52e2fa8dbd65246', + 'dev_requirement' => false, + ), + 'web-auth/webauthn-lib' => array( + 'pretty_version' => 'v3.3.12', + 'version' => '3.3.12.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-auth/webauthn-lib', + 'aliases' => array(), + 'reference' => '5ef9b21c8e9f8a817e524ac93290d08a9f065b33', + 'dev_requirement' => false, + ), + 'web-token/jwt-core' => array( + 'pretty_version' => 'v2.2.11', + 'version' => '2.2.11.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-token/jwt-core', + 'aliases' => array(), + 'reference' => '53beb6f6c1eec4fa93c1c3e5d9e5701e71fa1678', + 'dev_requirement' => false, + ), + 'web-token/jwt-key-mgmt' => array( + 'pretty_version' => 'v2.2.11', + 'version' => '2.2.11.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-token/jwt-key-mgmt', + 'aliases' => array(), + 'reference' => '0b116379515700d237b4e5de86879078ccb09d8a', + 'dev_requirement' => false, + ), + 'web-token/jwt-signature' => array( + 'pretty_version' => 'v2.2.11', + 'version' => '2.2.11.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-token/jwt-signature', + 'aliases' => array(), + 'reference' => '015b59aaf3b6e8fb9f5bd1338845b7464c7d8103', + 'dev_requirement' => false, + ), + 'web-token/jwt-signature-algorithm-ecdsa' => array( + 'pretty_version' => 'v2.2.11', + 'version' => '2.2.11.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-ecdsa', + 'aliases' => array(), + 'reference' => '44cbbb4374c51f1cf48b82ae761efbf24e1a8591', + 'dev_requirement' => false, + ), + 'web-token/jwt-signature-algorithm-eddsa' => array( + 'pretty_version' => 'v2.2.11', + 'version' => '2.2.11.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-eddsa', + 'aliases' => array(), + 'reference' => 'b805ecca593c56e60e0463bd2cacc9b1341910f6', + 'dev_requirement' => false, + ), + 'web-token/jwt-signature-algorithm-rsa' => array( + 'pretty_version' => 'v2.2.11', + 'version' => '2.2.11.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-rsa', + 'aliases' => array(), + 'reference' => '513ad90eb5ef1886ff176727a769bda4618141b0', + 'dev_requirement' => false, + ), + ), +); diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/.github/workflows/phpunit.yml b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/.github/workflows/phpunit.yml new file mode 100644 index 00000000..556e105d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/.github/workflows/phpunit.yml @@ -0,0 +1,35 @@ +name: PHPUnit + +on: + push: + branches: + - master + pull_request: + +jobs: + phpunit: + name: PHPUnit + runs-on: ubuntu-latest + strategy: + matrix: + php: + - '7.1' + - '7.2' + - '7.3' + - '7.4' + - '8.0' + - '8.1' + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + extensions: gmp, bcmath + tools: composer + - uses: actions/checkout@v2 + - name: Setup problem matchers + run: | + echo "::add-matcher::${{ runner.tool_cache }}/php.json" + echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + - run: composer install + - run: vendor/bin/phpunit diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/CHANGELOG.md b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/CHANGELOG.md new file mode 100644 index 00000000..f7b4663c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/CHANGELOG.md @@ -0,0 +1,55 @@ +#### v2.4.0 (2021-12) +* Drop support for PHP 7.0 [#89](https://github.com/fgrosse/PHPASN1/pull/89) + +#### v2.3.1 (2021-12) +* Add `#[\ReturnTypeWillChange]` attributes for PHP 8.1 compatibility [#87](https://github.com/fgrosse/PHPASN1/pull/87) + +#### v2.3.0 (2021-04) +* Allow creating an unsigned CSR and adding the signature later [#82](https://github.com/fgrosse/PHPASN1/pull/82) + +#### v2.2.0 (2020-08) +* support polyfills for bcmath and gmp, and add a composer.json + suggestion for the `phpseclib/bcmath_polyfill` for servers unable + to install PHP the gmp or bcmath extensions. + +#### v.2.1.1 & &v.2.0.2 (2018-12) +* add stricter validation around some structures, highlighed + by wycheproof test suite + +#### v.2.1.0 (2018-03) +* add support for `bcmath` extension (making `gmp` optional) [#68](https://github.com/fgrosse/PHPASN1/pull/68) + +#### v.2.0.1 & v.1.5.3 (2017-12) +* add .gitattributes file to prevent examples and tests to be installed via composer when --prefer-dist was set + +#### v.2.0.0 (2017-08) +* rename `FG\ASN1\Object` to `FG\ASN1\ASNObject` because `Object` is a special class name in the next major PHP release + - when you upgrade you have to adapt all corresponding `use` and `extends` statements as well as type hints and all + usages of `Object::fromBinary(…)`. +* generally drop PHP 5.6 support + +#### v.1.5.2 (2016-10-29) +* allow empty octet strings + +#### v.1.5.1 (2015-10-02) +* add keywords to composer.json (this is a version on its own so the keywords are found on a stable version at packagist.org) + +#### v.1.5.0 (2015-10-30) +* fix a bug that would prevent you from decoding context specific tags on multiple objects [#57](https://github.com/fgrosse/PHPASN1/issues/57) + - `ExplicitlyTaggedObject::__construct` does now accept multiple objects to be tagged with a single tag + - `ExplicitlyTaggedObject::getContent` will now always return an array (even if only one object is tagged) + +#### v.1.4.2 (2015-09-29) +* fix a bug that would prevent you from decoding empty tagged objects [#57](https://github.com/fgrosse/PHPASN1/issues/57) + +#### v.1.4.1 +* improve exception messages and general error handling [#55](https ://github.com/fgrosse/PHPASN1/pull/55) + +#### v.1.4.0 +* **require PHP 5.6** +* support big integers (closes #1 and #37) +* enforce one code style via [styleci.io][9] +* track code coverage via [coveralls.io][10] +* replace obsolete `FG\ASN1\Exception\GeneralException` with `\Exception` +* `Construct` (`Sequence`, `Set`) does now implement `ArrayAccess`, `Countable` and `Iterator` so its easier to use +* add [`TemplateParser`][11] diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/LICENSE b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/LICENSE new file mode 100644 index 00000000..1e17eb03 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012-2015 Friedrich Große + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/README.md b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/README.md new file mode 100644 index 00000000..6a1a18bf --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/README.md @@ -0,0 +1,167 @@ +PHPASN1 +======= + +[![Build Status](https://github.com/fgrosse/PHPASN1/actions/workflows/phpunit.yml/badge.svg)](https://github.com/fgrosse/PHPASN1/actions/workflows/phpunit.yml) +[![PHP 7 ready](http://php7ready.timesplinter.ch/fgrosse/PHPASN1/badge.svg)](https://travis-ci.org/fgrosse/PHPASN1) +[![Coverage Status](https://coveralls.io/repos/fgrosse/PHPASN1/badge.svg?branch=master&service=github)](https://coveralls.io/github/fgrosse/PHPASN1?branch=master) + +[![Latest Stable Version](https://poser.pugx.org/fgrosse/phpasn1/v/stable.png)](https://packagist.org/packages/fgrosse/phpasn1) +[![Total Downloads](https://poser.pugx.org/fgrosse/phpasn1/downloads.png)](https://packagist.org/packages/fgrosse/phpasn1) +[![Latest Unstable Version](https://poser.pugx.org/fgrosse/phpasn1/v/unstable.png)](https://packagist.org/packages/fgrosse/phpasn1) +[![License](https://poser.pugx.org/fgrosse/phpasn1/license.png)](https://packagist.org/packages/fgrosse/phpasn1) + +A PHP Framework that allows you to encode and decode arbitrary [ASN.1][3] structures +using the [ITU-T X.690 Encoding Rules][4]. +This encoding is very frequently used in [X.509 PKI environments][5] or the communication between heterogeneous computer systems. + +The API allows you to encode ASN.1 structures to create binary data such as certificate +signing requests (CSR), X.509 certificates or certificate revocation lists (CRL). +PHPASN1 can also read [BER encoded][6] binary data into separate PHP objects that can be manipulated by the user and reencoded afterwards. + +The **changelog** can now be found at [CHANGELOG.md](CHANGELOG.md). + +## Dependencies + +PHPASN1 requires at least `PHP 7.0` and either the `gmp` or `bcmath` extension. +Support for older PHP versions (i.e. PHP 5.6) was dropped starting with `v2.0`. +If you must use an outdated PHP version consider using [PHPASN v1.5][13]. + +For the loading of object identifier names directly from the web [curl][7] is used. + +## Installation + +The preferred way to install this library is to rely on [Composer][2]: + +```bash +$ composer require fgrosse/phpasn1 +``` + +## Usage + +### Encoding ASN.1 Structures + +PHPASN1 offers you a class for each of the implemented ASN.1 universal types. +The constructors should be pretty self explanatory so you should have no big trouble getting started. +All data will be encoded using [DER encoding][8] + +```php +use FG\ASN1\OID; +use FG\ASN1\Universal\Integer; +use FG\ASN1\Universal\Boolean; +use FG\ASN1\Universal\Enumerated; +use FG\ASN1\Universal\IA5String; +use FG\ASN1\Universal\ObjectIdentifier; +use FG\ASN1\Universal\PrintableString; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\Set; +use FG\ASN1\Universal\NullObject; + +$integer = new Integer(123456); +$boolean = new Boolean(true); +$enum = new Enumerated(1); +$ia5String = new IA5String('Hello world'); + +$asnNull = new NullObject(); +$objectIdentifier1 = new ObjectIdentifier('1.2.250.1.16.9'); +$objectIdentifier2 = new ObjectIdentifier(OID::RSA_ENCRYPTION); +$printableString = new PrintableString('Foo bar'); + +$sequence = new Sequence($integer, $boolean, $enum, $ia5String); +$set = new Set($sequence, $asnNull, $objectIdentifier1, $objectIdentifier2, $printableString); + +$myBinary = $sequence->getBinary(); +$myBinary .= $set->getBinary(); + +echo base64_encode($myBinary); +``` + + +### Decoding binary data + +Decoding BER encoded binary data is just as easy as encoding it: + +```php +use FG\ASN1\ASNObject; + +$base64String = ... +$binaryData = base64_decode($base64String); +$asnObject = ASNObject::fromBinary($binaryData); + + +// do stuff +``` + +If you already know exactly how your expected data should look like you can use the `FG\ASN1\TemplateParser`: + +```php +use FG\ASN1\TemplateParser; + +// first define your template +$template = [ + Identifier::SEQUENCE => [ + Identifier::SET => [ + Identifier::OBJECT_IDENTIFIER, + Identifier::SEQUENCE => [ + Identifier::INTEGER, + Identifier::BITSTRING, + ] + ] + ] +]; + +// if your binary data is not matching the template you provided this will throw an `\Exception`: +$parser = new TemplateParser(); +$object = $parser->parseBinary($data, $template); + +// there is also a convenience function if you parse binary data from base64: +$object = $parser->parseBase64($data, $template); +``` + +You can use this function to make sure your data has exactly the format you are expecting. + +### Navigating decoded data + +All constructed classes (i.e. `Sequence` and `Set`) can be navigated by array access or using an iterator. +You can find examples +[here](https://github.com/fgrosse/PHPASN1/blob/f6442cadda9d36f3518c737e32f28300a588b777/tests/ASN1/Universal/SequenceTest.php#L148-148), +[here](https://github.com/fgrosse/PHPASN1/blob/f6442cadda9d36f3518c737e32f28300a588b777/tests/ASN1/Universal/SequenceTest.php#L121) and +[here](https://github.com/fgrosse/PHPASN1/blob/f6442cadda9d36f3518c737e32f28300a588b777/tests/ASN1/TemplateParserTest.php#L45). + + +### Give me more examples! + +To see some example usage of the API classes or some generated output check out the [examples](https://github.com/fgrosse/PHPASN1/tree/master/examples). + + +### How do I contribute? + +If you found an issue or have a question submit a github issue with detailed information. + +In case you already know what caused the issue and feel in the mood to fix it, your code contributions are always welcome. Just fork the repository, implement your changes and make sure that you covered everything with tests. +Afterwards submit a pull request via github and be a little patient :) I usually try to comment and/or merge as soon as possible. + +#### Mailing list + +New features or questions can be discussed in [this google group/mailing list][12]. + +### Thanks + +To [all contributors][1] so far! + +## License + +This library is distributed under the [MIT License](LICENSE). + +[1]: https://github.com/fgrosse/PHPASN1/graphs/contributors +[2]: https://getcomposer.org/ +[3]: http://www.itu.int/ITU-T/asn1/ +[4]: http://www.itu.int/ITU-T/recommendations/rec.aspx?rec=x.690 +[5]: http://en.wikipedia.org/wiki/X.509 +[6]: http://en.wikipedia.org/wiki/X.690#BER_encoding +[7]: http://php.net/manual/en/book.curl.php +[8]: http://en.wikipedia.org/wiki/X.690#DER_encoding +[9]: https://styleci.io +[10]: https://coveralls.io/github/fgrosse/PHPASN1 +[11]: https://github.com/fgrosse/PHPASN1/blob/master/tests/ASN1/TemplateParserTest.php#L16 +[12]: https://groups.google.com/d/forum/phpasn1 +[13]: https://packagist.org/packages/fgrosse/phpasn1#1.5.2 diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/composer.json b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/composer.json new file mode 100644 index 00000000..00f7d070 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/composer.json @@ -0,0 +1,49 @@ +{ + "name": "fgrosse/phpasn1", + "description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.", + "type": "library", + "homepage": "https://github.com/FGrosse/PHPASN1", + "license": "MIT", + "authors": [ + { + "name": "Friedrich Große", + "email": "friedrich.grosse@gmail.com", + "homepage": "https://github.com/FGrosse", + "role": "Author" + }, + { + "name": "All contributors", + "homepage": "https://github.com/FGrosse/PHPASN1/contributors" + } + ], + "keywords": [ "x690", "x.690", "x.509", "x509", "asn1", "asn.1", "ber", "der", "binary", "encoding", "decoding" ], + + "require": { + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.3 || ^7.0 || ^8.0", + "php-coveralls/php-coveralls": "~2.0" + }, + "suggest": { + "ext-gmp": "GMP is the preferred extension for big integer calculations", + "ext-bcmath": "BCmath is the fallback extension for big integer calculations", + "phpseclib/bcmath_compat": "BCmath polyfill for servers where neither GMP nor BCmath is available", + "ext-curl": "For loading OID information from the web if they have not bee defined statically" + }, + "autoload": { + "psr-4": { + "FG\\": "lib/" + } + }, + "autoload-dev": { + "psr-4": { + "FG\\Test\\": "tests/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php new file mode 100644 index 00000000..3b7f1621 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php @@ -0,0 +1,355 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use FG\ASN1\Exception\ParserException; +use FG\ASN1\Universal\BitString; +use FG\ASN1\Universal\Boolean; +use FG\ASN1\Universal\Enumerated; +use FG\ASN1\Universal\GeneralizedTime; +use FG\ASN1\Universal\Integer; +use FG\ASN1\Universal\NullObject; +use FG\ASN1\Universal\ObjectIdentifier; +use FG\ASN1\Universal\RelativeObjectIdentifier; +use FG\ASN1\Universal\OctetString; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\Set; +use FG\ASN1\Universal\UTCTime; +use FG\ASN1\Universal\IA5String; +use FG\ASN1\Universal\PrintableString; +use FG\ASN1\Universal\NumericString; +use FG\ASN1\Universal\UTF8String; +use FG\ASN1\Universal\UniversalString; +use FG\ASN1\Universal\CharacterString; +use FG\ASN1\Universal\GeneralString; +use FG\ASN1\Universal\VisibleString; +use FG\ASN1\Universal\GraphicString; +use FG\ASN1\Universal\BMPString; +use FG\ASN1\Universal\T61String; +use FG\ASN1\Universal\ObjectDescriptor; +use FG\Utility\BigInteger; +use LogicException; + +/** + * Class ASNObject is the base class for all concrete ASN.1 objects. + */ +abstract class ASNObject implements Parsable +{ + private $contentLength; + private $nrOfLengthOctets; + + /** + * Must return the number of octets of the content part. + * + * @return int + */ + abstract protected function calculateContentLength(); + + /** + * Encode the object using DER encoding. + * + * @see http://en.wikipedia.org/wiki/X.690#DER_encoding + * + * @return string the binary representation of an objects value + */ + abstract protected function getEncodedValue(); + + /** + * Return the content of this object in a non encoded form. + * This can be used to print the value in human readable form. + * + * @return mixed + */ + abstract public function getContent(); + + /** + * Return the object type octet. + * This should use the class constants of Identifier. + * + * @see Identifier + * + * @return int + */ + abstract public function getType(); + + /** + * Returns all identifier octets. If an inheriting class models a tag with + * the long form identifier format, it MUST reimplement this method to + * return all octets of the identifier. + * + * @throws LogicException If the identifier format is long form + * + * @return string Identifier as a set of octets + */ + public function getIdentifier() + { + $firstOctet = $this->getType(); + + if (Identifier::isLongForm($firstOctet)) { + throw new LogicException(sprintf('Identifier of %s uses the long form and must therefor override "ASNObject::getIdentifier()".', get_class($this))); + } + + return chr($firstOctet); + } + + /** + * Encode this object using DER encoding. + * + * @return string the full binary representation of the complete object + */ + public function getBinary() + { + $result = $this->getIdentifier(); + $result .= $this->createLengthPart(); + $result .= $this->getEncodedValue(); + + return $result; + } + + private function createLengthPart() + { + $contentLength = $this->getContentLength(); + $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength); + + if ($nrOfLengthOctets == 1) { + return chr($contentLength); + } else { + // the first length octet determines the number subsequent length octets + $lengthOctets = chr(0x80 | ($nrOfLengthOctets - 1)); + for ($shiftLength = 8 * ($nrOfLengthOctets - 2); $shiftLength >= 0; $shiftLength -= 8) { + $lengthOctets .= chr($contentLength >> $shiftLength); + } + + return $lengthOctets; + } + } + + protected function getNumberOfLengthOctets($contentLength = null) + { + if (!isset($this->nrOfLengthOctets)) { + if ($contentLength == null) { + $contentLength = $this->getContentLength(); + } + + $this->nrOfLengthOctets = 1; + if ($contentLength > 127) { + do { // long form + $this->nrOfLengthOctets++; + $contentLength = $contentLength >> 8; + } while ($contentLength > 0); + } + } + + return $this->nrOfLengthOctets; + } + + protected function getContentLength() + { + if (!isset($this->contentLength)) { + $this->contentLength = $this->calculateContentLength(); + } + + return $this->contentLength; + } + + protected function setContentLength($newContentLength) + { + $this->contentLength = $newContentLength; + $this->getNumberOfLengthOctets($newContentLength); + } + + /** + * Returns the length of the whole object (including the identifier and length octets). + */ + public function getObjectLength() + { + $nrOfIdentifierOctets = strlen($this->getIdentifier()); + $contentLength = $this->getContentLength(); + $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength); + + return $nrOfIdentifierOctets + $nrOfLengthOctets + $contentLength; + } + + public function __toString() + { + return $this->getContent(); + } + + /** + * Returns the name of the ASN.1 Type of this object. + * + * @see Identifier::getName() + */ + public function getTypeName() + { + return Identifier::getName($this->getType()); + } + + /** + * @param string $binaryData + * @param int $offsetIndex + * + * @throws ParserException + * + * @return \FG\ASN1\ASNObject + */ + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + if (strlen($binaryData) <= $offsetIndex) { + throw new ParserException('Can not parse binary from data: Offset index larger than input size', $offsetIndex); + } + + $identifierOctet = ord($binaryData[$offsetIndex]); + if (Identifier::isContextSpecificClass($identifierOctet) && Identifier::isConstructed($identifierOctet)) { + return ExplicitlyTaggedObject::fromBinary($binaryData, $offsetIndex); + } + + switch ($identifierOctet) { + case Identifier::BITSTRING: + return BitString::fromBinary($binaryData, $offsetIndex); + case Identifier::BOOLEAN: + return Boolean::fromBinary($binaryData, $offsetIndex); + case Identifier::ENUMERATED: + return Enumerated::fromBinary($binaryData, $offsetIndex); + case Identifier::INTEGER: + return Integer::fromBinary($binaryData, $offsetIndex); + case Identifier::NULL: + return NullObject::fromBinary($binaryData, $offsetIndex); + case Identifier::OBJECT_IDENTIFIER: + return ObjectIdentifier::fromBinary($binaryData, $offsetIndex); + case Identifier::RELATIVE_OID: + return RelativeObjectIdentifier::fromBinary($binaryData, $offsetIndex); + case Identifier::OCTETSTRING: + return OctetString::fromBinary($binaryData, $offsetIndex); + case Identifier::SEQUENCE: + return Sequence::fromBinary($binaryData, $offsetIndex); + case Identifier::SET: + return Set::fromBinary($binaryData, $offsetIndex); + case Identifier::UTC_TIME: + return UTCTime::fromBinary($binaryData, $offsetIndex); + case Identifier::GENERALIZED_TIME: + return GeneralizedTime::fromBinary($binaryData, $offsetIndex); + case Identifier::IA5_STRING: + return IA5String::fromBinary($binaryData, $offsetIndex); + case Identifier::PRINTABLE_STRING: + return PrintableString::fromBinary($binaryData, $offsetIndex); + case Identifier::NUMERIC_STRING: + return NumericString::fromBinary($binaryData, $offsetIndex); + case Identifier::UTF8_STRING: + return UTF8String::fromBinary($binaryData, $offsetIndex); + case Identifier::UNIVERSAL_STRING: + return UniversalString::fromBinary($binaryData, $offsetIndex); + case Identifier::CHARACTER_STRING: + return CharacterString::fromBinary($binaryData, $offsetIndex); + case Identifier::GENERAL_STRING: + return GeneralString::fromBinary($binaryData, $offsetIndex); + case Identifier::VISIBLE_STRING: + return VisibleString::fromBinary($binaryData, $offsetIndex); + case Identifier::GRAPHIC_STRING: + return GraphicString::fromBinary($binaryData, $offsetIndex); + case Identifier::BMP_STRING: + return BMPString::fromBinary($binaryData, $offsetIndex); + case Identifier::T61_STRING: + return T61String::fromBinary($binaryData, $offsetIndex); + case Identifier::OBJECT_DESCRIPTOR: + return ObjectDescriptor::fromBinary($binaryData, $offsetIndex); + default: + // At this point the identifier may be >1 byte. + if (Identifier::isConstructed($identifierOctet)) { + return new UnknownConstructedObject($binaryData, $offsetIndex); + } else { + $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex); + $lengthOfUnknownObject = self::parseContentLength($binaryData, $offsetIndex); + $offsetIndex += $lengthOfUnknownObject; + + return new UnknownObject($identifier, $lengthOfUnknownObject); + } + } + } + + protected static function parseIdentifier($identifierOctet, $expectedIdentifier, $offsetForExceptionHandling) + { + if (is_string($identifierOctet) || is_numeric($identifierOctet) == false) { + $identifierOctet = ord($identifierOctet); + } + + if ($identifierOctet != $expectedIdentifier) { + $message = 'Can not create an '.Identifier::getName($expectedIdentifier).' from an '.Identifier::getName($identifierOctet); + throw new ParserException($message, $offsetForExceptionHandling); + } + } + + protected static function parseBinaryIdentifier($binaryData, &$offsetIndex) + { + if (strlen($binaryData) <= $offsetIndex) { + throw new ParserException('Can not parse identifier from data: Offset index larger than input size', $offsetIndex); + } + + $identifier = $binaryData[$offsetIndex++]; + + if (Identifier::isLongForm(ord($identifier)) == false) { + return $identifier; + } + + while (true) { + if (strlen($binaryData) <= $offsetIndex) { + throw new ParserException('Can not parse identifier (long form) from data: Offset index larger than input size', $offsetIndex); + } + $nextOctet = $binaryData[$offsetIndex++]; + $identifier .= $nextOctet; + + if ((ord($nextOctet) & 0x80) === 0) { + // the most significant bit is 0 to we have reached the end of the identifier + break; + } + } + + return $identifier; + } + + protected static function parseContentLength(&$binaryData, &$offsetIndex, $minimumLength = 0) + { + if (strlen($binaryData) <= $offsetIndex) { + throw new ParserException('Can not parse content length from data: Offset index larger than input size', $offsetIndex); + } + + $contentLength = ord($binaryData[$offsetIndex++]); + if (($contentLength & 0x80) != 0) { + // bit 8 is set -> this is the long form + $nrOfLengthOctets = $contentLength & 0x7F; + $contentLength = BigInteger::create(0x00); + for ($i = 0; $i < $nrOfLengthOctets; $i++) { + if (strlen($binaryData) <= $offsetIndex) { + throw new ParserException('Can not parse content length (long form) from data: Offset index larger than input size', $offsetIndex); + } + $contentLength = $contentLength->shiftLeft(8)->add(ord($binaryData[$offsetIndex++])); + } + + if ($contentLength->compare(PHP_INT_MAX) > 0) { + throw new ParserException("Can not parse content length from data: length > maximum integer", $offsetIndex); + } + + $contentLength = $contentLength->toInteger(); + } + + if ($contentLength < $minimumLength) { + throw new ParserException('A '.get_called_class()." should have a content length of at least {$minimumLength}. Extracted length was {$contentLength}", $offsetIndex); + } + + $lenDataRemaining = strlen($binaryData) - $offsetIndex; + + if ($lenDataRemaining < $contentLength) { + throw new ParserException("Content length {$contentLength} exceeds remaining data length {$lenDataRemaining}", $offsetIndex); + } + + return $contentLength; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php new file mode 100644 index 00000000..7e0d7ddb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use Exception; + +abstract class AbstractString extends ASNObject implements Parsable +{ + /** @var string */ + protected $value; + private $checkStringForIllegalChars = true; + private $allowedCharacters = []; + + /** + * The abstract base class for ASN.1 classes which represent some string of character. + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + } + + public function getContent() + { + return $this->value; + } + + protected function allowCharacter($character) + { + $this->allowedCharacters[] = $character; + } + + protected function allowCharacters(...$characters) + { + foreach ($characters as $character) { + $this->allowedCharacters[] = $character; + } + } + + protected function allowNumbers() + { + foreach (range('0', '9') as $char) { + $this->allowedCharacters[] = (string) $char; + } + } + + protected function allowAllLetters() + { + $this->allowSmallLetters(); + $this->allowCapitalLetters(); + } + + protected function allowSmallLetters() + { + foreach (range('a', 'z') as $char) { + $this->allowedCharacters[] = $char; + } + } + + protected function allowCapitalLetters() + { + foreach (range('A', 'Z') as $char) { + $this->allowedCharacters[] = $char; + } + } + + protected function allowSpaces() + { + $this->allowedCharacters[] = ' '; + } + + protected function allowAll() + { + $this->checkStringForIllegalChars = false; + } + + protected function calculateContentLength() + { + return strlen($this->value); + } + + protected function getEncodedValue() + { + if ($this->checkStringForIllegalChars) { + $this->checkString(); + } + + return $this->value; + } + + protected function checkString() + { + $stringLength = $this->getContentLength(); + for ($i = 0; $i < $stringLength; $i++) { + if (in_array($this->value[$i], $this->allowedCharacters) == false) { + $typeName = Identifier::getName($this->getType()); + throw new Exception("Could not create a {$typeName} from the character sequence '{$this->value}'."); + } + } + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + $parsedObject = new static(''); + + self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + $string = substr($binaryData, $offsetIndex, $contentLength); + $offsetIndex += $contentLength; + + $parsedObject->value = $string; + $parsedObject->setContentLength($contentLength); + return $parsedObject; + } + + public static function isValid($string) + { + $testObject = new static($string); + try { + $testObject->checkString(); + + return true; + } catch (Exception $exception) { + return false; + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php new file mode 100644 index 00000000..9fad5051 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use DateInterval; +use DateTime; +use DateTimeZone; +use Exception; + +abstract class AbstractTime extends ASNObject +{ + /** @var DateTime */ + protected $value; + + public function __construct($dateTime = null, $dateTimeZone = 'UTC') + { + if ($dateTime == null || is_string($dateTime)) { + $timeZone = new DateTimeZone($dateTimeZone); + $dateTimeObject = new DateTime($dateTime, $timeZone); + if ($dateTimeObject == false) { + $errorMessage = $this->getLastDateTimeErrors(); + $className = Identifier::getName($this->getType()); + throw new Exception(sprintf("Could not create %s from date time string '%s': %s", $className, $dateTime, $errorMessage)); + } + $dateTime = $dateTimeObject; + } elseif (!$dateTime instanceof DateTime) { + throw new Exception('Invalid first argument for some instance of AbstractTime constructor'); + } + + $this->value = $dateTime; + } + + public function getContent() + { + return $this->value; + } + + protected function getLastDateTimeErrors() + { + $messages = ''; + $lastErrors = DateTime::getLastErrors(); + foreach ($lastErrors['errors'] as $errorMessage) { + $messages .= "{$errorMessage}, "; + } + + return substr($messages, 0, -2); + } + + public function __toString() + { + return $this->value->format("Y-m-d\tH:i:s"); + } + + protected static function extractTimeZoneData(&$binaryData, &$offsetIndex, DateTime $dateTime) + { + $sign = $binaryData[$offsetIndex++]; + $timeOffsetHours = intval(substr($binaryData, $offsetIndex, 2)); + $timeOffsetMinutes = intval(substr($binaryData, $offsetIndex + 2, 2)); + $offsetIndex += 4; + + $interval = new DateInterval("PT{$timeOffsetHours}H{$timeOffsetMinutes}M"); + if ($sign == '+') { + $dateTime->sub($interval); + } else { + $dateTime->add($interval); + } + + return $dateTime; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php new file mode 100644 index 00000000..119ee7b9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php @@ -0,0 +1,63 @@ +modulus(0x80)->toInteger()); + + $value = $value->shiftRight(7); + while ($value->compare(0) > 0) { + $octets .= chr(0x80 | $value->modulus(0x80)->toInteger()); + $value = $value->shiftRight(7); + } + + return strrev($octets); + } + + /** + * @param string $octets + * + * @throws InvalidArgumentException if the given octets represent a malformed base-128 value or the decoded value would exceed the the maximum integer length + * + * @return int + */ + public static function decode($octets) + { + $bitsPerOctet = 7; + $value = BigInteger::create(0); + $i = 0; + + while (true) { + if (!isset($octets[$i])) { + throw new InvalidArgumentException(sprintf('Malformed base-128 encoded value (0x%s).', strtoupper(bin2hex($octets)) ?: '0')); + } + + $octet = ord($octets[$i++]); + + $l1 = $value->shiftLeft($bitsPerOctet); + $r1 = $octet & 0x7f; + $value = $l1->add($r1); + + if (0 === ($octet & 0x80)) { + break; + } + } + + return (string)$value; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php new file mode 100644 index 00000000..3f4027c2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Composite; + +use FG\ASN1\ASNObject; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\ObjectIdentifier; + +class AttributeTypeAndValue extends Sequence +{ + /** + * @param ObjectIdentifier|string $objIdentifier + * @param \FG\ASN1\ASNObject $value + */ + public function __construct($objIdentifier, ASNObject $value) + { + if ($objIdentifier instanceof ObjectIdentifier == false) { + $objIdentifier = new ObjectIdentifier($objIdentifier); + } + parent::__construct($objIdentifier, $value); + } + + public function __toString() + { + return $this->children[0].': '.$this->children[1]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php new file mode 100644 index 00000000..e95e7acd --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Composite; + +use FG\ASN1\Universal\PrintableString; +use FG\ASN1\Universal\IA5String; +use FG\ASN1\Universal\UTF8String; + +class RDNString extends RelativeDistinguishedName +{ + /** + * @param string|\FG\ASN1\Universal\ObjectIdentifier $objectIdentifierString + * @param string|\FG\ASN1\ASNObject $value + */ + public function __construct($objectIdentifierString, $value) + { + if (PrintableString::isValid($value)) { + $value = new PrintableString($value); + } else { + if (IA5String::isValid($value)) { + $value = new IA5String($value); + } else { + $value = new UTF8String($value); + } + } + + parent::__construct($objectIdentifierString, $value); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php new file mode 100644 index 00000000..4185f41a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Composite; + +use FG\ASN1\Exception\NotImplementedException; +use FG\ASN1\ASNObject; +use FG\ASN1\Universal\Set; + +class RelativeDistinguishedName extends Set +{ + /** + * @param string|\FG\ASN1\Universal\ObjectIdentifier $objIdentifierString + * @param \FG\ASN1\ASNObject $value + */ + public function __construct($objIdentifierString, ASNObject $value) + { + // TODO: This does only support one element in the RelativeDistinguishedName Set but it it is defined as follows: + // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue + parent::__construct(new AttributeTypeAndValue($objIdentifierString, $value)); + } + + public function getContent() + { + /** @var \FG\ASN1\ASNObject $firstObject */ + $firstObject = $this->children[0]; + return $firstObject->__toString(); + } + + /** + * At the current version this code can not work since the implementation of Construct requires + * the class to support a constructor without arguments. + * + * @deprecated this function is not yet implemented! Feel free to submit a pull request on github + * @param string $binaryData + * @param int $offsetIndex + * @throws NotImplementedException + */ + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + throw new NotImplementedException(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php new file mode 100644 index 00000000..cedf422e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use ArrayAccess; +use ArrayIterator; +use Countable; +use FG\ASN1\Exception\ParserException; +use Iterator; + +abstract class Construct extends ASNObject implements Countable, ArrayAccess, Iterator, Parsable +{ + /** @var \FG\ASN1\ASNObject[] */ + protected $children; + private $iteratorPosition; + + /** + * @param \FG\ASN1\ASNObject[] $children the variadic type hint is commented due to https://github.com/facebook/hhvm/issues/4858 + */ + public function __construct(/* HH_FIXME[4858]: variadic + strict */ ...$children) + { + $this->children = $children; + $this->iteratorPosition = 0; + } + + public function getContent() + { + return $this->children; + } + + #[\ReturnTypeWillChange] + public function rewind() + { + $this->iteratorPosition = 0; + } + + #[\ReturnTypeWillChange] + public function current() + { + return $this->children[$this->iteratorPosition]; + } + + #[\ReturnTypeWillChange] + public function key() + { + return $this->iteratorPosition; + } + + #[\ReturnTypeWillChange] + public function next() + { + $this->iteratorPosition++; + } + + #[\ReturnTypeWillChange] + public function valid() + { + return isset($this->children[$this->iteratorPosition]); + } + + #[\ReturnTypeWillChange] + public function offsetExists($offset) + { + return array_key_exists($offset, $this->children); + } + + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->children[$offset]; + } + + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + if ($offset === null) { + $offset = count($this->children); + } + + $this->children[$offset] = $value; + } + + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + unset($this->children[$offset]); + } + + protected function calculateContentLength() + { + $length = 0; + foreach ($this->children as $component) { + $length += $component->getObjectLength(); + } + + return $length; + } + + protected function getEncodedValue() + { + $result = ''; + foreach ($this->children as $component) { + $result .= $component->getBinary(); + } + + return $result; + } + + public function addChild(ASNObject $child) + { + $this->children[] = $child; + } + + public function addChildren(array $children) + { + foreach ($children as $child) { + $this->addChild($child); + } + } + + public function __toString() + { + $nrOfChildren = $this->getNumberOfChildren(); + $childString = $nrOfChildren == 1 ? 'child' : 'children'; + + return "[{$nrOfChildren} {$childString}]"; + } + + public function getNumberOfChildren() + { + return count($this->children); + } + + /** + * @return \FG\ASN1\ASNObject[] + */ + public function getChildren() + { + return $this->children; + } + + /** + * @return \FG\ASN1\ASNObject + */ + public function getFirstChild() + { + return $this->children[0]; + } + + /** + * @param string $binaryData + * @param int $offsetIndex + * + * @throws Exception\ParserException + * + * @return Construct|static + */ + #[\ReturnTypeWillChange] + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + $parsedObject = new static(); + self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + $startIndex = $offsetIndex; + + $children = []; + $octetsToRead = $contentLength; + while ($octetsToRead > 0) { + $newChild = ASNObject::fromBinary($binaryData, $offsetIndex); + $octetsToRead -= $newChild->getObjectLength(); + $children[] = $newChild; + } + + if ($octetsToRead !== 0) { + throw new ParserException("Sequence length incorrect", $startIndex); + } + + $parsedObject->addChildren($children); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } + + #[\ReturnTypeWillChange] + public function count($mode = COUNT_NORMAL) + { + return count($this->children, $mode); + } + + public function getIterator() + { + return new ArrayIterator($this->children); + } +} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php new file mode 100644 index 00000000..c9f8e82e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Exception; + +class NotImplementedException extends \Exception +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php new file mode 100644 index 00000000..4bda4e87 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Exception; + +class ParserException extends \Exception +{ + private $errorMessage; + private $offset; + + public function __construct($errorMessage, $offset) + { + $this->errorMessage = $errorMessage; + $this->offset = $offset; + parent::__construct("ASN.1 Parser Exception at offset {$this->offset}: {$this->errorMessage}"); + } + + public function getOffset() + { + return $this->offset; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php new file mode 100644 index 00000000..b947a959 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use FG\ASN1\Exception\ParserException; + +/** + * Class ExplicitlyTaggedObject decorate an inner object with an additional tag that gives information about + * its context specific meaning. + * + * Explanation taken from A Layman's Guide to a Subset of ASN.1, BER, and DER: + * >>> An RSA Laboratories Technical Note + * >>> Burton S. Kaliski Jr. + * >>> Revised November 1, 1993 + * + * [...] + * Explicitly tagged types are derived from other types by adding an outer tag to the underlying type. + * In effect, explicitly tagged types are structured types consisting of one component, the underlying type. + * Explicit tagging is denoted by the ASN.1 keywords [class number] EXPLICIT (see Section 5.2). + * [...] + * + * @see http://luca.ntop.org/Teaching/Appunti/asn1.html + */ +class ExplicitlyTaggedObject extends ASNObject +{ + /** @var \FG\ASN1\ASNObject[] */ + private $decoratedObjects; + private $tag; + + /** + * @param int $tag + * @param \FG\ASN1\ASNObject $objects,... + */ + public function __construct($tag, /* HH_FIXME[4858]: variadic + strict */ ...$objects) + { + $this->tag = $tag; + $this->decoratedObjects = $objects; + } + + protected function calculateContentLength() + { + $length = 0; + foreach ($this->decoratedObjects as $object) { + $length += $object->getObjectLength(); + } + + return $length; + } + + protected function getEncodedValue() + { + $encoded = ''; + foreach ($this->decoratedObjects as $object) { + $encoded .= $object->getBinary(); + } + + return $encoded; + } + + public function getContent() + { + return $this->decoratedObjects; + } + + public function __toString() + { + switch ($length = count($this->decoratedObjects)) { + case 0: + return "Context specific empty object with tag [{$this->tag}]"; + case 1: + $decoratedType = Identifier::getShortName($this->decoratedObjects[0]->getType()); + return "Context specific $decoratedType with tag [{$this->tag}]"; + default: + return "$length context specific objects with tag [{$this->tag}]"; + } + } + + public function getType() + { + return ord($this->getIdentifier()); + } + + public function getIdentifier() + { + $identifier = Identifier::create(Identifier::CLASS_CONTEXT_SPECIFIC, true, $this->tag); + + return is_int($identifier) ? chr($identifier) : $identifier; + } + + public function getTag() + { + return $this->tag; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex); + $firstIdentifierOctet = ord($identifier); + assert(Identifier::isContextSpecificClass($firstIdentifierOctet), 'identifier octet should indicate context specific class'); + assert(Identifier::isConstructed($firstIdentifierOctet), 'identifier octet should indicate constructed object'); + $tag = Identifier::getTagNumber($identifier); + + $totalContentLength = self::parseContentLength($binaryData, $offsetIndex); + $remainingContentLength = $totalContentLength; + + $offsetIndexOfDecoratedObject = $offsetIndex; + $decoratedObjects = []; + + while ($remainingContentLength > 0) { + $nextObject = ASNObject::fromBinary($binaryData, $offsetIndex); + $remainingContentLength -= $nextObject->getObjectLength(); + $decoratedObjects[] = $nextObject; + } + + if ($remainingContentLength != 0) { + throw new ParserException("Context-Specific explicitly tagged object [$tag] starting at offset $offsetIndexOfDecoratedObject specifies a length of $totalContentLength octets but $remainingContentLength remain after parsing the content", $offsetIndexOfDecoratedObject); + } + + $parsedObject = new self($tag, ...$decoratedObjects); + $parsedObject->setContentLength($totalContentLength); + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php new file mode 100644 index 00000000..b21caa34 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php @@ -0,0 +1,339 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use Exception; + +/** + * The Identifier encodes the ASN.1 tag (class and number) of the type of a data value. + * + * Every identifier whose number is in the range 0 to 30 has the following structure: + * + * Bits: 8 7 6 5 4 3 2 1 + * | Class | P/C | Tag number | + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Bits 8 and 7 define the class of this type ( Universal, Application, Context-specific or Private). + * Bit 6 encoded whether this type is primitive or constructed + * The remaining bits 5 - 1 encode the tag number + */ +class Identifier +{ + const CLASS_UNIVERSAL = 0x00; + const CLASS_APPLICATION = 0x01; + const CLASS_CONTEXT_SPECIFIC = 0x02; + const CLASS_PRIVATE = 0x03; + + const EOC = 0x00; // unsupported for now + const BOOLEAN = 0x01; + const INTEGER = 0x02; + const BITSTRING = 0x03; + const OCTETSTRING = 0x04; + const NULL = 0x05; + const OBJECT_IDENTIFIER = 0x06; + const OBJECT_DESCRIPTOR = 0x07; + const EXTERNAL = 0x08; // unsupported for now + const REAL = 0x09; // unsupported for now + const ENUMERATED = 0x0A; + const EMBEDDED_PDV = 0x0B; // unsupported for now + const UTF8_STRING = 0x0C; + const RELATIVE_OID = 0x0D; + // value 0x0E and 0x0F are reserved for future use + + const SEQUENCE = 0x30; + const SET = 0x31; + const NUMERIC_STRING = 0x12; + const PRINTABLE_STRING = 0x13; + const T61_STRING = 0x14; // sometimes referred to as TeletextString + const VIDEOTEXT_STRING = 0x15; + const IA5_STRING = 0x16; + const UTC_TIME = 0x17; + const GENERALIZED_TIME = 0x18; + const GRAPHIC_STRING = 0x19; + const VISIBLE_STRING = 0x1A; + const GENERAL_STRING = 0x1B; + const UNIVERSAL_STRING = 0x1C; + const CHARACTER_STRING = 0x1D; // Unrestricted character type + const BMP_STRING = 0x1E; + + const LONG_FORM = 0x1F; + const IS_CONSTRUCTED = 0x20; + + /** + * Creates an identifier. Short form identifiers are returned as integers + * for BC, long form identifiers will be returned as a string of octets. + * + * @param int $class + * @param bool $isConstructed + * @param int $tagNumber + * + * @throws Exception if the given arguments are invalid + * + * @return int|string + */ + public static function create($class, $isConstructed, $tagNumber) + { + if (!is_numeric($class) || $class < self::CLASS_UNIVERSAL || $class > self::CLASS_PRIVATE) { + throw new Exception(sprintf('Invalid class %d given', $class)); + } + + if (!is_bool($isConstructed)) { + throw new Exception("\$isConstructed must be a boolean value ($isConstructed given)"); + } + + $tagNumber = self::makeNumeric($tagNumber); + if ($tagNumber < 0) { + throw new Exception(sprintf('Invalid $tagNumber %d given. You can only use positive integers.', $tagNumber)); + } + + if ($tagNumber < self::LONG_FORM) { + return ($class << 6) | ($isConstructed << 5) | $tagNumber; + } + + $firstOctet = ($class << 6) | ($isConstructed << 5) | self::LONG_FORM; + + // Tag numbers formatted in long form are base-128 encoded. See X.609#8.1.2.4 + return chr($firstOctet).Base128::encode($tagNumber); + } + + public static function isConstructed($identifierOctet) + { + return ($identifierOctet & self::IS_CONSTRUCTED) === self::IS_CONSTRUCTED; + } + + public static function isLongForm($identifierOctet) + { + return ($identifierOctet & self::LONG_FORM) === self::LONG_FORM; + } + + /** + * Return the name of the mapped ASN.1 type with a preceding "ASN.1 ". + * + * Example: ASN.1 Octet String + * + * @see Identifier::getShortName() + * + * @param int|string $identifier + * + * @return string + */ + public static function getName($identifier) + { + $identifierOctet = self::makeNumeric($identifier); + + $typeName = static::getShortName($identifier); + + if (($identifierOctet & self::LONG_FORM) < self::LONG_FORM) { + $typeName = "ASN.1 {$typeName}"; + } + + return $typeName; + } + + /** + * Return the short version of the type name. + * + * If the given identifier octet can be mapped to a known universal type this will + * return its name. Else Identifier::getClassDescription() is used to retrieve + * information about the identifier. + * + * @see Identifier::getName() + * @see Identifier::getClassDescription() + * + * @param int|string $identifier + * + * @return string + */ + public static function getShortName($identifier) + { + $identifierOctet = self::makeNumeric($identifier); + + switch ($identifierOctet) { + case self::EOC: + return 'End-of-contents octet'; + case self::BOOLEAN: + return 'Boolean'; + case self::INTEGER: + return 'Integer'; + case self::BITSTRING: + return 'Bit String'; + case self::OCTETSTRING: + return 'Octet String'; + case self::NULL: + return 'NULL'; + case self::OBJECT_IDENTIFIER: + return 'Object Identifier'; + case self::OBJECT_DESCRIPTOR: + return 'Object Descriptor'; + case self::EXTERNAL: + return 'External Type'; + case self::REAL: + return 'Real'; + case self::ENUMERATED: + return 'Enumerated'; + case self::EMBEDDED_PDV: + return 'Embedded PDV'; + case self::UTF8_STRING: + return 'UTF8 String'; + case self::RELATIVE_OID: + return 'Relative OID'; + case self::SEQUENCE: + return 'Sequence'; + case self::SET: + return 'Set'; + case self::NUMERIC_STRING: + return 'Numeric String'; + case self::PRINTABLE_STRING: + return 'Printable String'; + case self::T61_STRING: + return 'T61 String'; + case self::VIDEOTEXT_STRING: + return 'Videotext String'; + case self::IA5_STRING: + return 'IA5 String'; + case self::UTC_TIME: + return 'UTC Time'; + case self::GENERALIZED_TIME: + return 'Generalized Time'; + case self::GRAPHIC_STRING: + return 'Graphic String'; + case self::VISIBLE_STRING: + return 'Visible String'; + case self::GENERAL_STRING: + return 'General String'; + case self::UNIVERSAL_STRING: + return 'Universal String'; + case self::CHARACTER_STRING: + return 'Character String'; + case self::BMP_STRING: + return 'BMP String'; + + case 0x0E: + return 'RESERVED (0x0E)'; + case 0x0F: + return 'RESERVED (0x0F)'; + + case self::LONG_FORM: + default: + $classDescription = self::getClassDescription($identifier); + + if (is_int($identifier)) { + $identifier = chr($identifier); + } + + return "$classDescription (0x".strtoupper(bin2hex($identifier)).')'; + } + } + + /** + * Returns a textual description of the information encoded in a given identifier octet. + * + * The first three (most significant) bytes are evaluated to determine if this is a + * constructed or primitive type and if it is either universal, application, context-specific or + * private. + * + * Example: + * Constructed context-specific + * Primitive universal + * + * @param int|string $identifier + * + * @return string + */ + public static function getClassDescription($identifier) + { + $identifierOctet = self::makeNumeric($identifier); + + if (self::isConstructed($identifierOctet)) { + $classDescription = 'Constructed '; + } else { + $classDescription = 'Primitive '; + } + $classBits = $identifierOctet >> 6; + switch ($classBits) { + case self::CLASS_UNIVERSAL: + $classDescription .= 'universal'; + break; + case self::CLASS_APPLICATION: + $classDescription .= 'application'; + break; + case self::CLASS_CONTEXT_SPECIFIC: + $tagNumber = self::getTagNumber($identifier); + $classDescription = "[$tagNumber] Context-specific"; + break; + case self::CLASS_PRIVATE: + $classDescription .= 'private'; + break; + + default: + return "INVALID IDENTIFIER OCTET: {$identifierOctet}"; + } + + return $classDescription; + } + + /** + * @param int|string $identifier + * + * @return int + */ + public static function getTagNumber($identifier) + { + $firstOctet = self::makeNumeric($identifier); + $tagNumber = $firstOctet & self::LONG_FORM; + + if ($tagNumber < self::LONG_FORM) { + return $tagNumber; + } + + if (is_numeric($identifier)) { + $identifier = chr($identifier); + } + return Base128::decode(substr($identifier, 1)); + } + + public static function isUniversalClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_UNIVERSAL; + } + + public static function isApplicationClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_APPLICATION; + } + + public static function isContextSpecificClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_CONTEXT_SPECIFIC; + } + + public static function isPrivateClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_PRIVATE; + } + + private static function makeNumeric($identifierOctet) + { + if (!is_numeric($identifierOctet)) { + return ord($identifierOctet); + } else { + return $identifierOctet; + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/OID.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/OID.php new file mode 100644 index 00000000..7d331b0a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/OID.php @@ -0,0 +1,199 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +class OID +{ + const RSA_ENCRYPTION = '1.2.840.113549.1.1.1'; + const MD5_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.4'; + const SHA1_WITH_RSA_SIGNATURE = '1.2.840.113549.1.1.5'; + const SHA256_WITH_RSA_SIGNATURE = '1.2.840.113549.1.1.11'; + const PKCS9_EMAIL = '1.2.840.113549.1.9.1'; + const PKCS9_UNSTRUCTURED_NAME = '1.2.840.113549.1.9.2'; + const PKCS9_CONTENT_TYPE = '1.2.840.113549.1.9.3'; + const PKCS9_MESSAGE_DIGEST = '1.2.840.113549.1.9.4'; + const PKCS9_SIGNING_TIME = '1.2.840.113549.1.9.5'; + const PKCS9_EXTENSION_REQUEST = '1.2.840.113549.1.9.14'; + + // certificate extension identifier + const CERT_EXT_SUBJECT_DIRECTORY_ATTR = '2.5.29.9'; + const CERT_EXT_SUBJECT_KEY_IDENTIFIER = '2.5.29.14'; + const CERT_EXT_KEY_USAGE = '2.5.29.15'; + const CERT_EXT_PRIVATE_KEY_USAGE_PERIOD = '2.5.29.16'; + const CERT_EXT_SUBJECT_ALT_NAME = '2.5.29.17'; + const CERT_EXT_ISSUER_ALT_NAME = '2.5.29.18'; + const CERT_EXT_BASIC_CONSTRAINTS = '2.5.29.19'; + const CERT_EXT_CRL_NUMBER = '2.5.29.20'; + const CERT_EXT_REASON_CODE = '2.5.29.21'; + const CERT_EXT_INVALIDITY_DATE = '2.5.29.24'; + const CERT_EXT_DELTA_CRL_INDICATOR = '2.5.29.27'; + const CERT_EXT_ISSUING_DIST_POINT = '2.5.29.28'; + const CERT_EXT_CERT_ISSUER = '2.5.29.29'; + const CERT_EXT_NAME_CONSTRAINTS = '2.5.29.30'; + const CERT_EXT_CRL_DISTRIBUTION_POINTS = '2.5.29.31'; + const CERT_EXT_CERT_POLICIES = '2.5.29.32'; + const CERT_EXT_AUTHORITY_KEY_IDENTIFIER = '2.5.29.35'; + const CERT_EXT_EXTENDED_KEY_USAGE = '2.5.29.37'; + + // standard certificate files + const COMMON_NAME = '2.5.4.3'; + const SURNAME = '2.5.4.4'; + const SERIAL_NUMBER = '2.5.4.5'; + const COUNTRY_NAME = '2.5.4.6'; + const LOCALITY_NAME = '2.5.4.7'; + const STATE_OR_PROVINCE_NAME = '2.5.4.8'; + const STREET_ADDRESS = '2.5.4.9'; + const ORGANIZATION_NAME = '2.5.4.10'; + const OU_NAME = '2.5.4.11'; + const TITLE = '2.5.4.12'; + const DESCRIPTION = '2.5.4.13'; + const POSTAL_ADDRESS = '2.5.4.16'; + const POSTAL_CODE = '2.5.4.17'; + const AUTHORITY_REVOCATION_LIST = '2.5.4.38'; + + const AUTHORITY_INFORMATION_ACCESS = '1.3.6.1.5.5.7.1.1'; + + /** + * Returns the name of the given object identifier. + * + * Some OIDs are saved as class constants in this class. + * If the wanted oidString is not among them, this method will + * query http://oid-info.com for the right name. + * This behavior can be suppressed by setting the second method parameter to false. + * + * @param string $oidString + * @param bool $loadFromWeb + * + * @see self::loadFromWeb($oidString) + * + * @return string + */ + public static function getName($oidString, $loadFromWeb = true) + { + switch ($oidString) { + case self::RSA_ENCRYPTION: + return 'RSA Encryption'; + case self::MD5_WITH_RSA_ENCRYPTION: + return 'MD5 with RSA Encryption'; + case self::SHA1_WITH_RSA_SIGNATURE: + return 'SHA-1 with RSA Signature'; + + case self::PKCS9_EMAIL: + return 'PKCS #9 Email Address'; + case self::PKCS9_UNSTRUCTURED_NAME: + return 'PKCS #9 Unstructured Name'; + case self::PKCS9_CONTENT_TYPE: + return 'PKCS #9 Content Type'; + case self::PKCS9_MESSAGE_DIGEST: + return 'PKCS #9 Message Digest'; + case self::PKCS9_SIGNING_TIME: + return 'PKCS #9 Signing Time'; + + case self::COMMON_NAME: + return 'Common Name'; + case self::SURNAME: + return 'Surname'; + case self::SERIAL_NUMBER: + return 'Serial Number'; + case self::COUNTRY_NAME: + return 'Country Name'; + case self::LOCALITY_NAME: + return 'Locality Name'; + case self::STATE_OR_PROVINCE_NAME: + return 'State or Province Name'; + case self::STREET_ADDRESS: + return 'Street Address'; + case self::ORGANIZATION_NAME: + return 'Organization Name'; + case self::OU_NAME: + return 'Organization Unit Name'; + case self::TITLE: + return 'Title'; + case self::DESCRIPTION: + return 'Description'; + case self::POSTAL_ADDRESS: + return 'Postal Address'; + case self::POSTAL_CODE: + return 'Postal Code'; + case self::AUTHORITY_REVOCATION_LIST: + return 'Authority Revocation List'; + + case self::CERT_EXT_SUBJECT_DIRECTORY_ATTR: + return 'Subject directory attributes'; + case self::CERT_EXT_SUBJECT_KEY_IDENTIFIER: + return 'Subject key identifier'; + case self::CERT_EXT_KEY_USAGE: + return 'Key usage certificate extension'; + case self::CERT_EXT_PRIVATE_KEY_USAGE_PERIOD: + return 'Private key usage'; + case self::CERT_EXT_SUBJECT_ALT_NAME: + return 'Subject alternative name (SAN)'; + case self::CERT_EXT_ISSUER_ALT_NAME: + return 'Issuer alternative name'; + case self::CERT_EXT_BASIC_CONSTRAINTS: + return 'Basic constraints'; + case self::CERT_EXT_CRL_NUMBER: + return 'CRL number'; + case self::CERT_EXT_REASON_CODE: + return 'Reason code'; + case self::CERT_EXT_INVALIDITY_DATE: + return 'Invalidity code'; + case self::CERT_EXT_DELTA_CRL_INDICATOR: + return 'Delta CRL indicator'; + case self::CERT_EXT_ISSUING_DIST_POINT: + return 'Issuing distribution point'; + case self::CERT_EXT_CERT_ISSUER: + return 'Certificate issuer'; + case self::CERT_EXT_NAME_CONSTRAINTS: + return 'Name constraints'; + case self::CERT_EXT_CRL_DISTRIBUTION_POINTS: + return 'CRL distribution points'; + case self::CERT_EXT_CERT_POLICIES: + return 'Certificate policies '; + case self::CERT_EXT_AUTHORITY_KEY_IDENTIFIER: + return 'Authority key identifier'; + case self::CERT_EXT_EXTENDED_KEY_USAGE: + return 'Extended key usage'; + case self::AUTHORITY_INFORMATION_ACCESS: + return 'Certificate Authority Information Access (AIA)'; + + default: + if ($loadFromWeb) { + return self::loadFromWeb($oidString); + } else { + return $oidString; + } + } + } + + public static function loadFromWeb($oidString) + { + $ch = curl_init("http://oid-info.com/get/{$oidString}"); + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + + $contents = curl_exec($ch); + curl_close($ch); + + // This pattern needs to be updated as soon as the website layout of oid-info.com changes + preg_match_all('#(.+)\(\d+\)#si', $contents, $oidName); + + if (empty($oidName[1])) { + return "{$oidString} (unknown)"; + } + + $oidName = ucfirst(strtolower(preg_replace('/([A-Z][a-z])/', ' $1', $oidName[1][0]))); + $oidName = str_replace('-', ' ', $oidName); + + return "{$oidName} ({$oidString})"; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php new file mode 100644 index 00000000..fa66b558 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use FG\ASN1\Exception\ParserException; + +/** + * The Parsable interface describes classes that can be parsed from their binary DER representation. + */ +interface Parsable +{ + /** + * Parse an instance of this class from its binary DER encoded representation. + * + * @param string $binaryData + * @param int $offsetIndex the offset at which parsing of the $binaryData is started. This parameter ill be modified + * to contain the offset index of the next object after this object has been parsed + * + * @throws ParserException if the given binary data is either invalid or not currently supported + * + * @return static + */ + public static function fromBinary(&$binaryData, &$offsetIndex = null); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php new file mode 100644 index 00000000..90a40b03 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use Exception; +use FG\ASN1\Exception\ParserException; +use FG\ASN1\Universal\Sequence; + +class TemplateParser +{ + /** + * @param string $data + * @param array $template + * @return \FG\ASN1\ASNObject|Sequence + * @throws ParserException if there was an issue parsing + */ + public function parseBase64($data, array $template) + { + // TODO test with invalid data + return $this->parseBinary(base64_decode($data), $template); + } + + /** + * @param string $binary + * @param array $template + * @return \FG\ASN1\ASNObject|Sequence + * @throws ParserException if there was an issue parsing + */ + public function parseBinary($binary, array $template) + { + $parsedObject = ASNObject::fromBinary($binary); + + foreach ($template as $key => $value) { + $this->validate($parsedObject, $key, $value); + } + + return $parsedObject; + } + + private function validate(ASNObject $object, $key, $value) + { + if (is_array($value)) { + $this->assertTypeId($key, $object); + + /* @var Construct $object */ + foreach ($value as $key => $child) { + $this->validate($object->current(), $key, $child); + $object->next(); + } + } else { + $this->assertTypeId($value, $object); + } + } + + private function assertTypeId($expectedTypeId, ASNObject $object) + { + $actualType = $object->getType(); + if ($expectedTypeId != $actualType) { + throw new Exception("Expected type ($expectedTypeId) does not match actual type ($actualType"); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php new file mode 100644 index 00000000..83ec6a91 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class BMPString extends AbstractString +{ + /** + * Creates a new ASN.1 BMP String. + * + * BMPString is a subtype of UniversalString that has its own + * unique tag and contains only the characters in the + * Basic Multilingual Plane (those corresponding to the first + * 64K-2 cells, less cells whose encoding is used to address + * characters outside the Basic Multilingual Plane) of ISO/IEC 10646-1. + * + * TODO The encodable characters of this type are not yet checked. + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::BMP_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php new file mode 100644 index 00000000..226695c5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use Exception; +use FG\ASN1\Exception\ParserException; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; + +class BitString extends OctetString implements Parsable +{ + private $nrOfUnusedBits; + + /** + * Creates a new ASN.1 BitString object. + * + * @param string|int $value Either the hexadecimal value as a string (spaces are allowed - leading 0x is optional) or a numeric value + * @param int $nrOfUnusedBits the number of unused bits in the last octet [optional]. + * + * @throws Exception if the second parameter is no positive numeric value + */ + public function __construct($value, $nrOfUnusedBits = 0) + { + parent::__construct($value); + + if (!is_numeric($nrOfUnusedBits) || $nrOfUnusedBits < 0) { + throw new Exception('BitString: second parameter needs to be a positive number (or zero)!'); + } + + $this->nrOfUnusedBits = $nrOfUnusedBits; + } + + public function getType() + { + return Identifier::BITSTRING; + } + + protected function calculateContentLength() + { + // add one to the length for the first octet which encodes the number of unused bits in the last octet + return parent::calculateContentLength() + 1; + } + + protected function getEncodedValue() + { + // the first octet determines the number of unused bits + $nrOfUnusedBitsOctet = chr($this->nrOfUnusedBits); + $actualContent = parent::getEncodedValue(); + + return $nrOfUnusedBitsOctet.$actualContent; + } + + public function getNumberOfUnusedBits() + { + return $this->nrOfUnusedBits; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::BITSTRING, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex, 2); + + $nrOfUnusedBits = ord($binaryData[$offsetIndex]); + $value = substr($binaryData, $offsetIndex + 1, $contentLength - 1); + + if ($nrOfUnusedBits > 7 || // no less than 1 used, otherwise non-minimal + ($contentLength - 1) == 1 && $nrOfUnusedBits > 0 || // content length only 1, no + (ord($value[strlen($value)-1])&((1<<$nrOfUnusedBits)-1)) != 0 // unused bits set + ) { + throw new ParserException("Can not parse bit string with invalid padding", $offsetIndex); + } + + $offsetIndex += $contentLength; + + $parsedObject = new self(bin2hex($value), $nrOfUnusedBits); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php new file mode 100644 index 00000000..b73c99f1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Exception\ParserException; + +class Boolean extends ASNObject implements Parsable +{ + private $value; + + /** + * @param bool $value + */ + public function __construct($value) + { + $this->value = $value; + } + + public function getType() + { + return Identifier::BOOLEAN; + } + + protected function calculateContentLength() + { + return 1; + } + + protected function getEncodedValue() + { + if ($this->value == false) { + return chr(0x00); + } else { + return chr(0xFF); + } + } + + public function getContent() + { + if ($this->value == true) { + return 'TRUE'; + } else { + return 'FALSE'; + } + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::BOOLEAN, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + + if ($contentLength != 1) { + throw new ParserException("An ASN.1 Boolean should not have a length other than one. Extracted length was {$contentLength}", $offsetIndex); + } + + $value = ord($binaryData[$offsetIndex++]); + $booleanValue = $value == 0xFF ? true : false; + + $parsedObject = new self($booleanValue); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php new file mode 100644 index 00000000..bfc170db --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class CharacterString extends AbstractString +{ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::CHARACTER_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php new file mode 100644 index 00000000..06d04a3a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\Identifier; + +class Enumerated extends Integer +{ + public function getType() + { + return Identifier::ENUMERATED; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php new file mode 100644 index 00000000..fb0346f0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class GeneralString extends AbstractString +{ + /** + * Creates a new ASN.1 GeneralString. + * TODO The encodable characters of this type are not yet checked. + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::GENERAL_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php new file mode 100644 index 00000000..ca922097 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractTime; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Exception\ParserException; + +/** + * This ASN.1 universal type contains date and time information according to ISO 8601. + * + * The type consists of values representing: + * a) a calendar date, as defined in ISO 8601; and + * b) a time of day, to any of the precisions defined in ISO 8601, except for the hours value 24 which shall not be used; and + * c) the local time differential factor as defined in ISO 8601. + * + * Decoding of this type will accept the Basic Encoding Rules (BER) + * The encoding will comply with the Distinguished Encoding Rules (DER). + */ +class GeneralizedTime extends AbstractTime implements Parsable +{ + private $microseconds; + + public function __construct($dateTime = null, $dateTimeZone = 'UTC') + { + parent::__construct($dateTime, $dateTimeZone); + $this->microseconds = $this->value->format('u'); + if ($this->containsFractionalSecondsElement()) { + // DER requires us to remove trailing zeros + $this->microseconds = preg_replace('/([1-9]+)0+$/', '$1', $this->microseconds); + } + } + + public function getType() + { + return Identifier::GENERALIZED_TIME; + } + + protected function calculateContentLength() + { + $contentSize = 15; // YYYYMMDDHHmmSSZ + + if ($this->containsFractionalSecondsElement()) { + $contentSize += 1 + strlen($this->microseconds); + } + + return $contentSize; + } + + public function containsFractionalSecondsElement() + { + return intval($this->microseconds) > 0; + } + + protected function getEncodedValue() + { + $encodedContent = $this->value->format('YmdHis'); + if ($this->containsFractionalSecondsElement()) { + $encodedContent .= ".{$this->microseconds}"; + } + + return $encodedContent.'Z'; + } + + public function __toString() + { + if ($this->containsFractionalSecondsElement()) { + return $this->value->format("Y-m-d\tH:i:s.uP"); + } else { + return $this->value->format("Y-m-d\tH:i:sP"); + } + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::GENERALIZED_TIME, $offsetIndex++); + $lengthOfMinimumTimeString = 14; // YYYYMMDDHHmmSS + $contentLength = self::parseContentLength($binaryData, $offsetIndex, $lengthOfMinimumTimeString); + $maximumBytesToRead = $contentLength; + + $format = 'YmdGis'; + $content = substr($binaryData, $offsetIndex, $contentLength); + $dateTimeString = substr($content, 0, $lengthOfMinimumTimeString); + $offsetIndex += $lengthOfMinimumTimeString; + $maximumBytesToRead -= $lengthOfMinimumTimeString; + + if ($contentLength == $lengthOfMinimumTimeString) { + $localTimeZone = new \DateTimeZone(date_default_timezone_get()); + $dateTime = \DateTime::createFromFormat($format, $dateTimeString, $localTimeZone); + } else { + if ($binaryData[$offsetIndex] == '.') { + $maximumBytesToRead--; // account for the '.' + $nrOfFractionalSecondElements = 1; // account for the '.' + + while ($maximumBytesToRead > 0 + && $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '+' + && $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '-' + && $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != 'Z') { + $nrOfFractionalSecondElements++; + $maximumBytesToRead--; + } + + $dateTimeString .= substr($binaryData, $offsetIndex, $nrOfFractionalSecondElements); + $offsetIndex += $nrOfFractionalSecondElements; + $format .= '.u'; + } + + $dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC')); + + if ($maximumBytesToRead > 0) { + if ($binaryData[$offsetIndex] == '+' + || $binaryData[$offsetIndex] == '-') { + $dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime); + } elseif ($binaryData[$offsetIndex++] != 'Z') { + throw new ParserException('Invalid ISO 8601 Time String', $offsetIndex); + } + } + } + + $parsedObject = new self($dateTime); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php new file mode 100644 index 00000000..4a01d67b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class GraphicString extends AbstractString +{ + /** + * Creates a new ASN.1 Graphic String. + * TODO The encodable characters of this type are not yet checked. + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::GRAPHIC_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php new file mode 100644 index 00000000..33a80679 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +/** + * The International Alphabet No.5 (IA5) references the encoding of the ASCII characters. + * + * Each character in the data is encoded as 1 byte. + */ +class IA5String extends AbstractString +{ + public function __construct($string) + { + parent::__construct($string); + for ($i = 1; $i < 128; $i++) { + $this->allowCharacter(chr($i)); + } + } + + public function getType() + { + return Identifier::IA5_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php new file mode 100644 index 00000000..fe3806ba --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use Exception; +use FG\Utility\BigInteger; +use FG\ASN1\Exception\ParserException; +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; + +class Integer extends ASNObject implements Parsable +{ + /** @var int */ + private $value; + + /** + * @param int $value + * + * @throws Exception if the value is not numeric + */ + public function __construct($value) + { + if (is_numeric($value) == false) { + throw new Exception("Invalid VALUE [{$value}] for ASN1_INTEGER"); + } + $this->value = $value; + } + + public function getType() + { + return Identifier::INTEGER; + } + + public function getContent() + { + return $this->value; + } + + protected function calculateContentLength() + { + return strlen($this->getEncodedValue()); + } + + protected function getEncodedValue() + { + $value = BigInteger::create($this->value, 10); + $negative = $value->compare(0) < 0; + if ($negative) { + $value = $value->absoluteValue(); + $limit = 0x80; + } else { + $limit = 0x7f; + } + + $mod = 0xff+1; + $values = []; + while($value->compare($limit) > 0) { + $values[] = $value->modulus($mod)->toInteger(); + $value = $value->shiftRight(8); + } + + $values[] = $value->modulus($mod)->toInteger(); + $numValues = count($values); + + if ($negative) { + for ($i = 0; $i < $numValues; $i++) { + $values[$i] = 0xff - $values[$i]; + } + for ($i = 0; $i < $numValues; $i++) { + $values[$i] += 1; + if ($values[$i] <= 0xff) { + break; + } + assert($i != $numValues - 1); + $values[$i] = 0; + } + if ($values[$numValues - 1] == 0x7f) { + $values[] = 0xff; + } + } + $values = array_reverse($values); + $r = pack("C*", ...$values); + return $r; + } + + private static function ensureMinimalEncoding($binaryData, $offsetIndex) + { + // All the first nine bits cannot equal 0 or 1, which would + // be non-minimal encoding for positive and negative integers respectively + if ((ord($binaryData[$offsetIndex]) == 0x00 && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0) || + (ord($binaryData[$offsetIndex]) == 0xff && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0x80)) { + throw new ParserException("Integer not minimally encoded", $offsetIndex); + } + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + $parsedObject = new static(0); + self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex, 1); + + if ($contentLength > 1) { + self::ensureMinimalEncoding($binaryData, $offsetIndex); + } + $isNegative = (ord($binaryData[$offsetIndex]) & 0x80) != 0x00; + $number = BigInteger::create(ord($binaryData[$offsetIndex++]) & 0x7F); + + for ($i = 0; $i < $contentLength - 1; $i++) { + $number = $number->multiply(0x100)->add(ord($binaryData[$offsetIndex++])); + } + + if ($isNegative) { + $number = $number->subtract(BigInteger::create(2)->toPower(8 * $contentLength - 1)); + } + + $parsedObject = new static((string)$number); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php new file mode 100644 index 00000000..b5293e4b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Exception\ParserException; + +class NullObject extends ASNObject implements Parsable +{ + public function getType() + { + return Identifier::NULL; + } + + protected function calculateContentLength() + { + return 0; + } + + protected function getEncodedValue() + { + return null; + } + + public function getContent() + { + return 'NULL'; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::NULL, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + + if ($contentLength != 0) { + throw new ParserException("An ASN.1 Null should not have a length other than zero. Extracted length was {$contentLength}", $offsetIndex); + } + + $parsedObject = new self(); + $parsedObject->setContentLength(0); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php new file mode 100644 index 00000000..13fb7c34 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class NumericString extends AbstractString +{ + /** + * Creates a new ASN.1 NumericString. + * + * The following characters are permitted: + * Digits 0,1, ... 9 + * SPACE (space) + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowNumbers(); + $this->allowSpaces(); + } + + public function getType() + { + return Identifier::NUMERIC_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php new file mode 100644 index 00000000..1c5d3498 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\Identifier; + +class ObjectDescriptor extends GraphicString +{ + public function __construct($objectDescription) + { + parent::__construct($objectDescription); + } + + public function getType() + { + return Identifier::OBJECT_DESCRIPTOR; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php new file mode 100644 index 00000000..150ce9c4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use Exception; +use FG\ASN1\Base128; +use FG\ASN1\OID; +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Exception\ParserException; + +class ObjectIdentifier extends ASNObject implements Parsable +{ + protected $subIdentifiers; + protected $value; + + public function __construct($value) + { + $this->subIdentifiers = explode('.', $value); + $nrOfSubIdentifiers = count($this->subIdentifiers); + + for ($i = 0; $i < $nrOfSubIdentifiers; $i++) { + if (is_numeric($this->subIdentifiers[$i])) { + // enforce the integer type + $this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]); + } else { + throw new Exception("[{$value}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!'); + } + } + + // Merge the first to arcs of the OID registration tree (per ASN definition!) + if ($nrOfSubIdentifiers >= 2) { + $this->subIdentifiers[1] = ($this->subIdentifiers[0] * 40) + $this->subIdentifiers[1]; + unset($this->subIdentifiers[0]); + } + + $this->value = $value; + } + + public function getContent() + { + return $this->value; + } + + public function getType() + { + return Identifier::OBJECT_IDENTIFIER; + } + + protected function calculateContentLength() + { + $length = 0; + foreach ($this->subIdentifiers as $subIdentifier) { + do { + $subIdentifier = $subIdentifier >> 7; + $length++; + } while ($subIdentifier > 0); + } + + return $length; + } + + protected function getEncodedValue() + { + $encodedValue = ''; + foreach ($this->subIdentifiers as $subIdentifier) { + $encodedValue .= Base128::encode($subIdentifier); + } + + return $encodedValue; + } + + public function __toString() + { + return OID::getName($this->value); + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::OBJECT_IDENTIFIER, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex, 1); + + $firstOctet = ord($binaryData[$offsetIndex++]); + $oidString = floor($firstOctet / 40).'.'.($firstOctet % 40); + $oidString .= '.'.self::parseOid($binaryData, $offsetIndex, $contentLength - 1); + + $parsedObject = new self($oidString); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } + + /** + * Parses an object identifier except for the first octet, which is parsed + * differently. This way relative object identifiers can also be parsed + * using this. + * + * @param $binaryData + * @param $offsetIndex + * @param $octetsToRead + * + * @throws ParserException + * + * @return string + */ + protected static function parseOid(&$binaryData, &$offsetIndex, $octetsToRead) + { + $oid = ''; + + while ($octetsToRead > 0) { + $octets = ''; + + do { + if (0 === $octetsToRead) { + throw new ParserException('Malformed ASN.1 Object Identifier', $offsetIndex - 1); + } + + $octetsToRead--; + $octet = $binaryData[$offsetIndex++]; + $octets .= $octet; + } while (ord($octet) & 0x80); + + $oid .= sprintf('%d.', Base128::decode($octets)); + } + + // Remove trailing '.' + return substr($oid, 0, -1) ?: ''; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php new file mode 100644 index 00000000..5d69ae7b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use Exception; +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; + +class OctetString extends ASNObject implements Parsable +{ + protected $value; + + public function __construct($value) + { + if (is_string($value)) { + // remove gaps between hex digits + $value = preg_replace('/\s|0x/', '', $value); + } elseif (is_numeric($value)) { + $value = dechex($value); + } elseif ($value === null) { + return; + } else { + throw new Exception('OctetString: unrecognized input type!'); + } + + if (strlen($value) % 2 != 0) { + // transform values like 1F2 to 01F2 + $value = '0'.$value; + } + + $this->value = $value; + } + + public function getType() + { + return Identifier::OCTETSTRING; + } + + protected function calculateContentLength() + { + return strlen($this->value) / 2; + } + + protected function getEncodedValue() + { + $value = $this->value; + $result = ''; + + //Actual content + while (strlen($value) >= 2) { + // get the hex value byte by byte from the string and and add it to binary result + $result .= chr(hexdec(substr($value, 0, 2))); + $value = substr($value, 2); + } + + return $result; + } + + public function getContent() + { + return strtoupper($this->value); + } + + public function getBinaryContent() + { + return $this->getEncodedValue(); + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::OCTETSTRING, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + + $value = substr($binaryData, $offsetIndex, $contentLength); + $offsetIndex += $contentLength; + + $parsedObject = new self(bin2hex($value)); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php new file mode 100644 index 00000000..fe6d4bc0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class PrintableString extends AbstractString +{ + /** + * Creates a new ASN.1 PrintableString. + * + * The ITU-T X.680 Table 8 permits the following characters: + * Latin capital letters A,B, ... Z + * Latin small letters a,b, ... z + * Digits 0,1, ... 9 + * SPACE (space) + * APOSTROPHE ' + * LEFT PARENTHESIS ( + * RIGHT PARENTHESIS ) + * PLUS SIGN + + * COMMA , + * HYPHEN-MINUS - + * FULL STOP . + * SOLIDUS / + * COLON : + * EQUALS SIGN = + * QUESTION MARK ? + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowNumbers(); + $this->allowAllLetters(); + $this->allowSpaces(); + $this->allowCharacters("'", '(', ')', '+', '-', '.', ',', '/', ':', '=', '?'); + } + + public function getType() + { + return Identifier::PRINTABLE_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php new file mode 100644 index 00000000..2aa9643a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use Exception; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Exception\ParserException; + +class RelativeObjectIdentifier extends ObjectIdentifier implements Parsable +{ + public function __construct($subIdentifiers) + { + $this->value = $subIdentifiers; + $this->subIdentifiers = explode('.', $subIdentifiers); + $nrOfSubIdentifiers = count($this->subIdentifiers); + + for ($i = 0; $i < $nrOfSubIdentifiers; $i++) { + if (is_numeric($this->subIdentifiers[$i])) { + // enforce the integer type + $this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]); + } else { + throw new Exception("[{$subIdentifiers}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!'); + } + } + } + + public function getType() + { + return Identifier::RELATIVE_OID; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::RELATIVE_OID, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex, 1); + + try { + $oidString = self::parseOid($binaryData, $offsetIndex, $contentLength); + } catch (ParserException $e) { + throw new ParserException('Malformed ASN.1 Relative Object Identifier', $e->getOffset()); + } + + $parsedObject = new self($oidString); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php new file mode 100644 index 00000000..0397cf12 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\Construct; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; + +class Sequence extends Construct implements Parsable +{ + public function getType() + { + return Identifier::SEQUENCE; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php new file mode 100644 index 00000000..6e6d346f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\Identifier; + +class Set extends Sequence +{ + public function getType() + { + return Identifier::SET; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php new file mode 100644 index 00000000..56418645 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class T61String extends AbstractString +{ + /** + * Creates a new ASN.1 T61 String. + * TODO The encodable characters of this type are not yet checked. + * + * @see http://en.wikipedia.org/wiki/ITU_T.61 + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::T61_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php new file mode 100644 index 00000000..c4d303cb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractTime; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Exception\ParserException; + +/** + * This ASN.1 universal type contains the calendar date and time. + * + * The precision is one minute or one second and optionally a + * local time differential from coordinated universal time. + * + * Decoding of this type will accept the Basic Encoding Rules (BER) + * The encoding will comply with the Distinguished Encoding Rules (DER). + */ +class UTCTime extends AbstractTime implements Parsable +{ + public function getType() + { + return Identifier::UTC_TIME; + } + + protected function calculateContentLength() + { + return 13; // Content is a string o the following format: YYMMDDhhmmssZ (13 octets) + } + + protected function getEncodedValue() + { + return $this->value->format('ymdHis').'Z'; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::UTC_TIME, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex, 11); + + $format = 'ymdGi'; + $dateTimeString = substr($binaryData, $offsetIndex, 10); + $offsetIndex += 10; + + // extract optional seconds part + if ($binaryData[$offsetIndex] != 'Z' + && $binaryData[$offsetIndex] != '+' + && $binaryData[$offsetIndex] != '-') { + $dateTimeString .= substr($binaryData, $offsetIndex, 2); + $offsetIndex += 2; + $format .= 's'; + } + + $dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC')); + + // extract time zone settings + if ($binaryData[$offsetIndex] == '+' + || $binaryData[$offsetIndex] == '-') { + $dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime); + } elseif ($binaryData[$offsetIndex++] != 'Z') { + throw new ParserException('Invalid UTC String', $offsetIndex); + } + + $parsedObject = new self($dateTime); + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php new file mode 100644 index 00000000..cba568d3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class UTF8String extends AbstractString +{ + /** + * Creates a new ASN.1 Universal String. + * TODO The encodable characters of this type are not yet checked. + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::UTF8_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php new file mode 100644 index 00000000..0c3fe1d0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class UniversalString extends AbstractString +{ + /** + * Creates a new ASN.1 Universal String. + * TODO The encodable characters of this type are not yet checked. + * + * @see http://en.wikipedia.org/wiki/Universal_Character_Set + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::UNIVERSAL_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php new file mode 100644 index 00000000..d9326d3f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1\Universal; + +use FG\ASN1\AbstractString; +use FG\ASN1\Identifier; + +class VisibleString extends AbstractString +{ + /** + * Creates a new ASN.1 Visible String. + * TODO The encodable characters of this type are not yet checked. + * + * @param string $string + */ + public function __construct($string) + { + $this->value = $string; + $this->allowAll(); + } + + public function getType() + { + return Identifier::VISIBLE_STRING; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php new file mode 100644 index 00000000..b19a07a1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +class UnknownConstructedObject extends Construct +{ + private $identifier; + private $contentLength; + + /** + * @param string $binaryData + * @param int $offsetIndex + * + * @throws \FG\ASN1\Exception\ParserException + */ + public function __construct($binaryData, &$offsetIndex) + { + $this->identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex); + $this->contentLength = self::parseContentLength($binaryData, $offsetIndex); + + $children = []; + $octetsToRead = $this->contentLength; + while ($octetsToRead > 0) { + $newChild = ASNObject::fromBinary($binaryData, $offsetIndex); + $octetsToRead -= $newChild->getObjectLength(); + $children[] = $newChild; + } + + parent::__construct(...$children); + } + + public function getType() + { + return ord($this->identifier); + } + + public function getIdentifier() + { + return $this->identifier; + } + + protected function calculateContentLength() + { + return $this->contentLength; + } + + protected function getEncodedValue() + { + return ''; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php new file mode 100644 index 00000000..4ac536a9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +class UnknownObject extends ASNObject +{ + /** @var string */ + private $value; + + private $identifier; + + /** + * @param string|int $identifier Either the first identifier octet as int or all identifier bytes as a string + * @param int $contentLength + */ + public function __construct($identifier, $contentLength) + { + if (is_int($identifier)) { + $identifier = chr($identifier); + } + + $this->identifier = $identifier; + $this->value = "Unparsable Object ({$contentLength} bytes)"; + $this->setContentLength($contentLength); + } + + public function getContent() + { + return $this->value; + } + + public function getType() + { + return ord($this->identifier[0]); + } + + public function getIdentifier() + { + return $this->identifier; + } + + protected function calculateContentLength() + { + return $this->getContentLength(); + } + + protected function getEncodedValue() + { + return ''; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigInteger.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigInteger.php new file mode 100644 index 00000000..866162cc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigInteger.php @@ -0,0 +1,195 @@ +_fromInteger($val); + } + else { + // convert to string, if not already one + $val = (string)$val; + + // validate string + if (!preg_match('/^-?[0-9]+$/', $val)) { + throw new \InvalidArgumentException('Expects a string representation of an integer.'); + } + $ret->_fromString($val); + } + + return $ret; + } + + /** + * BigInteger constructor. + * Prevent directly instantiating object, use BigInteger::create instead. + */ + protected function __construct() + { + + } + + /** + * Subclasses must provide clone functionality. + * @return BigInteger + */ + abstract public function __clone(); + + /** + * Assign the instance value from base 10 string. + * @param string $str + */ + abstract protected function _fromString($str); + + /** + * Assign the instance value from an integer type. + * @param int $integer + */ + abstract protected function _fromInteger($integer); + + /** + * Must provide string implementation that returns base 10 number. + * @return string + */ + abstract public function __toString(); + + /* INFORMATIONAL FUNCTIONS */ + + /** + * Return integer, if possible. Throws an exception if the number can not be represented as a native integer. + * @return int + * @throws \OverflowException + */ + abstract public function toInteger(); + + /** + * Is represented integer negative? + * @return bool + */ + abstract public function isNegative(); + + /** + * Compare the integer with $number, returns a negative integer if $this is less than number, returns 0 if $this is + * equal to number and returns a positive integer if $this is greater than number. + * @param BigInteger|string|int $number + * @return int + */ + abstract public function compare($number); + + /* MODIFY */ + + /** + * Add another integer $b and returns the result. + * @param BigInteger|string|int $b + * @return BigInteger + */ + abstract public function add($b); + + /** + * Subtract $b from $this and returns the result. + * @param BigInteger|string|int $b + * @return BigInteger + */ + abstract public function subtract($b); + + /** + * Multiply value. + * @param BigInteger|string|int $b + * @return BigInteger + */ + abstract public function multiply($b); + + /** + * The value $this modulus $b. + * @param BigInteger|string|int $b + * @return BigInteger + */ + abstract public function modulus($b); + + /** + * Raise $this to the power of $b and returns the result. + * @param BigInteger|string|int $b + * @return BigInteger + */ + abstract public function toPower($b); + + /** + * Shift the value to the right by a set number of bits and returns the result. + * @param int $bits + * @return BigInteger + */ + abstract public function shiftRight($bits = 8); + + /** + * Shift the value to the left by a set number of bits and returns the result. + * @param int $bits + * @return BigInteger + */ + abstract public function shiftLeft($bits = 8); + + /** + * Returns the absolute value. + * @return BigInteger + */ + abstract public function absoluteValue(); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerBcmath.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerBcmath.php new file mode 100644 index 00000000..25ad8916 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerBcmath.php @@ -0,0 +1,133 @@ +_str = (string)$str; + } + + protected function _fromInteger($integer) + { + $this->_str = (string)$integer; + } + + public function __toString() + { + return $this->_str; + } + + public function toInteger() + { + if ($this->compare(PHP_INT_MAX) > 0 || $this->compare(PHP_INT_MIN) < 0) { + throw new \OverflowException(sprintf('Can not represent %s as integer.', $this->_str)); + } + return (int)$this->_str; + } + + public function isNegative() + { + return bccomp($this->_str, '0', 0) < 0; + } + + protected function _unwrap($number) + { + if ($number instanceof self) { + return $number->_str; + } + return $number; + } + + public function compare($number) + { + return bccomp($this->_str, $this->_unwrap($number), 0); + } + + public function add($b) + { + $ret = new self(); + $ret->_str = bcadd($this->_str, $this->_unwrap($b), 0); + return $ret; + } + + public function subtract($b) + { + $ret = new self(); + $ret->_str = bcsub($this->_str, $this->_unwrap($b), 0); + return $ret; + } + + public function multiply($b) + { + $ret = new self(); + $ret->_str = bcmul($this->_str, $this->_unwrap($b), 0); + return $ret; + } + + public function modulus($b) + { + $ret = new self(); + if ($this->isNegative()) { + // bcmod handles negative numbers differently + $b = $this->_unwrap($b); + $ret->_str = bcsub($b, bcmod(bcsub('0', $this->_str, 0), $b), 0); + } + else { + $ret->_str = bcmod($this->_str, $this->_unwrap($b)); + } + return $ret; + } + + public function toPower($b) + { + $ret = new self(); + $ret->_str = bcpow($this->_str, $this->_unwrap($b), 0); + return $ret; + } + + public function shiftRight($bits = 8) + { + $ret = new self(); + $ret->_str = bcdiv($this->_str, bcpow('2', $bits)); + return $ret; + } + + public function shiftLeft($bits = 8) { + $ret = new self(); + $ret->_str = bcmul($this->_str, bcpow('2', $bits)); + return $ret; + } + + public function absoluteValue() + { + $ret = new self(); + if (-1 === bccomp($this->_str, '0', 0)) { + $ret->_str = bcsub('0', $this->_str, 0); + } + else { + $ret->_str = $this->_str; + } + return $ret; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerGmp.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerGmp.php new file mode 100644 index 00000000..0791226a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerGmp.php @@ -0,0 +1,133 @@ +_rh = gmp_add($this->_rh, 0); + } + + protected function _fromString($str) + { + $this->_rh = gmp_init($str, 10); + } + + protected function _fromInteger($integer) + { + $this->_rh = gmp_init($integer, 10); + } + + public function __toString() + { + return gmp_strval($this->_rh, 10); + } + + public function toInteger() + { + if ($this->compare(PHP_INT_MAX) > 0 || $this->compare(PHP_INT_MIN) < 0) { + throw new \OverflowException(sprintf('Can not represent %s as integer.', $this)); + } + return gmp_intval($this->_rh); + } + + public function isNegative() + { + return gmp_sign($this->_rh) === -1; + } + + protected function _unwrap($number) + { + if ($number instanceof self) { + return $number->_rh; + } + return $number; + } + + public function compare($number) + { + return gmp_cmp($this->_rh, $this->_unwrap($number)); + } + + public function add($b) + { + $ret = new self(); + $ret->_rh = gmp_add($this->_rh, $this->_unwrap($b)); + return $ret; + } + + public function subtract($b) + { + $ret = new self(); + $ret->_rh = gmp_sub($this->_rh, $this->_unwrap($b)); + return $ret; + } + + public function multiply($b) + { + $ret = new self(); + $ret->_rh = gmp_mul($this->_rh, $this->_unwrap($b)); + return $ret; + } + + public function modulus($b) + { + $ret = new self(); + $ret->_rh = gmp_mod($this->_rh, $this->_unwrap($b)); + return $ret; + } + + public function toPower($b) + { + if ($b instanceof self) { + // gmp_pow accepts just an integer + if ($b->compare(PHP_INT_MAX) > 0) { + throw new \UnexpectedValueException('Unable to raise to power greater than PHP_INT_MAX.'); + } + $b = gmp_intval($b->_rh); + } + $ret = new self(); + $ret->_rh = gmp_pow($this->_rh, $b); + return $ret; + } + + public function shiftRight($bits=8) + { + $ret = new self(); + $ret->_rh = gmp_div($this->_rh, gmp_pow(2, $bits)); + return $ret; + } + + public function shiftLeft($bits=8) + { + $ret = new self(); + $ret->_rh = gmp_mul($this->_rh, gmp_pow(2, $bits)); + return $ret; + } + + public function absoluteValue() + { + $ret = new self(); + $ret->_rh = gmp_abs($this->_rh); + return $ret; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php new file mode 100644 index 00000000..a06b56f7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\Universal\NullObject; +use FG\ASN1\Composite\AttributeTypeAndValue; + +class AlgorithmIdentifier extends AttributeTypeAndValue +{ + public function __construct($objectIdentifierString) + { + parent::__construct($objectIdentifierString, new NullObject()); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php new file mode 100644 index 00000000..5a965e2f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\CSR; + +use FG\ASN1\ASNObject; +use FG\X509\CertificateExtensions; +use FG\ASN1\OID; +use FG\ASN1\Parsable; +use FG\ASN1\Construct; +use FG\ASN1\Identifier; +use FG\ASN1\Universal\Set; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\ObjectIdentifier; + +class Attributes extends Construct implements Parsable +{ + public function getType() + { + return 0xA0; + } + + public function addAttribute($objectIdentifier, Set $attribute) + { + if (is_string($objectIdentifier)) { + $objectIdentifier = new ObjectIdentifier($objectIdentifier); + } + $attributeSequence = new Sequence($objectIdentifier, $attribute); + $attributeSequence->getNumberOfLengthOctets(); // length and number of length octets is calculated + $this->addChild($attributeSequence); + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], 0xA0, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + $octetsToRead = $contentLength; + + $parsedObject = new self(); + while ($octetsToRead > 0) { + $initialOffset = $offsetIndex; // used to calculate how much bits have been read + self::parseIdentifier($binaryData[$offsetIndex], Identifier::SEQUENCE, $offsetIndex++); + self::parseContentLength($binaryData, $offsetIndex); + + $objectIdentifier = ObjectIdentifier::fromBinary($binaryData, $offsetIndex); + $oidString = $objectIdentifier->getContent(); + if ($oidString == OID::PKCS9_EXTENSION_REQUEST) { + $attribute = CertificateExtensions::fromBinary($binaryData, $offsetIndex); + } else { + $attribute = ASNObject::fromBinary($binaryData, $offsetIndex); + } + + $parsedObject->addAttribute($objectIdentifier, $attribute); + $octetsToRead -= ($offsetIndex - $initialOffset); + } + + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php new file mode 100644 index 00000000..8f2a3197 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\CSR; + +use FG\ASN1\OID; +use FG\ASN1\Universal\Integer; +use FG\ASN1\Universal\BitString; +use FG\ASN1\Universal\Sequence; +use FG\X509\CertificateSubject; +use FG\X509\AlgorithmIdentifier; +use FG\X509\PublicKey; + +class CSR extends Sequence +{ + const CSR_VERSION_NR = 0; + + protected $subject; + protected $publicKey; + protected $signature; + protected $signatureAlgorithm; + + protected $startSequence; + + /** + * @param string $commonName + * @param string $email + * @param string $organization + * @param string $locality + * @param string $state + * @param string $country + * @param string $organizationalUnit + * @param string $publicKey + * @param string $signature + * @param string $signatureAlgorithm + */ + public function __construct($commonName, $email, $organization, $locality, $state, $country, $organizationalUnit, $publicKey, $signature = null, $signatureAlgorithm = OID::SHA1_WITH_RSA_SIGNATURE) + { + $this->subject = new CertificateSubject( + $commonName, + $email, + $organization, + $locality, + $state, + $country, + $organizationalUnit + ); + $this->publicKey = $publicKey; + $this->signature = $signature; + $this->signatureAlgorithm = $signatureAlgorithm; + + if (isset($signature)) { + $this->createCSRSequence(); + } + } + + protected function createCSRSequence() + { + $versionNr = new Integer(self::CSR_VERSION_NR); + $publicKey = new PublicKey($this->publicKey); + $signature = new BitString($this->signature); + $signatureAlgorithm = new AlgorithmIdentifier($this->signatureAlgorithm); + + $certRequestInfo = new Sequence($versionNr, $this->subject, $publicKey); + + // Clear the underlying Construct + $this->rewind(); + $this->children = []; + $this->addChild($certRequestInfo); + $this->addChild($signatureAlgorithm); + $this->addChild($signature); + } + + public function getSignatureSubject() + { + $versionNr = new Integer(self::CSR_VERSION_NR); + $publicKey = new PublicKey($this->publicKey); + + $certRequestInfo = new Sequence($versionNr, $this->subject, $publicKey); + return $certRequestInfo->getBinary(); + } + + public function setSignature($signature, $signatureAlgorithm = OID::SHA1_WITH_RSA_SIGNATURE) + { + $this->signature = $signature; + $this->signatureAlgorithm = $signatureAlgorithm; + + $this->createCSRSequence(); + } + + public function __toString() + { + $tmp = base64_encode($this->getBinary()); + + for ($i = 0; $i < strlen($tmp); $i++) { + if (($i + 2) % 65 == 0) { + $tmp = substr($tmp, 0, $i + 1)."\n".substr($tmp, $i + 1); + } + } + + $result = '-----BEGIN CERTIFICATE REQUEST-----'.PHP_EOL; + $result .= $tmp.PHP_EOL; + $result .= '-----END CERTIFICATE REQUEST-----'; + + return $result; + } + + public function getVersion() + { + return self::CSR_VERSION_NR; + } + + public function getOrganizationName() + { + return $this->subject->getOrganization(); + } + + public function getLocalName() + { + return $this->subject->getLocality(); + } + + public function getState() + { + return $this->subject->getState(); + } + + public function getCountry() + { + return $this->subject->getCountry(); + } + + public function getOrganizationalUnit() + { + return $this->subject->getOrganizationalUnit(); + } + + public function getPublicKey() + { + return $this->publicKey; + } + + public function getSignature() + { + return $this->signature; + } + + public function getSignatureAlgorithm() + { + return $this->signatureAlgorithm; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php new file mode 100644 index 00000000..6ed1c6a7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\Exception\ParserException; +use FG\ASN1\OID; +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Universal\OctetString; +use FG\ASN1\Universal\Set; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\ObjectIdentifier; +use FG\X509\SAN\SubjectAlternativeNames; + +class CertificateExtensions extends Set implements Parsable +{ + private $innerSequence; + private $extensions = []; + + public function __construct() + { + $this->innerSequence = new Sequence(); + parent::__construct($this->innerSequence); + } + + public function addSubjectAlternativeNames(SubjectAlternativeNames $sans) + { + $this->addExtension(OID::CERT_EXT_SUBJECT_ALT_NAME, $sans); + } + + private function addExtension($oidString, ASNObject $extension) + { + $sequence = new Sequence(); + $sequence->addChild(new ObjectIdentifier($oidString)); + $sequence->addChild($extension); + + $this->innerSequence->addChild($sequence); + $this->extensions[] = $extension; + } + + public function getContent() + { + return $this->extensions; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::SET, $offsetIndex++); + self::parseContentLength($binaryData, $offsetIndex); + + $tmpOffset = $offsetIndex; + $extensions = Sequence::fromBinary($binaryData, $offsetIndex); + $tmpOffset += 1 + $extensions->getNumberOfLengthOctets(); + + $parsedObject = new self(); + foreach ($extensions as $extension) { + if ($extension->getType() != Identifier::SEQUENCE) { + //FIXME wrong offset index + throw new ParserException('Could not parse Certificate Extensions: Expected ASN.1 Sequence but got '.$extension->getTypeName(), $offsetIndex); + } + + $tmpOffset += 1 + $extension->getNumberOfLengthOctets(); + $children = $extension->getChildren(); + if (count($children) < 2) { + throw new ParserException('Could not parse Certificate Extensions: Needs at least two child elements per extension sequence (object identifier and octet string)', $tmpOffset); + } + /** @var \FG\ASN1\ASNObject $objectIdentifier */ + $objectIdentifier = $children[0]; + + /** @var OctetString $octetString */ + $octetString = $children[1]; + + if ($objectIdentifier->getType() != Identifier::OBJECT_IDENTIFIER) { + throw new ParserException('Could not parse Certificate Extensions: Expected ASN.1 Object Identifier but got '.$extension->getTypeName(), $tmpOffset); + } + + $tmpOffset += $objectIdentifier->getObjectLength(); + + if ($objectIdentifier->getContent() == OID::CERT_EXT_SUBJECT_ALT_NAME) { + $sans = SubjectAlternativeNames::fromBinary($binaryData, $tmpOffset); + $parsedObject->addSubjectAlternativeNames($sans); + } else { + // can now only parse SANs. There might be more in the future + $tmpOffset += $octetString->getObjectLength(); + } + } + + $parsedObject->getBinary(); // Determine the number of content octets and object sizes once (just to let the equality unit tests pass :/ ) + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php new file mode 100644 index 00000000..0a04d574 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\Composite\RelativeDistinguishedName; +use FG\ASN1\Identifier; +use FG\ASN1\OID; +use FG\ASN1\Parsable; +use FG\ASN1\Composite\RDNString; +use FG\ASN1\Universal\Sequence; + +class CertificateSubject extends Sequence implements Parsable +{ + private $commonName; + private $email; + private $organization; + private $locality; + private $state; + private $country; + private $organizationalUnit; + + /** + * @param string $commonName + * @param string $email + * @param string $organization + * @param string $locality + * @param string $state + * @param string $country + * @param string $organizationalUnit + */ + public function __construct($commonName, $email, $organization, $locality, $state, $country, $organizationalUnit) + { + parent::__construct( + new RDNString(OID::COUNTRY_NAME, $country), + new RDNString(OID::STATE_OR_PROVINCE_NAME, $state), + new RDNString(OID::LOCALITY_NAME, $locality), + new RDNString(OID::ORGANIZATION_NAME, $organization), + new RDNString(OID::OU_NAME, $organizationalUnit), + new RDNString(OID::COMMON_NAME, $commonName), + new RDNString(OID::PKCS9_EMAIL, $email) + ); + + $this->commonName = $commonName; + $this->email = $email; + $this->organization = $organization; + $this->locality = $locality; + $this->state = $state; + $this->country = $country; + $this->organizationalUnit = $organizationalUnit; + } + + public function getCommonName() + { + return $this->commonName; + } + + public function getEmail() + { + return $this->email; + } + + public function getOrganization() + { + return $this->organization; + } + + public function getLocality() + { + return $this->locality; + } + + public function getState() + { + return $this->state; + } + + public function getCountry() + { + return $this->country; + } + + public function getOrganizationalUnit() + { + return $this->organizationalUnit; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::SEQUENCE, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + + $names = []; + $octetsToRead = $contentLength; + while ($octetsToRead > 0) { + $relativeDistinguishedName = RelativeDistinguishedName::fromBinary($binaryData, $offsetIndex); + $octetsToRead -= $relativeDistinguishedName->getObjectLength(); + $names[] = $relativeDistinguishedName; + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php new file mode 100644 index 00000000..d57ad865 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\OID; +use FG\ASN1\Universal\NullObject; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\BitString; +use FG\ASN1\Universal\ObjectIdentifier; + +class PrivateKey extends Sequence +{ + /** + * @param string $hexKey + * @param \FG\ASN1\ASNObject|string $algorithmIdentifierString + */ + public function __construct($hexKey, $algorithmIdentifierString = OID::RSA_ENCRYPTION) + { + parent::__construct( + new Sequence( + new ObjectIdentifier($algorithmIdentifierString), + new NullObject() + ), + new BitString($hexKey) + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php new file mode 100644 index 00000000..ab8b4514 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\OID; +use FG\ASN1\Universal\NullObject; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\BitString; +use FG\ASN1\Universal\ObjectIdentifier; + +class PublicKey extends Sequence +{ + /** + * @param string $hexKey + * @param \FG\ASN1\ASNObject|string $algorithmIdentifierString + */ + public function __construct($hexKey, $algorithmIdentifierString = OID::RSA_ENCRYPTION) + { + parent::__construct( + new Sequence( + new ObjectIdentifier($algorithmIdentifierString), + new NullObject() + ), + new BitString($hexKey) + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php new file mode 100644 index 00000000..502738b0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\SAN; + +use FG\ASN1\Universal\GeneralString; + +class DNSName extends GeneralString +{ + const IDENTIFIER = 0x82; // not sure yet why this is the identifier used in SAN extensions + + public function __construct($dnsNameString) + { + parent::__construct($dnsNameString); + } + + public function getType() + { + return self::IDENTIFIER; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php new file mode 100644 index 00000000..f55be95b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\SAN; + +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Exception\ParserException; + +class IPAddress extends ASNObject implements Parsable +{ + const IDENTIFIER = 0x87; // not sure yet why this is the identifier used in SAN extensions + + /** @var string */ + private $value; + + public function __construct($ipAddressString) + { + $this->value = $ipAddressString; + } + + public function getType() + { + return self::IDENTIFIER; + } + + public function getContent() + { + return $this->value; + } + + protected function calculateContentLength() + { + return 4; + } + + protected function getEncodedValue() + { + $ipParts = explode('.', $this->value); + $binary = chr($ipParts[0]); + $binary .= chr($ipParts[1]); + $binary .= chr($ipParts[2]); + $binary .= chr($ipParts[3]); + + return $binary; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], self::IDENTIFIER, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + if ($contentLength != 4) { + throw new ParserException("A FG\\X509\SAN\IPAddress should have a content length of 4. Extracted length was {$contentLength}", $offsetIndex); + } + + $ipAddressString = ord($binaryData[$offsetIndex++]).'.'; + $ipAddressString .= ord($binaryData[$offsetIndex++]).'.'; + $ipAddressString .= ord($binaryData[$offsetIndex++]).'.'; + $ipAddressString .= ord($binaryData[$offsetIndex++]); + + $parsedObject = new self($ipAddressString); + $parsedObject->getObjectLength(); + + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php new file mode 100644 index 00000000..271ddde7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\SAN; + +use FG\ASN1\Exception\ParserException; +use FG\ASN1\ASNObject; +use FG\ASN1\OID; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Universal\Sequence; + +/** + * See section 8.3.2.1 of ITU-T X.509. + */ +class SubjectAlternativeNames extends ASNObject implements Parsable +{ + private $alternativeNamesSequence; + + public function __construct() + { + $this->alternativeNamesSequence = new Sequence(); + } + + protected function calculateContentLength() + { + return $this->alternativeNamesSequence->getObjectLength(); + } + + public function getType() + { + return Identifier::OCTETSTRING; + } + + public function addDomainName(DNSName $domainName) + { + $this->alternativeNamesSequence->addChild($domainName); + } + + public function addIP(IPAddress $ip) + { + $this->alternativeNamesSequence->addChild($ip); + } + + public function getContent() + { + return $this->alternativeNamesSequence->getContent(); + } + + protected function getEncodedValue() + { + return $this->alternativeNamesSequence->getBinary(); + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::OCTETSTRING, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + + if ($contentLength < 2) { + throw new ParserException('Can not parse Subject Alternative Names: The Sequence within the octet string after the Object identifier '.OID::CERT_EXT_SUBJECT_ALT_NAME." is too short ({$contentLength} octets)", $offsetIndex); + } + + $offsetOfSequence = $offsetIndex; + $sequence = Sequence::fromBinary($binaryData, $offsetIndex); + $offsetOfSequence += $sequence->getNumberOfLengthOctets() + 1; + + if ($sequence->getObjectLength() != $contentLength) { + throw new ParserException('Can not parse Subject Alternative Names: The Sequence length does not match the length of the surrounding octet string', $offsetIndex); + } + + $parsedObject = new self(); + /** @var \FG\ASN1\ASNObject $object */ + foreach ($sequence as $object) { + if ($object->getType() == DNSName::IDENTIFIER) { + $domainName = DNSName::fromBinary($binaryData, $offsetOfSequence); + $parsedObject->addDomainName($domainName); + } elseif ($object->getType() == IPAddress::IDENTIFIER) { + $ip = IPAddress::fromBinary($binaryData, $offsetOfSequence); + $parsedObject->addIP($ip); + } else { + throw new ParserException('Could not parse Subject Alternative Name: Only DNSName and IP SANs are currently supported', $offsetIndex); + } + } + + $parsedObject->getBinary(); // Determine the number of content octets and object sizes once (just to let the equality unit tests pass :/ ) + return $parsedObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/LICENSE b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/LICENSE new file mode 100644 index 00000000..14c82cd5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2016 ignace nyamagana butera + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/composer.json b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/composer.json new file mode 100644 index 00000000..fc34cfe3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/composer.json @@ -0,0 +1,68 @@ +{ + "name": "league/uri-interfaces", + "description" : "Common interface for URI representation", + "keywords": [ + "url", + "uri", + "rfc3986", + "rfc3987" + ], + "license": "MIT", + "homepage": "http://github.com/thephpleague/uri-interfaces", + "authors": [ + { + "name" : "Ignace Nyamagana Butera", + "email" : "nyamsprod@gmail.com", + "homepage" : "https://nyamsprod.com" + } + ], + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nyamsprod" + } + ], + "require": { + "php" : "^7.2 || ^8.0", + "ext-json": "*" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.19", + "phpstan/phpstan": "^0.12.90", + "phpstan/phpstan-strict-rules": "^0.12.9", + "phpstan/phpstan-phpunit": "^0.12.19", + "phpunit/phpunit": "^8.5.15 || ^9.5" + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "src/" + } + }, + "scripts": { + "phpunit": "phpunit --coverage-text", + "phpcs": "php-cs-fixer fix --dry-run --diff -vvv --allow-risky=yes --ansi", + "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi", + "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit 192M", + "test": [ + "@phpunit", + "@phpstan", + "@phpcs:fix" + ] + }, + "scripts-descriptions": { + "phpunit": "Runs package test suite", + "phpstan": "Runs complete codebase static analysis", + "phpcs": "Runs coding style testing", + "phpcs:fix": "Fix coding style issues", + "test": "Runs all tests" + }, + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "suggest": { + "ext-intl": "to use the IDNA feature", + "symfony/intl": "to use the IDNA feature via Symfony Polyfill" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php new file mode 100644 index 00000000..ed6c2b8d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; + +interface AuthorityInterface extends UriComponentInterface +{ + /** + * Returns the host component of the authority. + */ + public function getHost(): ?string; + + /** + * Returns the port component of the authority. + */ + public function getPort(): ?int; + + /** + * Returns the user information component of the authority. + */ + public function getUserInfo(): ?string; + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * A null value provided for the host is equivalent to removing the host + * information. + * + * @param ?string $host + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + * @throws IdnSupportMissing for component or transformations + * requiring IDN support when IDN support is not present + * or misconfigured. + */ + public function withHost(?string $host): self; + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param ?int $port + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withPort(?int $port): self; + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; a null value for the user is equivalent to removing user + * information. + * + * @param ?string $user + * @param ?string $password + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withUserInfo(?string $user, ?string $password = null): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php new file mode 100644 index 00000000..1e4f3856 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface DataPathInterface extends PathInterface +{ + /** + * Retrieve the data mime type associated to the URI. + * + * If no mimetype is present, this method MUST return the default mimetype 'text/plain'. + * + * @see http://tools.ietf.org/html/rfc2397#section-2 + */ + public function getMimeType(): string; + + /** + * Retrieve the parameters associated with the Mime Type of the URI. + * + * If no parameters is present, this method MUST return the default parameter 'charset=US-ASCII'. + * + * @see http://tools.ietf.org/html/rfc2397#section-2 + */ + public function getParameters(): string; + + /** + * Retrieve the mediatype associated with the URI. + * + * If no mediatype is present, this method MUST return the default parameter 'text/plain;charset=US-ASCII'. + * + * @see http://tools.ietf.org/html/rfc2397#section-3 + * + * @return string The URI scheme. + */ + public function getMediaType(): string; + + /** + * Retrieves the data string. + * + * Retrieves the data part of the path. If no data part is provided return + * a empty string + */ + public function getData(): string; + + /** + * Tells whether the data is binary safe encoded. + */ + public function isBinaryData(): bool; + + /** + * Save the data to a specific file. + */ + public function save(string $path, string $mode = 'w'): \SplFileObject; + + /** + * Returns an instance where the data part is base64 encoded. + * + * This method MUST retain the state of the current instance, and return + * an instance where the data part is base64 encoded + */ + public function toBinary(): self; + + /** + * Returns an instance where the data part is url encoded following RFC3986 rules. + * + * This method MUST retain the state of the current instance, and return + * an instance where the data part is url encoded + */ + public function toAscii(): self; + + /** + * Return an instance with the specified mediatype parameters. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified mediatype parameters. + * + * Users must provide encoded characters. + * + * An empty parameters value is equivalent to removing the parameter. + */ + public function withParameters(string $parameters): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php new file mode 100644 index 00000000..2490310f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\SyntaxError; + +/** + * @extends \IteratorAggregate + */ +interface DomainHostInterface extends \Countable, HostInterface, \IteratorAggregate +{ + /** + * Returns the labels total number. + */ + public function count(): int; + + /** + * Iterate over the Domain labels. + * + * @return \Iterator + */ + public function getIterator(): \Iterator; + + /** + * Retrieves a single host label. + * + * If the label offset has not been set, returns the null value. + */ + public function get(int $offset): ?string; + + /** + * Returns the associated key for a specific label or all the keys. + * + * @param ?string $label + * + * @return int[] + */ + public function keys(?string $label = null): array; + + /** + * Tells whether the domain is absolute. + */ + public function isAbsolute(): bool; + + /** + * Prepends a label to the host. + */ + public function prepend(string $label): self; + + /** + * Appends a label to the host. + */ + public function append(string $label): self; + + /** + * Returns an instance with its Root label. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + public function withRootLabel(): self; + + /** + * Returns an instance without its Root label. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + public function withoutRootLabel(): self; + + /** + * Returns an instance with the modified label. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the new label + * + * If $key is non-negative, the added label will be the label at $key position from the start. + * If $key is negative, the added label will be the label at $key position from the end. + * + * @throws SyntaxError If the key is invalid + */ + public function withLabel(int $key, string $label): self; + + /** + * Returns an instance without the specified label. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component + * + * If $key is non-negative, the removed label will be the label at $key position from the start. + * If $key is negative, the removed label will be the label at $key position from the end. + * + * @param int ...$keys + * + * @throws SyntaxError If the key is invalid + */ + public function withoutLabel(int ...$keys): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php new file mode 100644 index 00000000..3d80f066 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface FragmentInterface extends UriComponentInterface +{ + /** + * Returns the decoded fragment. + */ + public function decoded(): ?string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/HostInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/HostInterface.php new file mode 100644 index 00000000..a8b8bb35 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/HostInterface.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface HostInterface extends UriComponentInterface +{ + /** + * Returns the ascii representation. + */ + public function toAscii(): ?string; + + /** + * Returns the unicode representation. + */ + public function toUnicode(): ?string; + + /** + * Returns the IP version. + * + * If the host is a not an IP this method will return null + */ + public function getIpVersion(): ?string; + + /** + * Returns the IP component If the Host is an IP address. + * + * If the host is a not an IP this method will return null + */ + public function getIp(): ?string; + + /** + * Tells whether the host is a domain name. + */ + public function isDomain(): bool; + + /** + * Tells whether the host is an IP Address. + */ + public function isIp(): bool; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php new file mode 100644 index 00000000..1e2242ab --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface IpHostInterface extends HostInterface +{ + /** + * Returns whether or not the host is an IPv4 address. + */ + public function isIpv4(): bool; + /** + * Returns whether or not the host is an IPv6 address. + */ + public function isIpv6(): bool; + + /** + * Returns whether or not the host is an IPv6 address. + */ + public function isIpFuture(): bool; + + /** + * Returns whether or not the host has a ZoneIdentifier. + * + * @see http://tools.ietf.org/html/rfc6874#section-4 + */ + public function hasZoneIdentifier(): bool; + + /** + * Returns an host without its zone identifier according to RFC6874. + * + * This method MUST retain the state of the current instance, and return + * an instance without the host zone identifier according to RFC6874 + * + * @see http://tools.ietf.org/html/rfc6874#section-4 + */ + public function withoutZoneIdentifier(): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PathInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PathInterface.php new file mode 100644 index 00000000..389c0ff0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PathInterface.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\SyntaxError; + +interface PathInterface extends UriComponentInterface +{ + /** + * Returns the decoded path. + */ + public function decoded(): string; + + /** + * Returns whether or not the path is absolute or relative. + */ + public function isAbsolute(): bool; + + /** + * Returns whether or not the path has a trailing delimiter. + */ + public function hasTrailingSlash(): bool; + + /** + * Returns an instance without dot segments. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component normalized by removing + * the dot segment. + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withoutDotSegments(): self; + + /** + * Returns an instance with a leading slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component with a leading slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withLeadingSlash(): self; + + /** + * Returns an instance without a leading slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component without a leading slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withoutLeadingSlash(): self; + + /** + * Returns an instance with a trailing slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component with a trailing slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withTrailingSlash(): self; + + /** + * Returns an instance without a trailing slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component without a trailing slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withoutTrailingSlash(): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PortInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PortInterface.php new file mode 100644 index 00000000..7230c4ad --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/PortInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface PortInterface extends UriComponentInterface +{ + /** + * Returns the integer representation of the Port. + */ + public function toInt(): ?int; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/QueryInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/QueryInterface.php new file mode 100644 index 00000000..f7081ea2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/QueryInterface.php @@ -0,0 +1,227 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +/** + * @extends \IteratorAggregate + */ +interface QueryInterface extends \Countable, \IteratorAggregate, UriComponentInterface +{ + /** + * Returns the query separator. + */ + public function getSeparator(): string; + + /** + * Returns the number of key/value pairs present in the object. + */ + public function count(): int; + + /** + * Returns an iterator allowing to go through all key/value pairs contained in this object. + * + * The pair is represented as an array where the first value is the pair key + * and the second value the pair value. + * + * The key of each pair is a string + * The value of each pair is a scalar or the null value + * + * @return \Iterator + */ + public function getIterator(): \Iterator; + + /** + * Returns an iterator allowing to go through all key/value pairs contained in this object. + * + * The return type is as a Iterator where its offset is the pair key and its value the pair value. + * + * The key of each pair is a string + * The value of each pair is a scalar or the null value + * + * @return iterable + */ + public function pairs(): iterable; + + /** + * Tells whether a pair with a specific name exists. + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-has + */ + public function has(string $key): bool; + + /** + * Returns the first value associated to the given pair name. + * + * If no value is found null is returned + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-get + */ + public function get(string $key): ?string; + + /** + * Returns all the values associated to the given pair name as an array or all + * the instance pairs. + * + * If no value is found an empty array is returned + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-getall + * + * @return array + */ + public function getAll(string $key): array; + + /** + * Returns the store PHP variables as elements of an array. + * + * The result is similar as PHP parse_str when used with its + * second argument with the difference that variable names are + * not mangled. + * + * If a key is submitted it will returns the value attached to it or null + * + * @see http://php.net/parse_str + * @see https://wiki.php.net/rfc/on_demand_name_mangling + * + * @param ?string $key + * @return mixed the collection of stored PHP variables or the empty array if no input is given, + * the single value of a stored PHP variable or null if the variable is not present in the collection + */ + public function params(?string $key = null); + + /** + * Returns the RFC1738 encoded query. + */ + public function toRFC1738(): ?string; + + /** + * Returns the RFC3986 encoded query. + * + * @see ::getContent + */ + public function toRFC3986(): ?string; + + /** + * Returns an instance with a different separator. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component with a different separator + */ + public function withSeparator(string $separator): self; + + /** + * Sorts the query string by offset, maintaining offset to data correlations. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-sort + */ + public function sort(): self; + + /** + * Returns an instance without duplicate key/value pair. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component normalized by removing + * duplicate pairs whose key/value are the same. + */ + public function withoutDuplicates(): self; + + /** + * Returns an instance without empty key/value where the value is the null value. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component normalized by removing + * empty pairs. + * + * A pair is considered empty if its value is equal to the null value + */ + public function withoutEmptyPairs(): self; + + /** + * Returns an instance where numeric indices associated to PHP's array like key are removed. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component normalized so that numeric indexes + * are removed from the pair key value. + * + * ie.: toto[3]=bar[3]&foo=bar becomes toto[]=bar[3]&foo=bar + */ + public function withoutNumericIndices(): self; + + /** + * Returns an instance with the a new key/value pair added to it. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * If the pair already exists the value will replace the existing value. + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-set + * + * @param ?string $value + */ + public function withPair(string $key, ?string $value): self; + + /** + * Returns an instance with the new pairs set to it. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * @see ::withPair + */ + public function merge(string $query): self; + + /** + * Returns an instance without the specified keys. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component + * + * @param string ...$keys + */ + public function withoutPair(string ...$keys): self; + + /** + * Returns a new instance with a specified key/value pair appended as a new pair. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * @param ?string $value + */ + public function appendTo(string $key, ?string $value): self; + + /** + * Returns an instance with the new pairs appended to it. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * If the pair already exists the value will be added to it. + */ + public function append(string $query): self; + + /** + * Returns an instance without the specified params. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component without PHP's value. + * PHP's mangled is not taken into account. + * + * @param string ...$keys + */ + public function withoutParam(string ...$keys): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php new file mode 100644 index 00000000..53065fff --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\SyntaxError; + +/** + * @extends \IteratorAggregate + */ +interface SegmentedPathInterface extends \Countable, \IteratorAggregate, PathInterface +{ + /** + * Returns the total number of segments in the path. + */ + public function count(): int; + + /** + * Iterate over the path segment. + * + * @return \Iterator + */ + public function getIterator(): \Iterator; + + /** + * Returns parent directory's path. + */ + public function getDirname(): string; + + /** + * Returns the path basename. + */ + public function getBasename(): string; + + /** + * Returns the basename extension. + */ + public function getExtension(): string; + + /** + * Retrieves a single path segment. + * + * If the segment offset has not been set, returns null. + */ + public function get(int $offset): ?string; + + /** + * Returns the associated key for a specific segment. + * + * If a value is specified only the keys associated with + * the given value will be returned + * + * @param ?string $segment + * + * @return int[] + */ + public function keys(?string $segment = null): array; + + /** + * Appends a segment to the path. + */ + public function append(string $segment): self; + + /** + * Prepends a segment to the path. + */ + public function prepend(string $segment): self; + + /** + * Returns an instance with the modified segment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the new segment + * + * If $key is non-negative, the added segment will be the segment at $key position from the start. + * If $key is negative, the added segment will be the segment at $key position from the end. + * + * @param ?string $segment + * + * @throws SyntaxError If the key is invalid + */ + public function withSegment(int $key, ?string $segment): self; + + /** + * Returns an instance without the specified segment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component + * + * If $key is non-negative, the removed segment will be the segment at $key position from the start. + * If $key is negative, the removed segment will be the segment at $key position from the end. + * + * @param int ...$keys remaining keys to remove + * + * @throws SyntaxError If the key is invalid + */ + public function withoutSegment(int ...$keys): self; + + /** + * Returns an instance without duplicate delimiters. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component normalized by removing + * multiple consecutive empty segment + */ + public function withoutEmptySegments(): self; + + /** + * Returns an instance with the specified parent directory's path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the extension basename modified. + * + * @param ?string $path + */ + public function withDirname(?string $path): self; + + /** + * Returns an instance with the specified basename. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the extension basename modified. + * + * @param ?string $basename + */ + public function withBasename(?string $basename): self; + + /** + * Returns an instance with the specified basename extension. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the extension basename modified. + * + * @param ?string $extension + */ + public function withExtension(?string $extension): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php new file mode 100644 index 00000000..c7b39bb5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; + +interface UriComponentInterface extends \JsonSerializable +{ + /** + * Returns the instance content. + * + * If the instance is defined, the value returned MUST be encoded according to the + * selected encoding algorithm. In any case, the value MUST NOT double-encode any character + * depending on the selected encoding algorithm. + * + * To determine what characters to encode, please refer to RFC 3986, Sections 2 and 3. + * or RFC 3987 Section 3. By default the content is encoded according to RFC3986 + * + * If the instance is not defined null is returned + */ + public function getContent(): ?string; + + /** + * Returns the instance string representation. + * + * If the instance is defined, the value returned MUST be percent-encoded, + * but MUST NOT double-encode any characters. To determine what characters + * to encode, please refer to RFC 3986, Sections 2 and 3. + * + * If the instance is not defined an empty string is returned + */ + public function __toString(): string; + + /** + * Returns the instance json representation. + * + * If the instance is defined, the value returned MUST be percent-encoded, + * but MUST NOT double-encode any characters. To determine what characters + * to encode, please refer to RFC 3986 or RFC 1738. + * + * If the instance is not defined null is returned + */ + public function jsonSerialize(): ?string; + + /** + * Returns the instance string representation with its optional URI delimiters. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode any + * characters. To determine what characters to encode, please refer to RFC 3986, + * Sections 2 and 3. + * + * If the instance is not defined an empty string is returned + */ + public function getUriComponent(): string; + + /** + * Returns an instance with the specified content. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified content. + * + * Users can provide both encoded and decoded content characters. + * + * A null value is equivalent to removing the component content. + * + * + * @param ?string $content + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + * @throws IdnSupportMissing for component or transformations + * requiring IDN support when IDN support is not present + * or misconfigured. + */ + public function withContent(?string $content): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriException.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriException.php new file mode 100644 index 00000000..c0fec2a1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use Throwable; + +interface UriException extends Throwable +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriInterface.php new file mode 100644 index 00000000..b6eb6a1f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UriInterface.php @@ -0,0 +1,292 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; + +interface UriInterface extends \JsonSerializable +{ + /** + * Returns the string representation as a URI reference. + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + */ + public function __toString(): string; + + /** + * Returns the string representation as a URI reference. + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @see ::__toString + */ + public function jsonSerialize(): string; + + /** + * Retrieve the scheme component of the URI. + * + * If no scheme is present, this method MUST return a null value. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.1. + * + * The trailing ":" character is not part of the scheme and MUST NOT be + * added. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.1 + */ + public function getScheme(): ?string; + + /** + * Retrieve the authority component of the URI. + * + * If no scheme is present, this method MUST return a null value. + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + */ + public function getAuthority(): ?string; + + /** + * Retrieve the user information component of the URI. + * + * If no scheme is present, this method MUST return a null value. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + */ + public function getUserInfo(): ?string; + + /** + * Retrieve the host component of the URI. + * + * If no host is present this method MUST return a null value. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + public function getHost(): ?string; + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + */ + public function getPort(): ?int; + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + */ + public function getPath(): string; + + /** + * Retrieve the query string of the URI. + * + * If no host is present this method MUST return a null value. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + */ + public function getQuery(): ?string; + + /** + * Retrieve the fragment component of the URI. + * + * If no host is present this method MUST return a null value. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + */ + public function getFragment(): ?string; + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * A null value provided for the scheme is equivalent to removing the scheme + * information. + * + * @param ?string $scheme + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withScheme(?string $scheme): self; + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; a null value for the user is equivalent to removing user + * information. + * + * @param ?string $user + * @param ?string $password + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withUserInfo(?string $user, ?string $password = null): self; + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * A null value provided for the host is equivalent to removing the host + * information. + * + * @param ?string $host + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + * @throws IdnSupportMissing for component or transformations + * requiring IDN support when IDN support is not present + * or misconfigured. + */ + public function withHost(?string $host): self; + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param ?int $port + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withPort(?int $port): self; + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withPath(string $path): self; + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * A null value provided for the query is equivalent to removing the query + * information. + * + * @param ?string $query + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withQuery(?string $query): self; + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * A null value provided for the fragment is equivalent to removing the fragment + * information. + * + * @param ?string $fragment + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withFragment(?string $fragment): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php new file mode 100644 index 00000000..6411f9b6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface UserInfoInterface extends UriComponentInterface +{ + /** + * Returns the user component part. + */ + public function getUser(): ?string; + + /** + * Returns the pass component part. + */ + public function getPass(): ?string; + + /** + * Returns an instance with the specified user and/or pass. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user. + * + * An empty user is equivalent to removing the user information. + * + * @param ?string $user + * @param ?string $pass + */ + public function withUserInfo(?string $user, ?string $pass = null): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php new file mode 100644 index 00000000..0105b2da --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Contracts\UriException; + +class FileinfoSupportMissing extends \RuntimeException implements UriException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php new file mode 100644 index 00000000..8ff3b538 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Contracts\UriException; + +class IdnSupportMissing extends \RuntimeException implements UriException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php new file mode 100644 index 00000000..80259f3b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Idna\IdnaInfo; + +final class IdnaConversionFailed extends SyntaxError +{ + /** @var IdnaInfo|null */ + private $idnaInfo; + + private function __construct(string $message, IdnaInfo $idnaInfo = null) + { + parent::__construct($message); + $this->idnaInfo = $idnaInfo; + } + + public static function dueToIDNAError(string $domain, IdnaInfo $idnaInfo): self + { + return new self( + 'The host `'.$domain.'` is invalid : '.implode(', ', $idnaInfo->errorList()).' .', + $idnaInfo + ); + } + + public static function dueToInvalidHost(string $domain): self + { + return new self('The host `'.$domain.'` is not a valid IDN host'); + } + + public function idnaInfo(): ?IdnaInfo + { + return $this->idnaInfo; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php new file mode 100644 index 00000000..1b5e4cbd --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Contracts\UriException; + +class SyntaxError extends \InvalidArgumentException implements UriException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/Idna.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/Idna.php new file mode 100644 index 00000000..59306874 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/Idna.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Idna; + +use League\Uri\Exceptions\IdnaConversionFailed; +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; +use function defined; +use function function_exists; +use function idn_to_ascii; +use function idn_to_utf8; +use function rawurldecode; +use const INTL_IDNA_VARIANT_UTS46; + +/** + * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html + */ +final class Idna +{ + private const REGEXP_IDNA_PATTERN = '/[^\x20-\x7f]/'; + private const MAX_DOMAIN_LENGTH = 253; + private const MAX_LABEL_LENGTH = 63; + + /** + * General registered name regular expression. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 + * @see https://regex101.com/r/fptU8V/1 + */ + private const REGEXP_REGISTERED_NAME = '/ + (?(DEFINE) + (?[a-z0-9_~\-]) # . is missing as it is used to separate labels + (?[!$&\'()*+,;=]) + (?%[A-F0-9]{2}) + (?(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*) + ) + ^(?:(?®_name)\.)*(?®_name)\.?$ + /ix'; + + /** + * IDNA options. + */ + public const IDNA_DEFAULT = 0; + public const IDNA_ALLOW_UNASSIGNED = 1; + public const IDNA_USE_STD3_RULES = 2; + public const IDNA_CHECK_BIDI = 4; + public const IDNA_CHECK_CONTEXTJ = 8; + public const IDNA_NONTRANSITIONAL_TO_ASCII = 0x10; + public const IDNA_NONTRANSITIONAL_TO_UNICODE = 0x20; + public const IDNA_CHECK_CONTEXTO = 0x40; + + /** + * IDNA errors. + */ + public const ERROR_NONE = 0; + public const ERROR_EMPTY_LABEL = 1; + public const ERROR_LABEL_TOO_LONG = 2; + public const ERROR_DOMAIN_NAME_TOO_LONG = 4; + public const ERROR_LEADING_HYPHEN = 8; + public const ERROR_TRAILING_HYPHEN = 0x10; + public const ERROR_HYPHEN_3_4 = 0x20; + public const ERROR_LEADING_COMBINING_MARK = 0x40; + public const ERROR_DISALLOWED = 0x80; + public const ERROR_PUNYCODE = 0x100; + public const ERROR_LABEL_HAS_DOT = 0x200; + public const ERROR_INVALID_ACE_LABEL = 0x400; + public const ERROR_BIDI = 0x800; + public const ERROR_CONTEXTJ = 0x1000; + public const ERROR_CONTEXTO_PUNCTUATION = 0x2000; + public const ERROR_CONTEXTO_DIGITS = 0x4000; + + /** + * IDNA default options. + */ + public const IDNA2008_ASCII = self::IDNA_NONTRANSITIONAL_TO_ASCII + | self::IDNA_CHECK_BIDI + | self::IDNA_USE_STD3_RULES + | self::IDNA_CHECK_CONTEXTJ; + public const IDNA2008_UNICODE = self::IDNA_NONTRANSITIONAL_TO_UNICODE + | self::IDNA_CHECK_BIDI + | self::IDNA_USE_STD3_RULES + | self::IDNA_CHECK_CONTEXTJ; + + /** + * @codeCoverageIgnore + */ + private static function supportsIdna(): void + { + static $idnSupport; + if (null === $idnSupport) { + $idnSupport = function_exists('\idn_to_ascii') && defined('\INTL_IDNA_VARIANT_UTS46'); + } + + if (!$idnSupport) { + throw new IdnSupportMissing('IDN host can not be processed. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.'); + } + } + + /** + * Converts the input to its IDNA ASCII form. + * + * This method returns the string converted to IDN ASCII form + * + * @throws SyntaxError if the string can not be converted to ASCII using IDN UTS46 algorithm + */ + public static function toAscii(string $domain, int $options): IdnaInfo + { + $domain = rawurldecode($domain); + + if (1 === preg_match(self::REGEXP_IDNA_PATTERN, $domain)) { + self::supportsIdna(); + + /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + if ([] === $idnaInfo) { + return IdnaInfo::fromIntl([ + 'result' => strtolower($domain), + 'isTransitionalDifferent' => false, + 'errors' => self::validateDomainAndLabelLength($domain), + ]); + } + + /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + return IdnaInfo::fromIntl($idnaInfo); + } + + $error = self::ERROR_NONE; + if (1 !== preg_match(self::REGEXP_REGISTERED_NAME, $domain)) { + $error |= self::ERROR_DISALLOWED; + } + + return IdnaInfo::fromIntl([ + 'result' => strtolower($domain), + 'isTransitionalDifferent' => false, + 'errors' => self::validateDomainAndLabelLength($domain) | $error, + ]); + } + + /** + * Converts the input to its IDNA UNICODE form. + * + * This method returns the string converted to IDN UNICODE form + * + * @throws SyntaxError if the string can not be converted to UNICODE using IDN UTS46 algorithm + */ + public static function toUnicode(string $domain, int $options): IdnaInfo + { + $domain = rawurldecode($domain); + + if (false === stripos($domain, 'xn--')) { + return IdnaInfo::fromIntl(['result' => $domain, 'isTransitionalDifferent' => false, 'errors' => self::ERROR_NONE]); + } + + self::supportsIdna(); + + /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + idn_to_utf8($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + if ([] === $idnaInfo) { + throw IdnaConversionFailed::dueToInvalidHost($domain); + } + + /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + return IdnaInfo::fromIntl($idnaInfo); + } + + /** + * Adapted from https://github.com/TRowbotham/idna. + * + * @see https://github.com/TRowbotham/idna/blob/master/src/Idna.php#L236 + */ + private static function validateDomainAndLabelLength(string $domain): int + { + $error = self::ERROR_NONE; + $labels = explode('.', $domain); + $maxDomainSize = self::MAX_DOMAIN_LENGTH; + $length = count($labels); + + // If the last label is empty and it is not the first label, then it is the root label. + // Increase the max size by 1, making it 254, to account for the root label's "." + // delimiter. This also means we don't need to check the last label's length for being too + // long. + if ($length > 1 && $labels[$length - 1] === '') { + ++$maxDomainSize; + array_pop($labels); + } + + if (strlen($domain) > $maxDomainSize) { + $error |= self::ERROR_DOMAIN_NAME_TOO_LONG; + } + + foreach ($labels as $label) { + if (strlen($label) > self::MAX_LABEL_LENGTH) { + $error |= self::ERROR_LABEL_TOO_LONG; + + break; + } + } + + return $error; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/IdnaInfo.php b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/IdnaInfo.php new file mode 100644 index 00000000..73610a28 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri-interfaces/src/Idna/IdnaInfo.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Idna; + +use function array_filter; +use const ARRAY_FILTER_USE_KEY; + +/** + * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html + */ +final class IdnaInfo +{ + private const ERRORS = [ + Idna::ERROR_EMPTY_LABEL => 'a non-final domain name label (or the whole domain name) is empty', + Idna::ERROR_LABEL_TOO_LONG => 'a domain name label is longer than 63 bytes', + Idna::ERROR_DOMAIN_NAME_TOO_LONG => 'a domain name is longer than 255 bytes in its storage form', + Idna::ERROR_LEADING_HYPHEN => 'a label starts with a hyphen-minus ("-")', + Idna::ERROR_TRAILING_HYPHEN => 'a label ends with a hyphen-minus ("-")', + Idna::ERROR_HYPHEN_3_4 => 'a label contains hyphen-minus ("-") in the third and fourth positions', + Idna::ERROR_LEADING_COMBINING_MARK => 'a label starts with a combining mark', + Idna::ERROR_DISALLOWED => 'a label or domain name contains disallowed characters', + Idna::ERROR_PUNYCODE => 'a label starts with "xn--" but does not contain valid Punycode', + Idna::ERROR_LABEL_HAS_DOT => 'a label contains a dot=full stop', + Idna::ERROR_INVALID_ACE_LABEL => 'An ACE label does not contain a valid label string', + Idna::ERROR_BIDI => 'a label does not meet the IDNA BiDi requirements (for right-to-left characters)', + Idna::ERROR_CONTEXTJ => 'a label does not meet the IDNA CONTEXTJ requirements', + Idna::ERROR_CONTEXTO_DIGITS => 'a label does not meet the IDNA CONTEXTO requirements for digits', + Idna::ERROR_CONTEXTO_PUNCTUATION => 'a label does not meet the IDNA CONTEXTO requirements for punctuation characters. Some punctuation characters "Would otherwise have been DISALLOWED" but are allowed in certain contexts', + ]; + + /** @var string */ + private $result; + + /** @var bool */ + private $isTransitionalDifferent; + + /** @var int */ + private $errors; + + /** + * @var array + */ + private $errorList; + + private function __construct(string $result, bool $isTransitionalDifferent, int $errors) + { + $this->result = $result; + $this->errors = $errors; + $this->isTransitionalDifferent = $isTransitionalDifferent; + $this->errorList = array_filter( + self::ERRORS, + function (int $error): bool { + return 0 !== ($error & $this->errors); + }, + ARRAY_FILTER_USE_KEY + ); + } + + /** + * @param array{result:string, isTransitionalDifferent:bool, errors:int} $infos + */ + public static function fromIntl(array $infos): self + { + return new self($infos['result'], $infos['isTransitionalDifferent'], $infos['errors']); + } + + /** + * @param array{result:string, isTransitionalDifferent:bool, errors:int} $properties + */ + public static function __set_state(array $properties): self + { + return self::fromIntl($properties); + } + + public function result(): string + { + return $this->result; + } + + public function isTransitionalDifferent(): bool + { + return $this->isTransitionalDifferent; + } + + public function errors(): int + { + return $this->errors; + } + + public function error(int $error): ?string + { + return $this->errorList[$error] ?? null; + } + + /** + * @return array + */ + public function errorList(): array + { + return $this->errorList; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/.php-cs-fixer.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/.php-cs-fixer.php new file mode 100644 index 00000000..7304a712 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/.php-cs-fixer.php @@ -0,0 +1,58 @@ + + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +EOF; + +$finder = PhpCsFixer\Finder::create() + ->in(__DIR__.'/src') + ->in(__DIR__.'/benchmark') +; + +$config = new PhpCsFixer\Config(); + +return $config + ->setRules([ + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'concat_space' => ['spacing' => 'none'], + 'header_comment' => [ + 'comment_type' => 'PHPDoc', + 'header' => $header, + 'location' => 'after_open', + 'separate' => 'both', + ], + 'new_with_braces' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_empty_phpdoc' => true, + 'no_empty_comment' => true, + 'no_leading_import_slash' => true, + 'no_superfluous_phpdoc_tags' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_unused_imports' => true, + 'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'], + 'phpdoc_add_missing_param_annotation' => ['only_untyped' => false], + 'phpdoc_align' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_summary' => true, + 'psr_autoloading' => true, + 'return_type_declaration' => ['space_before' => 'none'], + 'single_blank_line_before_namespace' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'ternary_operator_spaces' => true, + 'trailing_comma_in_multiline' => true, + 'trim_array_spaces' => true, + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => true, + ]) + ->setFinder($finder) +; diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/LICENSE b/wp-content/plugins/wp-webauthn/vendor/league/uri/LICENSE new file mode 100644 index 00000000..3b52528f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 ignace nyamagana butera + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/composer.json b/wp-content/plugins/wp-webauthn/vendor/league/uri/composer.json new file mode 100644 index 00000000..a241129f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/composer.json @@ -0,0 +1,104 @@ +{ + "name": "league/uri", + "type": "library", + "description" : "URI manipulation library", + "keywords": [ + "url", + "uri", + "rfc3986", + "rfc3987", + "rfc6570", + "psr-7", + "parse_url", + "http", + "https", + "ws", + "ftp", + "data-uri", + "file-uri", + "middleware", + "parse_str", + "query-string", + "querystring", + "hostname", + "uri-template" + ], + "license": "MIT", + "homepage": "http://uri.thephpleague.com", + "authors": [ + { + "name" : "Ignace Nyamagana Butera", + "email" : "nyamsprod@gmail.com", + "homepage" : "https://nyamsprod.com" + } + ], + "support": { + "forum": "https://thephpleague.slack.com", + "docs": "https://uri.thephpleague.com", + "issues": "https://github.com/thephpleague/uri/issues" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nyamsprod" + } + ], + "require": { + "php": "^7.3 || ^8.0", + "ext-json": "*", + "psr/http-message": "^1.0", + "league/uri-interfaces": "^2.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.19 || ^3.0", + "phpunit/phpunit" : "^8.0 || ^9.0", + "phpstan/phpstan": "^0.12.90", + "phpstan/phpstan-strict-rules": "^0.12.11", + "phpstan/phpstan-phpunit": "^0.12.22", + "psr/http-factory": "^1.0" + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "LeagueTest\\Uri\\": "tests" + } + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "scripts": { + "phpcs": "php-cs-fixer fix -v --diff --dry-run --allow-risky=yes --ansi", + "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi", + "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit=256M", + "phpunit": "phpunit --coverage-text", + "test": [ + "@phpunit", + "@phpstan", + "@phpcs" + ] + }, + "scripts-descriptions": { + "phpcs": "Runs coding style test suite", + "phpstan": "Runs complete codebase static analysis", + "phpunit": "Runs unit and functional testing", + "test": "Runs full test suite" + }, + "suggest": { + "league/uri-components" : "Needed to easily manipulate URI objects", + "ext-intl" : "Needed to improve host validation", + "ext-fileinfo": "Needed to create Data URI from a filepath", + "psr/http-factory": "Needed to use the URI factory" + }, + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "config": { + "sort-packages": true + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Exceptions/TemplateCanNotBeExpanded.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Exceptions/TemplateCanNotBeExpanded.php new file mode 100644 index 00000000..5618154c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Exceptions/TemplateCanNotBeExpanded.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Contracts\UriException; + +class TemplateCanNotBeExpanded extends \InvalidArgumentException implements UriException +{ + public static function dueToUnableToProcessValueListWithPrefix(string $variableName): self + { + return new self('The ":" modifier can not be applied on "'.$variableName.'" since it is a list of values.'); + } + + public static function dueToNestedListOfValue(string $variableName): self + { + return new self('The "'.$variableName.'" can not be a nested list.'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Http.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Http.php new file mode 100644 index 00000000..2bbd8a77 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Http.php @@ -0,0 +1,335 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri; + +use League\Uri\Contracts\UriInterface; +use League\Uri\Exceptions\SyntaxError; +use Psr\Http\Message\UriInterface as Psr7UriInterface; +use function is_object; +use function is_scalar; +use function method_exists; +use function sprintf; + +final class Http implements Psr7UriInterface, \JsonSerializable +{ + /** + * @var UriInterface + */ + private $uri; + + /** + * New instance. + */ + private function __construct(UriInterface $uri) + { + $this->validate($uri); + $this->uri = $uri; + } + + /** + * Validate the submitted uri against PSR-7 UriInterface. + * + * @throws SyntaxError if the given URI does not follow PSR-7 UriInterface rules + */ + private function validate(UriInterface $uri): void + { + $scheme = $uri->getScheme(); + if (null === $scheme && '' === $uri->getHost()) { + throw new SyntaxError(sprintf('an URI without scheme can not contains a empty host string according to PSR-7: %s', (string) $uri)); + } + + $port = $uri->getPort(); + if (null !== $port && ($port < 0 || $port > 65535)) { + throw new SyntaxError(sprintf('The URI port is outside the established TCP and UDP port ranges: %s', (string) $uri->getPort())); + } + } + + /** + * Static method called by PHP's var export. + */ + public static function __set_state(array $components): self + { + return new self($components['uri']); + } + + /** + * Create a new instance from a string. + * + * @param string|mixed $uri + */ + public static function createFromString($uri = ''): self + { + return new self(Uri::createFromString($uri)); + } + + /** + * Create a new instance from a hash of parse_url parts. + * + * @param array $components a hash representation of the URI similar + * to PHP parse_url function result + */ + public static function createFromComponents(array $components): self + { + return new self(Uri::createFromComponents($components)); + } + + /** + * Create a new instance from the environment. + */ + public static function createFromServer(array $server): self + { + return new self(Uri::createFromServer($server)); + } + + /** + * Create a new instance from a URI and a Base URI. + * + * The returned URI must be absolute. + * + * @param mixed $uri the input URI to create + * @param mixed $base_uri the base URI used for reference + */ + public static function createFromBaseUri($uri, $base_uri = null): self + { + return new self(Uri::createFromBaseUri($uri, $base_uri)); + } + + /** + * Create a new instance from a URI object. + * + * @param Psr7UriInterface|UriInterface $uri the input URI to create + */ + public static function createFromUri($uri): self + { + if ($uri instanceof UriInterface) { + return new self($uri); + } + + return new self(Uri::createFromUri($uri)); + } + + /** + * {@inheritDoc} + */ + public function getScheme(): string + { + return (string) $this->uri->getScheme(); + } + + /** + * {@inheritDoc} + */ + public function getAuthority(): string + { + return (string) $this->uri->getAuthority(); + } + + /** + * {@inheritDoc} + */ + public function getUserInfo(): string + { + return (string) $this->uri->getUserInfo(); + } + + /** + * {@inheritDoc} + */ + public function getHost(): string + { + return (string) $this->uri->getHost(); + } + + /** + * {@inheritDoc} + */ + public function getPort(): ?int + { + return $this->uri->getPort(); + } + + /** + * {@inheritDoc} + */ + public function getPath(): string + { + return $this->uri->getPath(); + } + + /** + * {@inheritDoc} + */ + public function getQuery(): string + { + return (string) $this->uri->getQuery(); + } + + /** + * {@inheritDoc} + */ + public function getFragment(): string + { + return (string) $this->uri->getFragment(); + } + + /** + * {@inheritDoc} + */ + public function withScheme($scheme): self + { + $scheme = $this->filterInput($scheme); + if ('' === $scheme) { + $scheme = null; + } + + $uri = $this->uri->withScheme($scheme); + if ($uri->getScheme() === $this->uri->getScheme()) { + return $this; + } + + return new self($uri); + } + + /** + * Safely stringify input when possible. + * + * @param mixed $str the value to evaluate as a string + * + * @throws SyntaxError if the submitted data can not be converted to string + * + * @return string|mixed + */ + private function filterInput($str) + { + if (is_scalar($str) || (is_object($str) && method_exists($str, '__toString'))) { + return (string) $str; + } + + return $str; + } + + /** + * {@inheritDoc} + */ + public function withUserInfo($user, $password = null): self + { + $user = $this->filterInput($user); + if ('' === $user) { + $user = null; + } + + $uri = $this->uri->withUserInfo($user, $password); + if ($uri->getUserInfo() === $this->uri->getUserInfo()) { + return $this; + } + + return new self($uri); + } + + /** + * {@inheritDoc} + */ + public function withHost($host): self + { + $host = $this->filterInput($host); + if ('' === $host) { + $host = null; + } + + $uri = $this->uri->withHost($host); + if ($uri->getHost() === $this->uri->getHost()) { + return $this; + } + + return new self($uri); + } + + /** + * {@inheritDoc} + */ + public function withPort($port): self + { + $uri = $this->uri->withPort($port); + if ($uri->getPort() === $this->uri->getPort()) { + return $this; + } + + return new self($uri); + } + + /** + * {@inheritDoc} + */ + public function withPath($path): self + { + $uri = $this->uri->withPath($path); + if ($uri->getPath() === $this->uri->getPath()) { + return $this; + } + + return new self($uri); + } + + /** + * {@inheritDoc} + */ + public function withQuery($query): self + { + $query = $this->filterInput($query); + if ('' === $query) { + $query = null; + } + + $uri = $this->uri->withQuery($query); + if ($uri->getQuery() === $this->uri->getQuery()) { + return $this; + } + + return new self($uri); + } + + /** + * {@inheritDoc} + */ + public function withFragment($fragment): self + { + $fragment = $this->filterInput($fragment); + if ('' === $fragment) { + $fragment = null; + } + + $uri = $this->uri->withFragment($fragment); + if ($uri->getFragment() === $this->uri->getFragment()) { + return $this; + } + + return new self($uri); + } + + /** + * {@inheritDoc} + */ + public function __toString(): string + { + return $this->uri->__toString(); + } + + /** + * {@inheritDoc} + */ + public function jsonSerialize(): string + { + return $this->uri->__toString(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/HttpFactory.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/HttpFactory.php new file mode 100644 index 00000000..fc3bcfab --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/HttpFactory.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri; + +use Psr\Http\Message\UriFactoryInterface; +use Psr\Http\Message\UriInterface; + +final class HttpFactory implements UriFactoryInterface +{ + public function createUri(string $uri = ''): UriInterface + { + return Http::createFromString($uri); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Uri.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Uri.php new file mode 100644 index 00000000..89f9aa13 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/Uri.php @@ -0,0 +1,1397 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri; + +use League\Uri\Contracts\UriInterface; +use League\Uri\Exceptions\FileinfoSupportMissing; +use League\Uri\Exceptions\IdnaConversionFailed; +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; +use League\Uri\Idna\Idna; +use Psr\Http\Message\UriInterface as Psr7UriInterface; +use function array_filter; +use function array_map; +use function base64_decode; +use function base64_encode; +use function count; +use function explode; +use function file_get_contents; +use function filter_var; +use function implode; +use function in_array; +use function inet_pton; +use function is_object; +use function is_scalar; +use function method_exists; +use function preg_match; +use function preg_replace; +use function preg_replace_callback; +use function rawurlencode; +use function sprintf; +use function str_replace; +use function strlen; +use function strpos; +use function strspn; +use function strtolower; +use function substr; +use const FILEINFO_MIME; +use const FILTER_FLAG_IPV4; +use const FILTER_FLAG_IPV6; +use const FILTER_NULL_ON_FAILURE; +use const FILTER_VALIDATE_BOOLEAN; +use const FILTER_VALIDATE_IP; + +final class Uri implements UriInterface +{ + /** + * RFC3986 invalid characters. + * + * @link https://tools.ietf.org/html/rfc3986#section-2.2 + * + * @var string + */ + private const REGEXP_INVALID_CHARS = '/[\x00-\x1f\x7f]/'; + + /** + * RFC3986 Sub delimiter characters regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc3986#section-2.2 + * + * @var string + */ + private const REGEXP_CHARS_SUBDELIM = "\!\$&'\(\)\*\+,;\=%"; + + /** + * RFC3986 unreserved characters regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc3986#section-2.3 + * + * @var string + */ + private const REGEXP_CHARS_UNRESERVED = 'A-Za-z0-9_\-\.~'; + + /** + * RFC3986 schema regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.1 + */ + private const REGEXP_SCHEME = ',^[a-z]([-a-z0-9+.]+)?$,i'; + + /** + * RFC3986 host identified by a registered name regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + private const REGEXP_HOST_REGNAME = '/^( + (?[a-z0-9_~\-\.])| + (?[!$&\'()*+,;=])| + (?%[A-F0-9]{2}) + )+$/x'; + + /** + * RFC3986 delimiters of the generic URI components regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc3986#section-2.2 + */ + private const REGEXP_HOST_GEN_DELIMS = '/[:\/?#\[\]@ ]/'; // Also includes space. + + /** + * RFC3986 IPvFuture regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + private const REGEXP_HOST_IPFUTURE = '/^ + v(?[A-F0-9])+\. + (?: + (?[a-z0-9_~\-\.])| + (?[!$&\'()*+,;=:]) # also include the : character + )+ + $/ix'; + + /** + * RFC3986 IPvFuture host and port component. + */ + private const REGEXP_HOST_PORT = ',^(?(\[.*]|[^:])*)(:(?[^/?#]*))?$,x'; + + /** + * Significant 10 bits of IP to detect Zone ID regular expression pattern. + */ + private const HOST_ADDRESS_BLOCK = "\xfe\x80"; + + /** + * Regular expression pattern to for file URI. + * contains the volume but not the volume separator. + * The volume separator may be URL-encoded (`|` as `%7C`) by ::formatPath(), + * so we account for that here. + */ + private const REGEXP_FILE_PATH = ',^(?/)?(?[a-zA-Z])(?:[:|\|]|%7C)(?.*)?,'; + + /** + * Mimetype regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc2397 + */ + private const REGEXP_MIMETYPE = ',^\w+/[-.\w]+(?:\+[-.\w]+)?$,'; + + /** + * Base64 content regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc2397 + */ + private const REGEXP_BINARY = ',(;|^)base64$,'; + + /** + * Windows file path string regular expression pattern. + * contains both the volume and volume separator. + */ + private const REGEXP_WINDOW_PATH = ',^(?[a-zA-Z][:|\|]),'; + + + /** + * Supported schemes and corresponding default port. + * + * @var array + */ + private const SCHEME_DEFAULT_PORT = [ + 'data' => null, + 'file' => null, + 'ftp' => 21, + 'gopher' => 70, + 'http' => 80, + 'https' => 443, + 'ws' => 80, + 'wss' => 443, + ]; + + /** + * URI validation methods per scheme. + * + * @var array + */ + private const SCHEME_VALIDATION_METHOD = [ + 'data' => 'isUriWithSchemeAndPathOnly', + 'file' => 'isUriWithSchemeHostAndPathOnly', + 'ftp' => 'isNonEmptyHostUriWithoutFragmentAndQuery', + 'gopher' => 'isNonEmptyHostUriWithoutFragmentAndQuery', + 'http' => 'isNonEmptyHostUri', + 'https' => 'isNonEmptyHostUri', + 'ws' => 'isNonEmptyHostUriWithoutFragment', + 'wss' => 'isNonEmptyHostUriWithoutFragment', + ]; + + /** + * All ASCII letters sorted by typical frequency of occurrence. + * + * @var string + */ + private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; + + /** + * URI scheme component. + * + * @var string|null + */ + private $scheme; + + /** + * URI user info part. + * + * @var string|null + */ + private $user_info; + + /** + * URI host component. + * + * @var string|null + */ + private $host; + + /** + * URI port component. + * + * @var int|null + */ + private $port; + + /** + * URI authority string representation. + * + * @var string|null + */ + private $authority; + + /** + * URI path component. + * + * @var string + */ + private $path = ''; + + /** + * URI query component. + * + * @var string|null + */ + private $query; + + /** + * URI fragment component. + * + * @var string|null + */ + private $fragment; + + /** + * URI string representation. + * + * @var string|null + */ + private $uri; + + /** + * Create a new instance. + * + * @param ?string $scheme + * @param ?string $user + * @param ?string $pass + * @param ?string $host + * @param ?int $port + * @param ?string $query + * @param ?string $fragment + */ + private function __construct( + ?string $scheme, + ?string $user, + ?string $pass, + ?string $host, + ?int $port, + string $path, + ?string $query, + ?string $fragment + ) { + $this->scheme = $this->formatScheme($scheme); + $this->user_info = $this->formatUserInfo($user, $pass); + $this->host = $this->formatHost($host); + $this->port = $this->formatPort($port); + $this->authority = $this->setAuthority(); + $this->path = $this->formatPath($path); + $this->query = $this->formatQueryAndFragment($query); + $this->fragment = $this->formatQueryAndFragment($fragment); + $this->assertValidState(); + } + + /** + * Format the Scheme and Host component. + * + * @param ?string $scheme + * + * @throws SyntaxError if the scheme is invalid + */ + private function formatScheme(?string $scheme): ?string + { + if (null === $scheme) { + return $scheme; + } + + $formatted_scheme = strtolower($scheme); + if (1 === preg_match(self::REGEXP_SCHEME, $formatted_scheme)) { + return $formatted_scheme; + } + + throw new SyntaxError(sprintf('The scheme `%s` is invalid.', $scheme)); + } + + /** + * Set the UserInfo component. + * + * @param ?string $user + * @param ?string $password + */ + private function formatUserInfo(?string $user, ?string $password): ?string + { + if (null === $user) { + return $user; + } + + static $user_pattern = '/(?:[^%'.self::REGEXP_CHARS_UNRESERVED.self::REGEXP_CHARS_SUBDELIM.']++|%(?![A-Fa-f0-9]{2}))/'; + $user = preg_replace_callback($user_pattern, [Uri::class, 'urlEncodeMatch'], $user); + if (null === $password) { + return $user; + } + + static $password_pattern = '/(?:[^%:'.self::REGEXP_CHARS_UNRESERVED.self::REGEXP_CHARS_SUBDELIM.']++|%(?![A-Fa-f0-9]{2}))/'; + + return $user.':'.preg_replace_callback($password_pattern, [Uri::class, 'urlEncodeMatch'], $password); + } + + /** + * Returns the RFC3986 encoded string matched. + */ + private static function urlEncodeMatch(array $matches): string + { + return rawurlencode($matches[0]); + } + + /** + * Validate and Format the Host component. + * + * @param ?string $host + */ + private function formatHost(?string $host): ?string + { + if (null === $host || '' === $host) { + return $host; + } + + if ('[' !== $host[0]) { + return $this->formatRegisteredName($host); + } + + return $this->formatIp($host); + } + + /** + * Validate and format a registered name. + * + * The host is converted to its ascii representation if needed + * + * @throws IdnSupportMissing if the submitted host required missing or misconfigured IDN support + * @throws SyntaxError if the submitted host is not a valid registered name + */ + private function formatRegisteredName(string $host): string + { + $formatted_host = rawurldecode($host); + if (1 === preg_match(self::REGEXP_HOST_REGNAME, $formatted_host)) { + return $formatted_host; + } + + if (1 === preg_match(self::REGEXP_HOST_GEN_DELIMS, $formatted_host)) { + throw new SyntaxError(sprintf('The host `%s` is invalid : a registered name can not contain URI delimiters or spaces', $host)); + } + + $info = Idna::toAscii($host, Idna::IDNA2008_ASCII); + if (0 !== $info->errors()) { + throw IdnaConversionFailed::dueToIDNAError($host, $info); + } + + return $info->result(); + } + + /** + * Validate and Format the IPv6/IPvfuture host. + * + * @throws SyntaxError if the submitted host is not a valid IP host + */ + private function formatIp(string $host): string + { + $ip = substr($host, 1, -1); + if (false !== filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + return $host; + } + + if (1 === preg_match(self::REGEXP_HOST_IPFUTURE, $ip, $matches) && !in_array($matches['version'], ['4', '6'], true)) { + return $host; + } + + $pos = strpos($ip, '%'); + if (false === $pos) { + throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host)); + } + + if (1 === preg_match(self::REGEXP_HOST_GEN_DELIMS, rawurldecode(substr($ip, $pos)))) { + throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host)); + } + + $ip = substr($ip, 0, $pos); + if (false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host)); + } + + //Only the address block fe80::/10 can have a Zone ID attach to + //let's detect the link local significant 10 bits + if (0 === strpos((string) inet_pton($ip), self::HOST_ADDRESS_BLOCK)) { + return $host; + } + + throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host)); + } + + /** + * Format the Port component. + * + * @param null|mixed $port + * + * @throws SyntaxError + */ + private function formatPort($port = null): ?int + { + if (null === $port || '' === $port) { + return null; + } + + if (!is_int($port) && !(is_string($port) && 1 === preg_match('/^\d*$/', $port))) { + throw new SyntaxError(sprintf('The port `%s` is invalid', $port)); + } + + $port = (int) $port; + if (0 > $port) { + throw new SyntaxError(sprintf('The port `%s` is invalid', $port)); + } + + $defaultPort = self::SCHEME_DEFAULT_PORT[$this->scheme] ?? null; + if ($defaultPort === $port) { + return null; + } + + return $port; + } + + /** + * {@inheritDoc} + */ + public static function __set_state(array $components): self + { + $components['user'] = null; + $components['pass'] = null; + if (null !== $components['user_info']) { + [$components['user'], $components['pass']] = explode(':', $components['user_info'], 2) + [1 => null]; + } + + return new self( + $components['scheme'], + $components['user'], + $components['pass'], + $components['host'], + $components['port'], + $components['path'], + $components['query'], + $components['fragment'] + ); + } + + /** + * Create a new instance from a URI and a Base URI. + * + * The returned URI must be absolute. + * + * @param mixed $uri the input URI to create + * @param null|mixed $base_uri the base URI used for reference + */ + public static function createFromBaseUri($uri, $base_uri = null): UriInterface + { + if (!$uri instanceof UriInterface) { + $uri = self::createFromString($uri); + } + + if (null === $base_uri) { + if (null === $uri->getScheme()) { + throw new SyntaxError(sprintf('the URI `%s` must be absolute', (string) $uri)); + } + + if (null === $uri->getAuthority()) { + return $uri; + } + + /** @var UriInterface $uri */ + $uri = UriResolver::resolve($uri, $uri->withFragment(null)->withQuery(null)->withPath('')); + + return $uri; + } + + if (!$base_uri instanceof UriInterface) { + $base_uri = self::createFromString($base_uri); + } + + if (null === $base_uri->getScheme()) { + throw new SyntaxError(sprintf('the base URI `%s` must be absolute', (string) $base_uri)); + } + + /** @var UriInterface $uri */ + $uri = UriResolver::resolve($uri, $base_uri); + + return $uri; + } + + /** + * Create a new instance from a string. + * + * @param string|mixed $uri + */ + public static function createFromString($uri = ''): self + { + $components = UriString::parse($uri); + + return new self( + $components['scheme'], + $components['user'], + $components['pass'], + $components['host'], + $components['port'], + $components['path'], + $components['query'], + $components['fragment'] + ); + } + + /** + * Create a new instance from a hash of parse_url parts. + * + * Create an new instance from a hash representation of the URI similar + * to PHP parse_url function result + * + * @param array $components + */ + public static function createFromComponents(array $components = []): self + { + $components += [ + 'scheme' => null, 'user' => null, 'pass' => null, 'host' => null, + 'port' => null, 'path' => '', 'query' => null, 'fragment' => null, + ]; + + return new self( + $components['scheme'], + $components['user'], + $components['pass'], + $components['host'], + $components['port'], + $components['path'], + $components['query'], + $components['fragment'] + ); + } + + /** + * Create a new instance from a data file path. + * + * @param resource|null $context + * + * @throws FileinfoSupportMissing If ext/fileinfo is not installed + * @throws SyntaxError If the file does not exist or is not readable + */ + public static function createFromDataPath(string $path, $context = null): self + { + static $finfo_support = null; + $finfo_support = $finfo_support ?? class_exists(\finfo::class); + + // @codeCoverageIgnoreStart + if (!$finfo_support) { + throw new FileinfoSupportMissing(sprintf('Please install ext/fileinfo to use the %s() method.', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $file_args = [$path, false]; + $mime_args = [$path, FILEINFO_MIME]; + if (null !== $context) { + $file_args[] = $context; + $mime_args[] = $context; + } + + $raw = @file_get_contents(...$file_args); + if (false === $raw) { + throw new SyntaxError(sprintf('The file `%s` does not exist or is not readable', $path)); + } + + $mimetype = (string) (new \finfo(FILEINFO_MIME))->file(...$mime_args); + + return Uri::createFromComponents([ + 'scheme' => 'data', + 'path' => str_replace(' ', '', $mimetype.';base64,'.base64_encode($raw)), + ]); + } + + /** + * Create a new instance from a Unix path string. + */ + public static function createFromUnixPath(string $uri = ''): self + { + $uri = implode('/', array_map('rawurlencode', explode('/', $uri))); + if ('/' !== ($uri[0] ?? '')) { + return Uri::createFromComponents(['path' => $uri]); + } + + return Uri::createFromComponents(['path' => $uri, 'scheme' => 'file', 'host' => '']); + } + + /** + * Create a new instance from a local Windows path string. + */ + public static function createFromWindowsPath(string $uri = ''): self + { + $root = ''; + if (1 === preg_match(self::REGEXP_WINDOW_PATH, $uri, $matches)) { + $root = substr($matches['root'], 0, -1).':'; + $uri = substr($uri, strlen($root)); + } + $uri = str_replace('\\', '/', $uri); + $uri = implode('/', array_map('rawurlencode', explode('/', $uri))); + + //Local Windows absolute path + if ('' !== $root) { + return Uri::createFromComponents(['path' => '/'.$root.$uri, 'scheme' => 'file', 'host' => '']); + } + + //UNC Windows Path + if ('//' !== substr($uri, 0, 2)) { + return Uri::createFromComponents(['path' => $uri]); + } + + $parts = explode('/', substr($uri, 2), 2) + [1 => null]; + + return Uri::createFromComponents(['host' => $parts[0], 'path' => '/'.$parts[1], 'scheme' => 'file']); + } + + /** + * Create a new instance from a URI object. + * + * @param Psr7UriInterface|UriInterface $uri the input URI to create + */ + public static function createFromUri($uri): self + { + if ($uri instanceof UriInterface) { + $user_info = $uri->getUserInfo(); + $user = null; + $pass = null; + if (null !== $user_info) { + [$user, $pass] = explode(':', $user_info, 2) + [1 => null]; + } + + return new self( + $uri->getScheme(), + $user, + $pass, + $uri->getHost(), + $uri->getPort(), + $uri->getPath(), + $uri->getQuery(), + $uri->getFragment() + ); + } + + if (!$uri instanceof Psr7UriInterface) { + throw new \TypeError(sprintf('The object must implement the `%s` or the `%s`', Psr7UriInterface::class, UriInterface::class)); + } + + $scheme = $uri->getScheme(); + if ('' === $scheme) { + $scheme = null; + } + + $fragment = $uri->getFragment(); + if ('' === $fragment) { + $fragment = null; + } + + $query = $uri->getQuery(); + if ('' === $query) { + $query = null; + } + + $host = $uri->getHost(); + if ('' === $host) { + $host = null; + } + + $user_info = $uri->getUserInfo(); + $user = null; + $pass = null; + if ('' !== $user_info) { + [$user, $pass] = explode(':', $user_info, 2) + [1 => null]; + } + + return new self( + $scheme, + $user, + $pass, + $host, + $uri->getPort(), + $uri->getPath(), + $query, + $fragment + ); + } + + /** + * Create a new instance from the environment. + */ + public static function createFromServer(array $server): self + { + [$user, $pass] = self::fetchUserInfo($server); + [$host, $port] = self::fetchHostname($server); + [$path, $query] = self::fetchRequestUri($server); + + return Uri::createFromComponents([ + 'scheme' => self::fetchScheme($server), + 'user' => $user, + 'pass' => $pass, + 'host' => $host, + 'port' => $port, + 'path' => $path, + 'query' => $query, + ]); + } + + /** + * Returns the environment scheme. + */ + private static function fetchScheme(array $server): string + { + $server += ['HTTPS' => '']; + $res = filter_var($server['HTTPS'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + + return false !== $res ? 'https' : 'http'; + } + + /** + * Returns the environment user info. + * + * @return array{0:?string, 1:?string} + */ + private static function fetchUserInfo(array $server): array + { + $server += ['PHP_AUTH_USER' => null, 'PHP_AUTH_PW' => null, 'HTTP_AUTHORIZATION' => '']; + $user = $server['PHP_AUTH_USER']; + $pass = $server['PHP_AUTH_PW']; + if (0 === strpos(strtolower($server['HTTP_AUTHORIZATION']), 'basic')) { + $userinfo = base64_decode(substr($server['HTTP_AUTHORIZATION'], 6), true); + if (false === $userinfo) { + throw new SyntaxError('The user info could not be detected'); + } + [$user, $pass] = explode(':', $userinfo, 2) + [1 => null]; + } + + if (null !== $user) { + $user = rawurlencode($user); + } + + if (null !== $pass) { + $pass = rawurlencode($pass); + } + + return [$user, $pass]; + } + + /** + * Returns the environment host. + * + * @throws SyntaxError If the host can not be detected + * + * @return array{0:?string, 1:?string} + */ + private static function fetchHostname(array $server): array + { + $server += ['SERVER_PORT' => null]; + if (null !== $server['SERVER_PORT']) { + $server['SERVER_PORT'] = (int) $server['SERVER_PORT']; + } + + if (isset($server['HTTP_HOST']) && 1 === preg_match(self::REGEXP_HOST_PORT, $server['HTTP_HOST'], $matches)) { + return [ + $matches['host'], + isset($matches['port']) ? (int) $matches['port'] : $server['SERVER_PORT'], + ]; + } + + if (!isset($server['SERVER_ADDR'])) { + throw new SyntaxError('The host could not be detected'); + } + + if (false === filter_var($server['SERVER_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + $server['SERVER_ADDR'] = '['.$server['SERVER_ADDR'].']'; + } + + return [$server['SERVER_ADDR'], $server['SERVER_PORT']]; + } + + /** + * Returns the environment path. + * + * @return array{0:?string, 1:?string} + */ + private static function fetchRequestUri(array $server): array + { + $server += ['IIS_WasUrlRewritten' => null, 'UNENCODED_URL' => '', 'PHP_SELF' => '', 'QUERY_STRING' => null]; + if ('1' === $server['IIS_WasUrlRewritten'] && '' !== $server['UNENCODED_URL']) { + /** @var array{0:?string, 1:?string} $retval */ + $retval = explode('?', $server['UNENCODED_URL'], 2) + [1 => null]; + + return $retval; + } + + if (isset($server['REQUEST_URI'])) { + [$path, ] = explode('?', $server['REQUEST_URI'], 2); + $query = ('' !== $server['QUERY_STRING']) ? $server['QUERY_STRING'] : null; + + return [$path, $query]; + } + + return [$server['PHP_SELF'], $server['QUERY_STRING']]; + } + + /** + * Generate the URI authority part. + */ + private function setAuthority(): ?string + { + $authority = null; + if (null !== $this->user_info) { + $authority = $this->user_info.'@'; + } + + if (null !== $this->host) { + $authority .= $this->host; + } + + if (null !== $this->port) { + $authority .= ':'.$this->port; + } + + return $authority; + } + + /** + * Format the Path component. + */ + private function formatPath(string $path): string + { + $path = $this->formatDataPath($path); + + static $pattern = '/(?:[^'.self::REGEXP_CHARS_UNRESERVED.self::REGEXP_CHARS_SUBDELIM.'%:@\/}{]++|%(?![A-Fa-f0-9]{2}))/'; + + $path = (string) preg_replace_callback($pattern, [Uri::class, 'urlEncodeMatch'], $path); + + return $this->formatFilePath($path); + } + + /** + * Filter the Path component. + * + * @link https://tools.ietf.org/html/rfc2397 + * + * @throws SyntaxError If the path is not compliant with RFC2397 + */ + private function formatDataPath(string $path): string + { + if ('data' !== $this->scheme) { + return $path; + } + + if ('' == $path) { + return 'text/plain;charset=us-ascii,'; + } + + if (strlen($path) !== strspn($path, self::ASCII) || false === strpos($path, ',')) { + throw new SyntaxError(sprintf('The path `%s` is invalid according to RFC2937', $path)); + } + + $parts = explode(',', $path, 2) + [1 => null]; + $mediatype = explode(';', (string) $parts[0], 2) + [1 => null]; + $data = (string) $parts[1]; + $mimetype = $mediatype[0]; + if (null === $mimetype || '' === $mimetype) { + $mimetype = 'text/plain'; + } + + $parameters = $mediatype[1]; + if (null === $parameters || '' === $parameters) { + $parameters = 'charset=us-ascii'; + } + + $this->assertValidPath($mimetype, $parameters, $data); + + return $mimetype.';'.$parameters.','.$data; + } + + /** + * Assert the path is a compliant with RFC2397. + * + * @link https://tools.ietf.org/html/rfc2397 + * + * @throws SyntaxError If the mediatype or the data are not compliant with the RFC2397 + */ + private function assertValidPath(string $mimetype, string $parameters, string $data): void + { + if (1 !== preg_match(self::REGEXP_MIMETYPE, $mimetype)) { + throw new SyntaxError(sprintf('The path mimetype `%s` is invalid', $mimetype)); + } + + $is_binary = 1 === preg_match(self::REGEXP_BINARY, $parameters, $matches); + if ($is_binary) { + $parameters = substr($parameters, 0, - strlen($matches[0])); + } + + $res = array_filter(array_filter(explode(';', $parameters), [$this, 'validateParameter'])); + if ([] !== $res) { + throw new SyntaxError(sprintf('The path paremeters `%s` is invalid', $parameters)); + } + + if (!$is_binary) { + return; + } + + $res = base64_decode($data, true); + if (false === $res || $data !== base64_encode($res)) { + throw new SyntaxError(sprintf('The path data `%s` is invalid', $data)); + } + } + + /** + * Validate mediatype parameter. + */ + private function validateParameter(string $parameter): bool + { + $properties = explode('=', $parameter); + + return 2 != count($properties) || 'base64' === strtolower($properties[0]); + } + + /** + * Format path component for file scheme. + */ + private function formatFilePath(string $path): string + { + if ('file' !== $this->scheme) { + return $path; + } + + $replace = static function (array $matches): string { + return $matches['delim'].$matches['volume'].':'.$matches['rest']; + }; + + return (string) preg_replace_callback(self::REGEXP_FILE_PATH, $replace, $path); + } + + /** + * Format the Query or the Fragment component. + * + * Returns a array containing: + *
    + *
  • the formatted component (a string or null)
  • + *
  • a boolean flag telling wether the delimiter is to be added to the component + * when building the URI string representation
  • + *
+ * + * @param ?string $component + */ + private function formatQueryAndFragment(?string $component): ?string + { + if (null === $component || '' === $component) { + return $component; + } + + static $pattern = '/(?:[^'.self::REGEXP_CHARS_UNRESERVED.self::REGEXP_CHARS_SUBDELIM.'%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/'; + return preg_replace_callback($pattern, [Uri::class, 'urlEncodeMatch'], $component); + } + + /** + * assert the URI internal state is valid. + * + * @link https://tools.ietf.org/html/rfc3986#section-3 + * @link https://tools.ietf.org/html/rfc3986#section-3.3 + * + * @throws SyntaxError if the URI is in an invalid state according to RFC3986 + * @throws SyntaxError if the URI is in an invalid state according to scheme specific rules + */ + private function assertValidState(): void + { + if (null !== $this->authority && ('' !== $this->path && '/' !== $this->path[0])) { + throw new SyntaxError('If an authority is present the path must be empty or start with a `/`.'); + } + + if (null === $this->authority && 0 === strpos($this->path, '//')) { + throw new SyntaxError(sprintf('If there is no authority the path `%s` can not start with a `//`.', $this->path)); + } + + $pos = strpos($this->path, ':'); + if (null === $this->authority + && null === $this->scheme + && false !== $pos + && false === strpos(substr($this->path, 0, $pos), '/') + ) { + throw new SyntaxError('In absence of a scheme and an authority the first path segment cannot contain a colon (":") character.'); + } + + $validationMethod = self::SCHEME_VALIDATION_METHOD[$this->scheme] ?? null; + if (null === $validationMethod || true === $this->$validationMethod()) { + $this->uri = null; + + return; + } + + throw new SyntaxError(sprintf('The uri `%s` is invalid for the `%s` scheme.', (string) $this, $this->scheme)); + } + + /** + * URI validation for URI schemes which allows only scheme and path components. + */ + private function isUriWithSchemeAndPathOnly(): bool + { + return null === $this->authority + && null === $this->query + && null === $this->fragment; + } + + /** + * URI validation for URI schemes which allows only scheme, host and path components. + */ + private function isUriWithSchemeHostAndPathOnly(): bool + { + return null === $this->user_info + && null === $this->port + && null === $this->query + && null === $this->fragment + && !('' != $this->scheme && null === $this->host); + } + + /** + * URI validation for URI schemes which disallow the empty '' host. + */ + private function isNonEmptyHostUri(): bool + { + return '' !== $this->host + && !(null !== $this->scheme && null === $this->host); + } + + /** + * URI validation for URIs schemes which disallow the empty '' host + * and forbids the fragment component. + */ + private function isNonEmptyHostUriWithoutFragment(): bool + { + return $this->isNonEmptyHostUri() && null === $this->fragment; + } + + /** + * URI validation for URIs schemes which disallow the empty '' host + * and forbids fragment and query components. + */ + private function isNonEmptyHostUriWithoutFragmentAndQuery(): bool + { + return $this->isNonEmptyHostUri() && null === $this->fragment && null === $this->query; + } + + /** + * Generate the URI string representation from its components. + * + * @link https://tools.ietf.org/html/rfc3986#section-5.3 + * + * @param ?string $scheme + * @param ?string $authority + * @param ?string $query + * @param ?string $fragment + */ + private function getUriString( + ?string $scheme, + ?string $authority, + string $path, + ?string $query, + ?string $fragment + ): string { + if (null !== $scheme) { + $scheme = $scheme.':'; + } + + if (null !== $authority) { + $authority = '//'.$authority; + } + + if (null !== $query) { + $query = '?'.$query; + } + + if (null !== $fragment) { + $fragment = '#'.$fragment; + } + + return $scheme.$authority.$path.$query.$fragment; + } + + public function toString(): string + { + $this->uri = $this->uri ?? $this->getUriString( + $this->scheme, + $this->authority, + $this->path, + $this->query, + $this->fragment + ); + + return $this->uri; + } + + /** + * {@inheritDoc} + */ + public function __toString(): string + { + return $this->toString(); + } + + /** + * {@inheritDoc} + */ + public function jsonSerialize(): string + { + return $this->toString(); + } + + /** + * {@inheritDoc} + * + * @return array{scheme:?string, user_info:?string, host:?string, port:?int, path:string, query:?string, fragment:?string} + */ + public function __debugInfo(): array + { + return [ + 'scheme' => $this->scheme, + 'user_info' => isset($this->user_info) ? preg_replace(',:(.*).?$,', ':***', $this->user_info) : null, + 'host' => $this->host, + 'port' => $this->port, + 'path' => $this->path, + 'query' => $this->query, + 'fragment' => $this->fragment, + ]; + } + + /** + * {@inheritDoc} + */ + public function getScheme(): ?string + { + return $this->scheme; + } + + /** + * {@inheritDoc} + */ + public function getAuthority(): ?string + { + return $this->authority; + } + + /** + * {@inheritDoc} + */ + public function getUserInfo(): ?string + { + return $this->user_info; + } + + /** + * {@inheritDoc} + */ + public function getHost(): ?string + { + return $this->host; + } + + /** + * {@inheritDoc} + */ + public function getPort(): ?int + { + return $this->port; + } + + /** + * {@inheritDoc} + */ + public function getPath(): string + { + return $this->path; + } + + /** + * {@inheritDoc} + */ + public function getQuery(): ?string + { + return $this->query; + } + + /** + * {@inheritDoc} + */ + public function getFragment(): ?string + { + return $this->fragment; + } + + /** + * {@inheritDoc} + */ + public function withScheme($scheme): UriInterface + { + $scheme = $this->formatScheme($this->filterString($scheme)); + if ($scheme === $this->scheme) { + return $this; + } + + $clone = clone $this; + $clone->scheme = $scheme; + $clone->port = $clone->formatPort($clone->port); + $clone->authority = $clone->setAuthority(); + $clone->assertValidState(); + + return $clone; + } + + /** + * Filter a string. + * + * @param mixed $str the value to evaluate as a string + * + * @throws SyntaxError if the submitted data can not be converted to string + */ + private function filterString($str): ?string + { + if (null === $str) { + return $str; + } + + if (is_object($str) && method_exists($str, '__toString')) { + $str = (string) $str; + } + + if (!is_scalar($str)) { + throw new \TypeError(sprintf('The component must be a string, a scalar or a stringable object %s given.', gettype($str))); + } + + $str = (string) $str; + if (1 !== preg_match(self::REGEXP_INVALID_CHARS, $str)) { + return $str; + } + + throw new SyntaxError(sprintf('The component `%s` contains invalid characters.', $str)); + } + + /** + * {@inheritDoc} + */ + public function withUserInfo($user, $password = null): UriInterface + { + $user_info = null; + $user = $this->filterString($user); + if (null !== $password) { + $password = $this->filterString($password); + } + + if ('' !== $user) { + $user_info = $this->formatUserInfo($user, $password); + } + + if ($user_info === $this->user_info) { + return $this; + } + + $clone = clone $this; + $clone->user_info = $user_info; + $clone->authority = $clone->setAuthority(); + $clone->assertValidState(); + + return $clone; + } + + /** + * {@inheritDoc} + */ + public function withHost($host): UriInterface + { + $host = $this->formatHost($this->filterString($host)); + if ($host === $this->host) { + return $this; + } + + $clone = clone $this; + $clone->host = $host; + $clone->authority = $clone->setAuthority(); + $clone->assertValidState(); + + return $clone; + } + + /** + * {@inheritDoc} + */ + public function withPort($port): UriInterface + { + $port = $this->formatPort($port); + if ($port === $this->port) { + return $this; + } + + $clone = clone $this; + $clone->port = $port; + $clone->authority = $clone->setAuthority(); + $clone->assertValidState(); + + return $clone; + } + + /** + * {@inheritDoc} + */ + public function withPath($path): UriInterface + { + $path = $this->filterString($path); + if (null === $path) { + throw new \TypeError('A path must be a string NULL given.'); + } + + $path = $this->formatPath($path); + if ($path === $this->path) { + return $this; + } + + $clone = clone $this; + $clone->path = $path; + $clone->assertValidState(); + + return $clone; + } + + /** + * {@inheritDoc} + */ + public function withQuery($query): UriInterface + { + $query = $this->formatQueryAndFragment($this->filterString($query)); + if ($query === $this->query) { + return $this; + } + + $clone = clone $this; + $clone->query = $query; + $clone->assertValidState(); + + return $clone; + } + + /** + * {@inheritDoc} + */ + public function withFragment($fragment): UriInterface + { + $fragment = $this->formatQueryAndFragment($this->filterString($fragment)); + if ($fragment === $this->fragment) { + return $this; + } + + $clone = clone $this; + $clone->fragment = $fragment; + $clone->assertValidState(); + + return $clone; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriInfo.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriInfo.php new file mode 100644 index 00000000..5dd96e1a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriInfo.php @@ -0,0 +1,205 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri; + +use League\Uri\Contracts\UriInterface; +use Psr\Http\Message\UriInterface as Psr7UriInterface; +use function explode; +use function implode; +use function preg_replace_callback; +use function rawurldecode; +use function sprintf; + +final class UriInfo +{ + private const REGEXP_ENCODED_CHARS = ',%(2[D|E]|3[0-9]|4[1-9|A-F]|5[0-9|A|F]|6[1-9|A-F]|7[0-9|E]),i'; + + private const WHATWG_SPECIAL_SCHEMES = ['ftp', 'http', 'https', 'ws', 'wss']; + + /** + * @codeCoverageIgnore + */ + private function __construct() + { + } + + /** + * @param Psr7UriInterface|UriInterface $uri + */ + private static function emptyComponentValue($uri): ?string + { + return $uri instanceof Psr7UriInterface ? '' : null; + } + + /** + * Filter the URI object. + * + * To be valid an URI MUST implement at least one of the following interface: + * - League\Uri\UriInterface + * - Psr\Http\Message\UriInterface + * + * @param mixed $uri the URI to validate + * + * @throws \TypeError if the URI object does not implements the supported interfaces. + * + * @return Psr7UriInterface|UriInterface + */ + private static function filterUri($uri) + { + if ($uri instanceof Psr7UriInterface || $uri instanceof UriInterface) { + return $uri; + } + + throw new \TypeError(sprintf('The uri must be a valid URI object received `%s`', is_object($uri) ? get_class($uri) : gettype($uri))); + } + + /** + * Normalize an URI for comparison. + * + * @param Psr7UriInterface|UriInterface $uri + * + * @return Psr7UriInterface|UriInterface + */ + private static function normalize($uri) + { + $uri = self::filterUri($uri); + $null = self::emptyComponentValue($uri); + + $path = $uri->getPath(); + if ('/' === ($path[0] ?? '') || '' !== $uri->getScheme().$uri->getAuthority()) { + $path = UriResolver::resolve($uri, $uri->withPath('')->withQuery($null))->getPath(); + } + + $query = $uri->getQuery(); + $fragment = $uri->getFragment(); + $fragmentOrig = $fragment; + $pairs = null === $query ? [] : explode('&', $query); + sort($pairs, SORT_REGULAR); + + $replace = static function (array $matches): string { + return rawurldecode($matches[0]); + }; + + $retval = preg_replace_callback(self::REGEXP_ENCODED_CHARS, $replace, [$path, implode('&', $pairs), $fragment]); + if (null !== $retval) { + [$path, $query, $fragment] = $retval + ['', $null, $null]; + } + + if ($null !== $uri->getAuthority() && '' === $path) { + $path = '/'; + } + + return $uri + ->withHost(Uri::createFromComponents(['host' => $uri->getHost()])->getHost()) + ->withPath($path) + ->withQuery([] === $pairs ? $null : $query) + ->withFragment($null === $fragmentOrig ? $fragmentOrig : $fragment); + } + + /** + * Tell whether the URI represents an absolute URI. + * + * @param Psr7UriInterface|UriInterface $uri + */ + public static function isAbsolute($uri): bool + { + return self::emptyComponentValue($uri) !== self::filterUri($uri)->getScheme(); + } + + /** + * Tell whether the URI represents a network path. + * + * @param Psr7UriInterface|UriInterface $uri + */ + public static function isNetworkPath($uri): bool + { + $uri = self::filterUri($uri); + $null = self::emptyComponentValue($uri); + + return $null === $uri->getScheme() && $null !== $uri->getAuthority(); + } + + /** + * Tell whether the URI represents an absolute path. + * + * @param Psr7UriInterface|UriInterface $uri + */ + public static function isAbsolutePath($uri): bool + { + $uri = self::filterUri($uri); + $null = self::emptyComponentValue($uri); + + return $null === $uri->getScheme() + && $null === $uri->getAuthority() + && '/' === ($uri->getPath()[0] ?? ''); + } + + /** + * Tell whether the URI represents a relative path. + * + * @param Psr7UriInterface|UriInterface $uri + */ + public static function isRelativePath($uri): bool + { + $uri = self::filterUri($uri); + $null = self::emptyComponentValue($uri); + + return $null === $uri->getScheme() + && $null === $uri->getAuthority() + && '/' !== ($uri->getPath()[0] ?? ''); + } + + /** + * Tell whether both URI refers to the same document. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + */ + public static function isSameDocument($uri, $base_uri): bool + { + $uri = self::normalize($uri); + $base_uri = self::normalize($base_uri); + + return (string) $uri->withFragment($uri instanceof Psr7UriInterface ? '' : null) + === (string) $base_uri->withFragment($base_uri instanceof Psr7UriInterface ? '' : null); + } + + /** + * Returns the URI origin property as defined by WHATWG URL living standard. + * + * {@see https://url.spec.whatwg.org/#origin} + * + * For URI without a special scheme the method returns null + * For URI with the file scheme the method will return null (as this is left to the implementation decision) + * For URI with a special scheme the method returns the scheme followed by its authority (without the userinfo part) + * + * @param Psr7UriInterface|UriInterface $uri + */ + public static function getOrigin($uri): ?string + { + $scheme = self::filterUri($uri)->getScheme(); + if ('blob' === $scheme) { + $uri = Uri::createFromString($uri->getPath()); + $scheme = $uri->getScheme(); + } + + if (in_array($scheme, self::WHATWG_SPECIAL_SCHEMES, true)) { + $null = self::emptyComponentValue($uri); + + return (string) $uri->withFragment($null)->withQuery($null)->withPath('')->withUserInfo($null, null); + } + + return null; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriResolver.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriResolver.php new file mode 100644 index 00000000..7c34dbef --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriResolver.php @@ -0,0 +1,375 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri; + +use League\Uri\Contracts\UriInterface; +use Psr\Http\Message\UriInterface as Psr7UriInterface; +use function array_pop; +use function array_reduce; +use function count; +use function end; +use function explode; +use function gettype; +use function implode; +use function in_array; +use function sprintf; +use function str_repeat; +use function strpos; +use function substr; + +final class UriResolver +{ + /** + * @var array + */ + const DOT_SEGMENTS = ['.' => 1, '..' => 1]; + + /** + * @codeCoverageIgnore + */ + private function __construct() + { + } + + /** + * Resolve an URI against a base URI using RFC3986 rules. + * + * If the first argument is a UriInterface the method returns a UriInterface object + * If the first argument is a Psr7UriInterface the method returns a Psr7UriInterface object + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + * + * @return Psr7UriInterface|UriInterface + */ + public static function resolve($uri, $base_uri) + { + self::filterUri($uri); + self::filterUri($base_uri); + $null = $uri instanceof Psr7UriInterface ? '' : null; + + if ($null !== $uri->getScheme()) { + return $uri + ->withPath(self::removeDotSegments($uri->getPath())); + } + + if ($null !== $uri->getAuthority()) { + return $uri + ->withScheme($base_uri->getScheme()) + ->withPath(self::removeDotSegments($uri->getPath())); + } + + $user = $null; + $pass = null; + $userInfo = $base_uri->getUserInfo(); + if (null !== $userInfo) { + [$user, $pass] = explode(':', $userInfo, 2) + [1 => null]; + } + + [$uri_path, $uri_query] = self::resolvePathAndQuery($uri, $base_uri); + + return $uri + ->withPath(self::removeDotSegments($uri_path)) + ->withQuery($uri_query) + ->withHost($base_uri->getHost()) + ->withPort($base_uri->getPort()) + ->withUserInfo((string) $user, $pass) + ->withScheme($base_uri->getScheme()) + ; + } + + /** + * Filter the URI object. + * + * @param mixed $uri an URI object + * + * @throws \TypeError if the URI object does not implements the supported interfaces. + */ + private static function filterUri($uri): void + { + if (!$uri instanceof UriInterface && !$uri instanceof Psr7UriInterface) { + throw new \TypeError(sprintf('The uri must be a valid URI object received `%s`', gettype($uri))); + } + } + + /** + * Remove dot segments from the URI path. + */ + private static function removeDotSegments(string $path): string + { + if (false === strpos($path, '.')) { + return $path; + } + + $old_segments = explode('/', $path); + $new_path = implode('/', array_reduce($old_segments, [UriResolver::class, 'reducer'], [])); + if (isset(self::DOT_SEGMENTS[end($old_segments)])) { + $new_path .= '/'; + } + + // @codeCoverageIgnoreStart + // added because some PSR-7 implementations do not respect RFC3986 + if (0 === strpos($path, '/') && 0 !== strpos($new_path, '/')) { + return '/'.$new_path; + } + // @codeCoverageIgnoreEnd + + return $new_path; + } + + /** + * Remove dot segments. + * + * @return array + */ + private static function reducer(array $carry, string $segment): array + { + if ('..' === $segment) { + array_pop($carry); + + return $carry; + } + + if (!isset(self::DOT_SEGMENTS[$segment])) { + $carry[] = $segment; + } + + return $carry; + } + + /** + * Resolve an URI path and query component. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + * + * @return array{0:string, 1:string|null} + */ + private static function resolvePathAndQuery($uri, $base_uri): array + { + $target_path = $uri->getPath(); + $target_query = $uri->getQuery(); + $null = $uri instanceof Psr7UriInterface ? '' : null; + $baseNull = $base_uri instanceof Psr7UriInterface ? '' : null; + + if (0 === strpos($target_path, '/')) { + return [$target_path, $target_query]; + } + + if ('' === $target_path) { + if ($null === $target_query) { + $target_query = $base_uri->getQuery(); + } + + $target_path = $base_uri->getPath(); + //@codeCoverageIgnoreStart + //because some PSR-7 Uri implementations allow this RFC3986 forbidden construction + if ($baseNull !== $base_uri->getAuthority() && 0 !== strpos($target_path, '/')) { + $target_path = '/'.$target_path; + } + //@codeCoverageIgnoreEnd + + return [$target_path, $target_query]; + } + + $base_path = $base_uri->getPath(); + if ($baseNull !== $base_uri->getAuthority() && '' === $base_path) { + $target_path = '/'.$target_path; + } + + if ('' !== $base_path) { + $segments = explode('/', $base_path); + array_pop($segments); + if ([] !== $segments) { + $target_path = implode('/', $segments).'/'.$target_path; + } + } + + return [$target_path, $target_query]; + } + + /** + * Relativize an URI according to a base URI. + * + * This method MUST retain the state of the submitted URI instance, and return + * an URI instance of the same type that contains the applied modifications. + * + * This method MUST be transparent when dealing with error and exceptions. + * It MUST not alter of silence them apart from validating its own parameters. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + * + * @return Psr7UriInterface|UriInterface + */ + public static function relativize($uri, $base_uri) + { + self::filterUri($uri); + self::filterUri($base_uri); + $uri = self::formatHost($uri); + $base_uri = self::formatHost($base_uri); + if (!self::isRelativizable($uri, $base_uri)) { + return $uri; + } + + $null = $uri instanceof Psr7UriInterface ? '' : null; + $uri = $uri->withScheme($null)->withPort(null)->withUserInfo($null)->withHost($null); + $target_path = $uri->getPath(); + if ($target_path !== $base_uri->getPath()) { + return $uri->withPath(self::relativizePath($target_path, $base_uri->getPath())); + } + + if (self::componentEquals('getQuery', $uri, $base_uri)) { + return $uri->withPath('')->withQuery($null); + } + + if ($null === $uri->getQuery()) { + return $uri->withPath(self::formatPathWithEmptyBaseQuery($target_path)); + } + + return $uri->withPath(''); + } + + /** + * Tells whether the component value from both URI object equals. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + */ + private static function componentEquals(string $method, $uri, $base_uri): bool + { + return self::getComponent($method, $uri) === self::getComponent($method, $base_uri); + } + + /** + * Returns the component value from the submitted URI object. + * + * @param Psr7UriInterface|UriInterface $uri + */ + private static function getComponent(string $method, $uri): ?string + { + $component = $uri->$method(); + if ($uri instanceof Psr7UriInterface && '' === $component) { + return null; + } + + return $component; + } + + /** + * Filter the URI object. + * + * @param null|mixed $uri + * + * @throws \TypeError if the URI object does not implements the supported interfaces. + * + * @return Psr7UriInterface|UriInterface + */ + private static function formatHost($uri) + { + if (!$uri instanceof Psr7UriInterface) { + return $uri; + } + + $host = $uri->getHost(); + if ('' === $host) { + return $uri; + } + + return $uri->withHost((string) Uri::createFromComponents(['host' => $host])->getHost()); + } + + /** + * Tell whether the submitted URI object can be relativize. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + */ + private static function isRelativizable($uri, $base_uri): bool + { + return !UriInfo::isRelativePath($uri) + && self::componentEquals('getScheme', $uri, $base_uri) + && self::componentEquals('getAuthority', $uri, $base_uri); + } + + /** + * Relative the URI for a authority-less target URI. + */ + private static function relativizePath(string $path, string $basepath): string + { + $base_segments = self::getSegments($basepath); + $target_segments = self::getSegments($path); + $target_basename = array_pop($target_segments); + array_pop($base_segments); + foreach ($base_segments as $offset => $segment) { + if (!isset($target_segments[$offset]) || $segment !== $target_segments[$offset]) { + break; + } + unset($base_segments[$offset], $target_segments[$offset]); + } + $target_segments[] = $target_basename; + + return self::formatPath( + str_repeat('../', count($base_segments)).implode('/', $target_segments), + $basepath + ); + } + + /** + * returns the path segments. + * + * @return string[] + */ + private static function getSegments(string $path): array + { + if ('' !== $path && '/' === $path[0]) { + $path = substr($path, 1); + } + + return explode('/', $path); + } + + /** + * Formatting the path to keep a valid URI. + */ + private static function formatPath(string $path, string $basepath): string + { + if ('' === $path) { + return in_array($basepath, ['', '/'], true) ? $basepath : './'; + } + + if (false === ($colon_pos = strpos($path, ':'))) { + return $path; + } + + $slash_pos = strpos($path, '/'); + if (false === $slash_pos || $colon_pos < $slash_pos) { + return "./$path"; + } + + return $path; + } + + /** + * Formatting the path to keep a resolvable URI. + */ + private static function formatPathWithEmptyBaseQuery(string $path): string + { + $target_segments = self::getSegments($path); + /** @var string $basename */ + $basename = end($target_segments); + + return '' === $basename ? './' : $basename; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriString.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriString.php new file mode 100644 index 00000000..5f865479 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriString.php @@ -0,0 +1,466 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri; + +use League\Uri\Exceptions\IdnaConversionFailed; +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; +use League\Uri\Idna\Idna; +use function array_merge; +use function explode; +use function filter_var; +use function gettype; +use function inet_pton; +use function is_object; +use function is_scalar; +use function method_exists; +use function preg_match; +use function rawurldecode; +use function sprintf; +use function strpos; +use function substr; +use const FILTER_FLAG_IPV6; +use const FILTER_VALIDATE_IP; + +/** + * A class to parse a URI string according to RFC3986. + * + * @link https://tools.ietf.org/html/rfc3986 + * @package League\Uri + * @author Ignace Nyamagana Butera + * @since 6.0.0 + */ +final class UriString +{ + /** + * Default URI component values. + */ + private const URI_COMPONENTS = [ + 'scheme' => null, 'user' => null, 'pass' => null, 'host' => null, + 'port' => null, 'path' => '', 'query' => null, 'fragment' => null, + ]; + + /** + * Simple URI which do not need any parsing. + */ + private const URI_SCHORTCUTS = [ + '' => [], + '#' => ['fragment' => ''], + '?' => ['query' => ''], + '?#' => ['query' => '', 'fragment' => ''], + '/' => ['path' => '/'], + '//' => ['host' => ''], + ]; + + /** + * Range of invalid characters in URI string. + */ + private const REGEXP_INVALID_URI_CHARS = '/[\x00-\x1f\x7f]/'; + + /** + * RFC3986 regular expression URI splitter. + * + * @link https://tools.ietf.org/html/rfc3986#appendix-B + */ + private const REGEXP_URI_PARTS = ',^ + (?(?[^:/?\#]+):)? # URI scheme component + (?//(?[^/?\#]*))? # URI authority part + (?[^?\#]*) # URI path component + (?\?(?[^\#]*))? # URI query component + (?\#(?.*))? # URI fragment component + ,x'; + + /** + * URI scheme regular expresssion. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.1 + */ + private const REGEXP_URI_SCHEME = '/^([a-z][a-z\d\+\.\-]*)?$/i'; + + /** + * IPvFuture regular expression. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + private const REGEXP_IP_FUTURE = '/^ + v(?[A-F0-9])+\. + (?: + (?[a-z0-9_~\-\.])| + (?[!$&\'()*+,;=:]) # also include the : character + )+ + $/ix'; + + /** + * General registered name regular expression. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + private const REGEXP_REGISTERED_NAME = '/(?(DEFINE) + (?[a-z0-9_~\-]) # . is missing as it is used to separate labels + (?[!$&\'()*+,;=]) + (?%[A-F0-9]{2}) + (?(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*) + ) + ^(?:(?®_name)\.)*(?®_name)\.?$/ix'; + + /** + * Invalid characters in host regular expression. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + private const REGEXP_INVALID_HOST_CHARS = '/ + [:\/?#\[\]@ ] # gen-delims characters as well as the space character + /ix'; + + /** + * Invalid path for URI without scheme and authority regular expression. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.3 + */ + private const REGEXP_INVALID_PATH = ',^(([^/]*):)(.*)?/,'; + + /** + * Host and Port splitter regular expression. + */ + private const REGEXP_HOST_PORT = ',^(?\[.*\]|[^:]*)(:(?.*))?$,'; + + /** + * IDN Host detector regular expression. + */ + private const REGEXP_IDN_PATTERN = '/[^\x20-\x7f]/'; + + /** + * Only the address block fe80::/10 can have a Zone ID attach to + * let's detect the link local significant 10 bits. + */ + private const ZONE_ID_ADDRESS_BLOCK = "\xfe\x80"; + + /** + * Generate an URI string representation from its parsed representation + * returned by League\Uri\parse() or PHP's parse_url. + * + * If you supply your own array, you are responsible for providing + * valid components without their URI delimiters. + * + * @link https://tools.ietf.org/html/rfc3986#section-5.3 + * @link https://tools.ietf.org/html/rfc3986#section-7.5 + * + * @param array{ + * scheme:?string, + * user:?string, + * pass:?string, + * host:?string, + * port:?int, + * path:string, + * query:?string, + * fragment:?string + * } $components + */ + public static function build(array $components): string + { + $result = $components['path'] ?? ''; + if (isset($components['query'])) { + $result .= '?'.$components['query']; + } + + if (isset($components['fragment'])) { + $result .= '#'.$components['fragment']; + } + + $scheme = null; + if (isset($components['scheme'])) { + $scheme = $components['scheme'].':'; + } + + if (!isset($components['host'])) { + return $scheme.$result; + } + + $scheme .= '//'; + $authority = $components['host']; + if (isset($components['port'])) { + $authority .= ':'.$components['port']; + } + + if (!isset($components['user'])) { + return $scheme.$authority.$result; + } + + $authority = '@'.$authority; + if (!isset($components['pass'])) { + return $scheme.$components['user'].$authority.$result; + } + + return $scheme.$components['user'].':'.$components['pass'].$authority.$result; + } + + /** + * Parse an URI string into its components. + * + * This method parses a URI and returns an associative array containing any + * of the various components of the URI that are present. + * + * + * $components = (new Parser())->parse('http://foo@test.example.com:42?query#'); + * var_export($components); + * //will display + * array( + * 'scheme' => 'http', // the URI scheme component + * 'user' => 'foo', // the URI user component + * 'pass' => null, // the URI pass component + * 'host' => 'test.example.com', // the URI host component + * 'port' => 42, // the URI port component + * 'path' => '', // the URI path component + * 'query' => 'query', // the URI query component + * 'fragment' => '', // the URI fragment component + * ); + * + * + * The returned array is similar to PHP's parse_url return value with the following + * differences: + * + *
    + *
  • All components are always present in the returned array
  • + *
  • Empty and undefined component are treated differently. And empty component is + * set to the empty string while an undefined component is set to the `null` value.
  • + *
  • The path component is never undefined
  • + *
  • The method parses the URI following the RFC3986 rules but you are still + * required to validate the returned components against its related scheme specific rules.
  • + *
+ * + * @link https://tools.ietf.org/html/rfc3986 + * + * @param mixed $uri any scalar or stringable object + * + * @throws SyntaxError if the URI contains invalid characters + * @throws SyntaxError if the URI contains an invalid scheme + * @throws SyntaxError if the URI contains an invalid path + * + * @return array{ + * scheme:?string, + * user:?string, + * pass:?string, + * host:?string, + * port:?int, + * path:string, + * query:?string, + * fragment:?string + * } + */ + public static function parse($uri): array + { + if (is_object($uri) && method_exists($uri, '__toString')) { + $uri = (string) $uri; + } + + if (!is_scalar($uri)) { + throw new \TypeError(sprintf('The uri must be a scalar or a stringable object `%s` given', gettype($uri))); + } + + $uri = (string) $uri; + + if (isset(self::URI_SCHORTCUTS[$uri])) { + /** @var array{scheme:?string, user:?string, pass:?string, host:?string, port:?int, path:string, query:?string, fragment:?string} $components */ + $components = array_merge(self::URI_COMPONENTS, self::URI_SCHORTCUTS[$uri]); + + return $components; + } + + if (1 === preg_match(self::REGEXP_INVALID_URI_CHARS, $uri)) { + throw new SyntaxError(sprintf('The uri `%s` contains invalid characters', $uri)); + } + + //if the first character is a known URI delimiter parsing can be simplified + $first_char = $uri[0]; + + //The URI is made of the fragment only + if ('#' === $first_char) { + [, $fragment] = explode('#', $uri, 2); + $components = self::URI_COMPONENTS; + $components['fragment'] = $fragment; + + return $components; + } + + //The URI is made of the query and fragment + if ('?' === $first_char) { + [, $partial] = explode('?', $uri, 2); + [$query, $fragment] = explode('#', $partial, 2) + [1 => null]; + $components = self::URI_COMPONENTS; + $components['query'] = $query; + $components['fragment'] = $fragment; + + return $components; + } + + //use RFC3986 URI regexp to split the URI + preg_match(self::REGEXP_URI_PARTS, $uri, $parts); + $parts += ['query' => '', 'fragment' => '']; + + if (':' === $parts['scheme'] || 1 !== preg_match(self::REGEXP_URI_SCHEME, $parts['scontent'])) { + throw new SyntaxError(sprintf('The uri `%s` contains an invalid scheme', $uri)); + } + + if ('' === $parts['scheme'].$parts['authority'] && 1 === preg_match(self::REGEXP_INVALID_PATH, $parts['path'])) { + throw new SyntaxError(sprintf('The uri `%s` contains an invalid path.', $uri)); + } + + /** @var array{scheme:?string, user:?string, pass:?string, host:?string, port:?int, path:string, query:?string, fragment:?string} $components */ + $components = array_merge( + self::URI_COMPONENTS, + '' === $parts['authority'] ? [] : self::parseAuthority($parts['acontent']), + [ + 'path' => $parts['path'], + 'scheme' => '' === $parts['scheme'] ? null : $parts['scontent'], + 'query' => '' === $parts['query'] ? null : $parts['qcontent'], + 'fragment' => '' === $parts['fragment'] ? null : $parts['fcontent'], + ] + ); + + return $components; + } + + /** + * Parses the URI authority part. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2 + * + * @throws SyntaxError If the port component is invalid + * + * @return array{user:?string, pass:?string, host:?string, port:?int} + */ + private static function parseAuthority(string $authority): array + { + $components = ['user' => null, 'pass' => null, 'host' => '', 'port' => null]; + if ('' === $authority) { + return $components; + } + + $parts = explode('@', $authority, 2); + if (isset($parts[1])) { + [$components['user'], $components['pass']] = explode(':', $parts[0], 2) + [1 => null]; + } + + preg_match(self::REGEXP_HOST_PORT, $parts[1] ?? $parts[0], $matches); + $matches += ['port' => '']; + + $components['port'] = self::filterPort($matches['port']); + $components['host'] = self::filterHost($matches['host']); + + return $components; + } + + /** + * Filter and format the port component. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + * + * @throws SyntaxError if the registered name is invalid + */ + private static function filterPort(string $port): ?int + { + if ('' === $port) { + return null; + } + + if (1 === preg_match('/^\d*$/', $port)) { + return (int) $port; + } + + throw new SyntaxError(sprintf('The port `%s` is invalid', $port)); + } + + /** + * Returns whether a hostname is valid. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + * + * @throws SyntaxError if the registered name is invalid + */ + private static function filterHost(string $host): string + { + if ('' === $host) { + return $host; + } + + if ('[' !== $host[0] || ']' !== substr($host, -1)) { + return self::filterRegisteredName($host); + } + + if (!self::isIpHost(substr($host, 1, -1))) { + throw new SyntaxError(sprintf('Host `%s` is invalid : the IP host is malformed', $host)); + } + + return $host; + } + + /** + * Returns whether the host is an IPv4 or a registered named. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + * + * @throws SyntaxError if the registered name is invalid + * @throws IdnSupportMissing if IDN support or ICU requirement are not available or met. + */ + private static function filterRegisteredName(string $host): string + { + $formatted_host = rawurldecode($host); + if (1 === preg_match(self::REGEXP_REGISTERED_NAME, $formatted_host)) { + return $host; + } + + //to test IDN host non-ascii characters must be present in the host + if (1 !== preg_match(self::REGEXP_IDN_PATTERN, $formatted_host)) { + throw new SyntaxError(sprintf('Host `%s` is invalid : the host is not a valid registered name', $host)); + } + + $info = Idna::toAscii($host, Idna::IDNA2008_ASCII); + if (0 !== $info->errors()) { + throw IdnaConversionFailed::dueToIDNAError($host, $info); + } + + return $host; + } + + /** + * Validates a IPv6/IPvfuture host. + * + * @link https://tools.ietf.org/html/rfc3986#section-3.2.2 + * @link https://tools.ietf.org/html/rfc6874#section-2 + * @link https://tools.ietf.org/html/rfc6874#section-4 + */ + private static function isIpHost(string $ip_host): bool + { + if (false !== filter_var($ip_host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + return true; + } + + if (1 === preg_match(self::REGEXP_IP_FUTURE, $ip_host, $matches)) { + return !in_array($matches['version'], ['4', '6'], true); + } + + $pos = strpos($ip_host, '%'); + if (false === $pos || 1 === preg_match( + self::REGEXP_INVALID_HOST_CHARS, + rawurldecode(substr($ip_host, $pos)) + )) { + return false; + } + + $ip_host = substr($ip_host, 0, $pos); + + return false !== filter_var($ip_host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) + && 0 === strpos((string) inet_pton($ip_host), self::ZONE_ID_ADDRESS_BLOCK); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate.php new file mode 100644 index 00000000..94bbef93 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri; + +use League\Uri\Contracts\UriException; +use League\Uri\Contracts\UriInterface; +use League\Uri\Exceptions\SyntaxError; +use League\Uri\Exceptions\TemplateCanNotBeExpanded; +use League\Uri\UriTemplate\Template; +use League\Uri\UriTemplate\VariableBag; + +/** + * Defines the URI Template syntax and the process for expanding a URI Template into a URI reference. + * + * @link https://tools.ietf.org/html/rfc6570 + * @package League\Uri + * @author Ignace Nyamagana Butera + * @since 6.1.0 + * + * Based on GuzzleHttp\UriTemplate class in Guzzle v6.5. + * @link https://github.com/guzzle/guzzle/blob/6.5/src/UriTemplate.php + */ +final class UriTemplate +{ + /** + * @var Template + */ + private $template; + + /** + * @var VariableBag + */ + private $defaultVariables; + + /** + * @param object|string $template a string or an object with the __toString method + * + * @throws \TypeError if the template is not a string or an object with the __toString method + * @throws SyntaxError if the template syntax is invalid + * @throws TemplateCanNotBeExpanded if the template variables are invalid + */ + public function __construct($template, array $defaultVariables = []) + { + $this->template = Template::createFromString($template); + $this->defaultVariables = $this->filterVariables($defaultVariables); + } + + public static function __set_state(array $properties): self + { + return new self($properties['template']->toString(), $properties['defaultVariables']->all()); + } + + /** + * Filters out variables for the given template. + * + * @param array> $variables + */ + private function filterVariables(array $variables): VariableBag + { + $output = new VariableBag(); + foreach ($this->template->variableNames() as $name) { + if (isset($variables[$name])) { + $output->assign($name, $variables[$name]); + } + } + + return $output; + } + + /** + * The template string. + */ + public function getTemplate(): string + { + return $this->template->toString(); + } + + /** + * Returns the names of the variables in the template, in order. + * + * @return string[] + */ + public function getVariableNames(): array + { + return $this->template->variableNames(); + } + + /** + * Returns the default values used to expand the template. + * + * The returned list only contains variables whose name is part of the current template. + * + * @return array + */ + public function getDefaultVariables(): array + { + return $this->defaultVariables->all(); + } + + /** + * Returns a new instance with the updated default variables. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified default variables. + * + * If present, variables whose name is not part of the current template + * possible variable names are removed. + */ + public function withDefaultVariables(array $defaultDefaultVariables): self + { + $clone = clone $this; + $clone->defaultVariables = $this->filterVariables($defaultDefaultVariables); + + return $clone; + } + + /** + * @throws TemplateCanNotBeExpanded if the variable contains nested array values + * @throws UriException if the resulting expansion can not be converted to a UriInterface instance + */ + public function expand(array $variables = []): UriInterface + { + $uriString = $this->template->expand( + $this->filterVariables($variables)->replace($this->defaultVariables) + ); + + return Uri::createFromString($uriString); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Expression.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Expression.php new file mode 100644 index 00000000..7a57b4a2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Expression.php @@ -0,0 +1,353 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\UriTemplate; + +use League\Uri\Exceptions\SyntaxError; +use League\Uri\Exceptions\TemplateCanNotBeExpanded; +use function array_filter; +use function array_keys; +use function array_map; +use function array_unique; +use function explode; +use function implode; +use function preg_match; +use function rawurlencode; +use function str_replace; +use function strpos; +use function substr; + +final class Expression +{ + /** + * Expression regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc6570#section-2.2 + */ + private const REGEXP_EXPRESSION = '/^\{ + (?: + (?[\.\/;\?&\=,\!@\|\+#])? + (?[^\}]*) + ) + \}$/x'; + + /** + * Reserved Operator characters. + * + * @link https://tools.ietf.org/html/rfc6570#section-2.2 + */ + private const RESERVED_OPERATOR = '=,!@|'; + + /** + * Processing behavior according to the expression type operator. + * + * @link https://tools.ietf.org/html/rfc6570#appendix-A + */ + private const OPERATOR_HASH_LOOKUP = [ + '' => ['prefix' => '', 'joiner' => ',', 'query' => false], + '+' => ['prefix' => '', 'joiner' => ',', 'query' => false], + '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false], + '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false], + '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false], + ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true], + '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true], + '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true], + ]; + + /** + * @var string + */ + private $operator; + + /** + * @var string + */ + private $joiner; + + /** + * @var array + */ + private $varSpecifiers; + + /** + * @var array + */ + private $variableNames; + + /** + * @var string + */ + private $expressionString; + + private function __construct(string $operator, VarSpecifier ...$varSpecifiers) + { + $this->operator = $operator; + $this->varSpecifiers = $varSpecifiers; + $this->joiner = self::OPERATOR_HASH_LOOKUP[$operator]['joiner']; + $this->variableNames = $this->setVariableNames(); + $this->expressionString = $this->setExpressionString(); + } + + /** + * @return array + */ + private function setVariableNames(): array + { + $mapper = static function (VarSpecifier $varSpecifier): string { + return $varSpecifier->name(); + }; + + return array_unique(array_map($mapper, $this->varSpecifiers)); + } + + private function setExpressionString(): string + { + $mapper = static function (VarSpecifier $variable): string { + return $variable->toString(); + }; + + $varSpecifierString = implode(',', array_map($mapper, $this->varSpecifiers)); + + return '{'.$this->operator.$varSpecifierString.'}'; + } + + /** + * {@inheritDoc} + */ + public static function __set_state(array $properties): self + { + return new self($properties['operator'], ...$properties['varSpecifiers']); + } + + /** + * @throws SyntaxError if the expression is invalid + * @throws SyntaxError if the operator used in the expression is invalid + * @throws SyntaxError if the variable specifiers is invalid + */ + public static function createFromString(string $expression): self + { + if (1 !== preg_match(self::REGEXP_EXPRESSION, $expression, $parts)) { + throw new SyntaxError('The expression "'.$expression.'" is invalid.'); + } + + /** @var array{operator:string, variables:string} $parts */ + $parts = $parts + ['operator' => '']; + if ('' !== $parts['operator'] && false !== strpos(self::RESERVED_OPERATOR, $parts['operator'])) { + throw new SyntaxError('The operator used in the expression "'.$expression.'" is reserved.'); + } + + $mapper = static function (string $varSpec): VarSpecifier { + return VarSpecifier::createFromString($varSpec); + }; + + return new Expression($parts['operator'], ...array_map($mapper, explode(',', $parts['variables']))); + } + + /** + * Returns the expression string representation. + * + */ + public function toString(): string + { + return $this->expressionString; + } + + /** + * @return array + */ + public function variableNames(): array + { + return $this->variableNames; + } + + public function expand(VariableBag $variables): string + { + $parts = []; + foreach ($this->varSpecifiers as $varSpecifier) { + $parts[] = $this->replace($varSpecifier, $variables); + } + + $nullFilter = static function ($value): bool { + return '' !== $value; + }; + + $expanded = implode($this->joiner, array_filter($parts, $nullFilter)); + if ('' === $expanded) { + return $expanded; + } + + $prefix = self::OPERATOR_HASH_LOOKUP[$this->operator]['prefix']; + if ('' === $prefix) { + return $expanded; + } + + return $prefix.$expanded; + } + + /** + * Replaces an expression with the given variables. + * + * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied + * @throws TemplateCanNotBeExpanded if the variables contains nested array values + */ + private function replace(VarSpecifier $varSpec, VariableBag $variables): string + { + $value = $variables->fetch($varSpec->name()); + if (null === $value) { + return ''; + } + + $useQuery = self::OPERATOR_HASH_LOOKUP[$this->operator]['query']; + [$expanded, $actualQuery] = $this->inject($value, $varSpec, $useQuery); + if (!$actualQuery) { + return $expanded; + } + + if ('&' !== $this->joiner && '' === $expanded) { + return $varSpec->name(); + } + + return $varSpec->name().'='.$expanded; + } + + /** + * @param string|array $value + * + * @return array{0:string, 1:bool} + */ + private function inject($value, VarSpecifier $varSpec, bool $useQuery): array + { + if (is_string($value)) { + return $this->replaceString($value, $varSpec, $useQuery); + } + + return $this->replaceList($value, $varSpec, $useQuery); + } + + /** + * Expands an expression using a string value. + * + * @return array{0:string, 1:bool} + */ + private function replaceString(string $value, VarSpecifier $varSpec, bool $useQuery): array + { + if (':' === $varSpec->modifier()) { + $value = substr($value, 0, $varSpec->position()); + } + + $expanded = rawurlencode($value); + if ('+' === $this->operator || '#' === $this->operator) { + return [$this->decodeReserved($expanded), $useQuery]; + } + + return [$expanded, $useQuery]; + } + + /** + * Expands an expression using a list of values. + * + * @param array $value + * + * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied + * + * @return array{0:string, 1:bool} + */ + private function replaceList(array $value, VarSpecifier $varSpec, bool $useQuery): array + { + if ([] === $value) { + return ['', false]; + } + + if (':' === $varSpec->modifier()) { + throw TemplateCanNotBeExpanded::dueToUnableToProcessValueListWithPrefix($varSpec->name()); + } + + $pairs = []; + $isAssoc = $this->isAssoc($value); + foreach ($value as $key => $var) { + if ($isAssoc) { + $key = rawurlencode((string) $key); + } + + $var = rawurlencode($var); + if ('+' === $this->operator || '#' === $this->operator) { + $var = $this->decodeReserved($var); + } + + if ('*' === $varSpec->modifier()) { + if ($isAssoc) { + $var = $key.'='.$var; + } elseif ($key > 0 && $useQuery) { + $var = $varSpec->name().'='.$var; + } + } + + $pairs[$key] = $var; + } + + if ('*' === $varSpec->modifier()) { + if ($isAssoc) { + // Don't prepend the value name when using the explode + // modifier with an associative array. + $useQuery = false; + } + + return [implode($this->joiner, $pairs), $useQuery]; + } + + if ($isAssoc) { + // When an associative array is encountered and the + // explode modifier is not set, then the result must be + // a comma separated list of keys followed by their + // respective values. + foreach ($pairs as $offset => &$data) { + $data = $offset.','.$data; + } + + unset($data); + } + + return [implode(',', $pairs), $useQuery]; + } + + /** + * Determines if an array is associative. + * + * This makes the assumption that input arrays are sequences or hashes. + * This assumption is a trade-off for accuracy in favor of speed, but it + * should work in almost every case where input is supplied for a URI + * template. + */ + private function isAssoc(array $array): bool + { + return [] !== $array && 0 !== array_keys($array)[0]; + } + + /** + * Removes percent encoding on reserved characters (used with + and # modifiers). + */ + private function decodeReserved(string $str): string + { + static $delimiters = [ + ':', '/', '?', '#', '[', ']', '@', '!', '$', + '&', '\'', '(', ')', '*', '+', ',', ';', '=', + ]; + + static $delimitersEncoded = [ + '%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', + '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D', + ]; + + return str_replace($delimitersEncoded, $delimiters, $str); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Template.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Template.php new file mode 100644 index 00000000..e17b3c94 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/Template.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\UriTemplate; + +use League\Uri\Exceptions\SyntaxError; +use League\Uri\Exceptions\TemplateCanNotBeExpanded; +use function array_merge; +use function array_unique; +use function gettype; +use function is_object; +use function is_string; +use function method_exists; +use function preg_match_all; +use function preg_replace; +use function sprintf; +use function strpos; +use const PREG_SET_ORDER; + +final class Template +{ + /** + * Expression regular expression pattern. + */ + private const REGEXP_EXPRESSION_DETECTOR = '/\{[^\}]*\}/x'; + + /** + * @var string + */ + private $template; + + /** + * @var array + */ + private $expressions = []; + + /** + * @var array + */ + private $variableNames; + + private function __construct(string $template, Expression ...$expressions) + { + $this->template = $template; + $variableNames = []; + foreach ($expressions as $expression) { + $this->expressions[$expression->toString()] = $expression; + $variableNames[] = $expression->variableNames(); + } + $this->variableNames = array_unique(array_merge([], ...$variableNames)); + } + + /** + * {@inheritDoc} + */ + public static function __set_state(array $properties): self + { + return new self($properties['template'], ...array_values($properties['expressions'])); + } + + /** + * @param object|string $template a string or an object with the __toString method + * + * @throws \TypeError if the template is not a string or an object with the __toString method + * @throws SyntaxError if the template contains invalid expressions + * @throws SyntaxError if the template contains invalid variable specification + */ + public static function createFromString($template): self + { + if (is_object($template) && method_exists($template, '__toString')) { + $template = (string) $template; + } + + if (!is_string($template)) { + throw new \TypeError(sprintf('The template must be a string or a stringable object %s given.', gettype($template))); + } + + /** @var string $remainder */ + $remainder = preg_replace(self::REGEXP_EXPRESSION_DETECTOR, '', $template); + if (false !== strpos($remainder, '{') || false !== strpos($remainder, '}')) { + throw new SyntaxError('The template "'.$template.'" contains invalid expressions.'); + } + + $names = []; + preg_match_all(self::REGEXP_EXPRESSION_DETECTOR, $template, $findings, PREG_SET_ORDER); + $arguments = []; + foreach ($findings as $finding) { + if (!isset($names[$finding[0]])) { + $arguments[] = Expression::createFromString($finding[0]); + $names[$finding[0]] = 1; + } + } + + return new self($template, ...$arguments); + } + + public function toString(): string + { + return $this->template; + } + + /** + * @return array + */ + public function variableNames(): array + { + return $this->variableNames; + } + + /** + * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied + * @throws TemplateCanNotBeExpanded if the variables contains nested array values + */ + public function expand(VariableBag $variables): string + { + $uriString = $this->template; + /** @var Expression $expression */ + foreach ($this->expressions as $pattern => $expression) { + $uriString = str_replace($pattern, $expression->expand($variables), $uriString); + } + + return $uriString; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VarSpecifier.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VarSpecifier.php new file mode 100644 index 00000000..e66de073 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VarSpecifier.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\UriTemplate; + +use League\Uri\Exceptions\SyntaxError; +use function preg_match; + +final class VarSpecifier +{ + /** + * Variables specification regular expression pattern. + * + * @link https://tools.ietf.org/html/rfc6570#section-2.3 + */ + private const REGEXP_VARSPEC = '/^ + (?(?:[A-z0-9_\.]|%[0-9a-fA-F]{2})+) + (?\:(?\d+)|\*)? + $/x'; + + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $modifier; + + /** + * @var int + */ + private $position; + + private function __construct(string $name, string $modifier, int $position) + { + $this->name = $name; + $this->modifier = $modifier; + $this->position = $position; + } + + /** + * {@inheritDoc} + */ + public static function __set_state(array $properties): self + { + return new self($properties['name'], $properties['modifier'], $properties['position']); + } + + public static function createFromString(string $specification): self + { + if (1 !== preg_match(self::REGEXP_VARSPEC, $specification, $parsed)) { + throw new SyntaxError('The variable specification "'.$specification.'" is invalid.'); + } + + $parsed += ['modifier' => '', 'position' => '']; + if ('' !== $parsed['position']) { + $parsed['position'] = (int) $parsed['position']; + $parsed['modifier'] = ':'; + } + + if ('' === $parsed['position']) { + $parsed['position'] = 0; + } + + if (10000 <= $parsed['position']) { + throw new SyntaxError('The variable specification "'.$specification.'" is invalid the position modifier must be lower than 10000.'); + } + + return new self($parsed['name'], $parsed['modifier'], $parsed['position']); + } + + public function toString(): string + { + if (0 < $this->position) { + return $this->name.$this->modifier.$this->position; + } + + return $this->name.$this->modifier; + } + + public function name(): string + { + return $this->name; + } + + public function modifier(): string + { + return $this->modifier; + } + + public function position(): int + { + return $this->position; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VariableBag.php b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VariableBag.php new file mode 100644 index 00000000..cd4b0972 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/src/UriTemplate/VariableBag.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\UriTemplate; + +use League\Uri\Exceptions\TemplateCanNotBeExpanded; +use function gettype; +use function is_array; +use function is_bool; +use function is_object; +use function is_scalar; +use function method_exists; +use function sprintf; + +final class VariableBag +{ + /** + * @var array> + */ + private $variables = []; + + /** + * @param iterable $variables + */ + public function __construct(iterable $variables = []) + { + foreach ($variables as $name => $value) { + $this->assign($name, $value); + } + } + + public static function __set_state(array $properties): self + { + return new self($properties['variables']); + } + + /** + * @return array> + */ + public function all(): array + { + return $this->variables; + } + + /** + * Fetches the variable value if none found returns null. + * + * @return null|string|array + */ + public function fetch(string $name) + { + return $this->variables[$name] ?? null; + } + + /** + * @param string|array $value + */ + public function assign(string $name, $value): void + { + $this->variables[$name] = $this->normalizeValue($value, $name, true); + } + + /** + * @param mixed $value the value to be expanded + * + * @throws TemplateCanNotBeExpanded if the value contains nested list + * + * @return string|array + */ + private function normalizeValue($value, string $name, bool $isNestedListAllowed) + { + if (is_bool($value)) { + return true === $value ? '1' : '0'; + } + + if (null === $value || is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) { + return (string) $value; + } + + if (!is_array($value)) { + throw new \TypeError(sprintf('The variable '.$name.' must be NULL, a scalar or a stringable object `%s` given', gettype($value))); + } + + if (!$isNestedListAllowed) { + throw TemplateCanNotBeExpanded::dueToNestedListOfValue($name); + } + + foreach ($value as &$var) { + $var = self::normalizeValue($var, $name, false); + } + unset($var); + + return $value; + } + + /** + * Replaces elements from passed variables into the current instance. + */ + public function replace(VariableBag $variables): self + { + $instance = clone $this; + $instance->variables += $variables->variables; + + return $instance; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/hello-world.txt b/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/hello-world.txt new file mode 100644 index 00000000..2fb8406f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/hello-world.txt @@ -0,0 +1 @@ +Bonjour le monde! \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/john-doe.vcf b/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/john-doe.vcf new file mode 100644 index 00000000..1116636e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/john-doe.vcf @@ -0,0 +1,25 @@ +BEGIN:VCARD +VERSION:3.0 +N:Doe;John;;; +FN:John Doe +ORG:Example.com Inc.; +TITLE:Imaginary test person +EMAIL;type=INTERNET;type=WORK;type=pref:johnDoe@example.org +TEL;type=WORK;type=pref:+1 617 555 1212 +TEL;type=WORK:+1 (617) 555-1234 +TEL;type=CELL:+1 781 555 1212 +TEL;type=HOME:+1 202 555 1212 +item1.ADR;type=WORK:;;2 Enterprise Avenue;Worktown;NY;01111;USA +item1.X-ABADR:us +item2.ADR;type=HOME;type=pref:;;3 Acacia Avenue;Hoemtown;MA;02222;USA +item2.X-ABADR:us +NOTE:John Doe has a long and varied history\, being documented on more police files that anyone else. Reports of his death are alas numerous. +item3.URL;type=pref:http\://www.example/com/doe +item3.X-ABLabel:_$!!$_ +item4.URL:http\://www.example.com/Joe/foaf.df +item4.X-ABLabel:FOAF +item5.X-ABRELATEDNAMES;type=pref:Jane Doe +item5.X-ABLabel:_$!!$_ +CATEGORIES:Work,Test group +X-ABUID:5AD380FD-B2DE-4261-BA99-DE1D1DB52FBE\:ABPerson +END:VCARD diff --git a/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/red-nose.gif b/wp-content/plugins/wp-webauthn/vendor/league/uri/test_files/red-nose.gif new file mode 100644 index 0000000000000000000000000000000000000000..283fdd3ef079af467660eb5af9d67a9ecdc393aa GIT binary patch literal 119 zcmZ?wbhEHbRA5kGXkcXc&%p5i|9{1Qg3d*$i6yBi3gww484B*6z5xu1KUo;L7#JCJ z7=QqzoPo)*r+?+?xBQFeY`N9Fxo*L4ex?wQs$|c38Y|X4d$OtEk5`H8-B{_*>-IA( WYEezfD!Z*Q{min@oV{sW4Aua3p)D-{ literal 0 HcmV?d00001 diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/.github/FUNDING.yml b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/.github/FUNDING.yml new file mode 100644 index 00000000..11255a01 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [nyholm, Zegnat] diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/CHANGELOG.md b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/CHANGELOG.md new file mode 100644 index 00000000..2e98d6ff --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/CHANGELOG.md @@ -0,0 +1,54 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 0.4.2 + +### Fixed + +- Support for numerical headers + +## 0.4.1 + +### Fixed + +- Support for ´HTTP_X_FORWARDED_PROTO´ + +## 0.4.0 + +### Fixed + +- Support for Host-header with port-number + +## 0.3.0 + +### Added + +- `ServerRequestCreator` is final + +### Fixed + +- Fallback to an empty Stream if UploadedFileFactory fails. + +## 0.2.0 + +### Changed + +- Make sure we use psr/http-factory + +## 0.1.2 + +### Added + +- `ServerRequestCreatorInterface` +- `ServerRequestCreator::getHeadersFromServer` + +## 0.1.1 + +### Added + +Better testing + +## 0.1.0 + +First release diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/LICENSE b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/LICENSE new file mode 100644 index 00000000..d91e7536 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Tobias Nyholm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/README.md b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/README.md new file mode 100644 index 00000000..b3f5cb3a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/README.md @@ -0,0 +1,38 @@ +# Helper class to create PSR-7 server request + +[![Latest Version](https://img.shields.io/github/release/Nyholm/psr7-server.svg?style=flat-square)](https://github.com/Nyholm/psr7-server/releases) +[![Build Status](https://img.shields.io/travis/Nyholm/psr7-server/master.svg?style=flat-square)](https://travis-ci.org/Nyholm/psr7-server) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/Nyholm/psr7-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/Nyholm/psr7-server) +[![Quality Score](https://img.shields.io/scrutinizer/g/Nyholm/psr7-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/Nyholm/psr7-server) +[![Total Downloads](https://poser.pugx.org/nyholm/psr7-server/downloads)](https://packagist.org/packages/nyholm/psr7-server) +[![Monthly Downloads](https://poser.pugx.org/nyholm/psr7-server/d/monthly.png)](https://packagist.org/packages/nyholm/psr7-server) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) + +A helper class that can create ANY PSR-7 server request. + +## Installation + +```bash +composer require nyholm/psr7-server +``` + +## Usage + +```php +// Instanciate ANY PSR-17 factory implementations. Here is nyholm/psr7 as an example +$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); + +$creator = new \Nyholm\Psr7Server\ServerRequestCreator( + $psr17Factory, // ServerRequestFactory + $psr17Factory, // UriFactory + $psr17Factory, // UploadedFileFactory + $psr17Factory // StreamFactory +); + +$serverRequest = $creator->fromGlobals(); +``` + +## Other packages + +* [nyholm/psr7](https://github.com/Nyholm/psr7) - A super fast PSR-7 implementation. +* [zendframework/zend-httphandlerrunner](https://github.com/zendframework/zend-httphandlerrunner) - To send/emit PSR-7 responses diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/composer.json b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/composer.json new file mode 100644 index 00000000..732406da --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/composer.json @@ -0,0 +1,41 @@ +{ + "name": "nyholm/psr7-server", + "description": "Helper classes to handle PSR-7 server requests", + "license": "MIT", + "keywords": ["psr-7", "psr-17"], + "homepage": "http://tnyholm.se", + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "require": { + "php": "^7.1", + "psr/http-message": "^1.0", + "psr/http-factory": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0", + "nyholm/psr7": "^1.3", + "nyholm/nsa": "^1.1" + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7Server\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\Nyholm\\Psr7Server\\": "tests/" + } + }, + "scripts": { + "test": "vendor/bin/phpunit", + "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreator.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreator.php new file mode 100644 index 00000000..efecc689 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreator.php @@ -0,0 +1,282 @@ + + * @author Martijn van der Ven + */ +final class ServerRequestCreator implements ServerRequestCreatorInterface +{ + private $serverRequestFactory; + + private $uriFactory; + + private $uploadedFileFactory; + + private $streamFactory; + + public function __construct( + ServerRequestFactoryInterface $serverRequestFactory, + UriFactoryInterface $uriFactory, + UploadedFileFactoryInterface $uploadedFileFactory, + StreamFactoryInterface $streamFactory + ) { + $this->serverRequestFactory = $serverRequestFactory; + $this->uriFactory = $uriFactory; + $this->uploadedFileFactory = $uploadedFileFactory; + $this->streamFactory = $streamFactory; + } + + /** + * {@inheritdoc} + */ + public function fromGlobals(): ServerRequestInterface + { + $server = $_SERVER; + if (false === isset($server['REQUEST_METHOD'])) { + $server['REQUEST_METHOD'] = 'GET'; + } + + $headers = \function_exists('getallheaders') ? getallheaders() : static::getHeadersFromServer($_SERVER); + + return $this->fromArrays($server, $headers, $_COOKIE, $_GET, $_POST, $_FILES, \fopen('php://input', 'r') ?: null); + } + + /** + * {@inheritdoc} + */ + public function fromArrays(array $server, array $headers = [], array $cookie = [], array $get = [], array $post = [], array $files = [], $body = null): ServerRequestInterface + { + $method = $this->getMethodFromEnv($server); + $uri = $this->getUriFromEnvWithHTTP($server); + $protocol = isset($server['SERVER_PROTOCOL']) ? \str_replace('HTTP/', '', $server['SERVER_PROTOCOL']) : '1.1'; + + $serverRequest = $this->serverRequestFactory->createServerRequest($method, $uri, $server); + foreach ($headers as $name => $value) { + // Because PHP automatically casts array keys set with numeric strings to integers, we have to make sure + // that numeric headers will not be sent along as integers, as withAddedHeader can only accept strings. + if (\is_int($name)) { + $name = (string) $name; + } + $serverRequest = $serverRequest->withAddedHeader($name, $value); + } + + $serverRequest = $serverRequest + ->withProtocolVersion($protocol) + ->withCookieParams($cookie) + ->withQueryParams($get) + ->withParsedBody($post) + ->withUploadedFiles($this->normalizeFiles($files)); + + if (null === $body) { + return $serverRequest; + } + + if (\is_resource($body)) { + $body = $this->streamFactory->createStreamFromResource($body); + } elseif (\is_string($body)) { + $body = $this->streamFactory->createStream($body); + } elseif (!$body instanceof StreamInterface) { + throw new \InvalidArgumentException('The $body parameter to ServerRequestCreator::fromArrays must be string, resource or StreamInterface'); + } + + return $serverRequest->withBody($body); + } + + /** + * Implementation from Zend\Diactoros\marshalHeadersFromSapi(). + */ + public static function getHeadersFromServer(array $server): array + { + $headers = []; + foreach ($server as $key => $value) { + // Apache prefixes environment variables with REDIRECT_ + // if they are added by rewrite rules + if (0 === \strpos($key, 'REDIRECT_')) { + $key = \substr($key, 9); + + // We will not overwrite existing variables with the + // prefixed versions, though + if (\array_key_exists($key, $server)) { + continue; + } + } + + if ($value && 0 === \strpos($key, 'HTTP_')) { + $name = \strtr(\strtolower(\substr($key, 5)), '_', '-'); + $headers[$name] = $value; + + continue; + } + + if ($value && 0 === \strpos($key, 'CONTENT_')) { + $name = 'content-'.\strtolower(\substr($key, 8)); + $headers[$name] = $value; + + continue; + } + } + + return $headers; + } + + private function getMethodFromEnv(array $environment): string + { + if (false === isset($environment['REQUEST_METHOD'])) { + throw new \InvalidArgumentException('Cannot determine HTTP method'); + } + + return $environment['REQUEST_METHOD']; + } + + private function getUriFromEnvWithHTTP(array $environment): UriInterface + { + $uri = $this->createUriFromArray($environment); + if (empty($uri->getScheme())) { + $uri = $uri->withScheme('http'); + } + + return $uri; + } + + /** + * Return an UploadedFile instance array. + * + * @param array $files A array which respect $_FILES structure + * + * @return UploadedFileInterface[] + * + * @throws \InvalidArgumentException for unrecognized values + */ + private function normalizeFiles(array $files): array + { + $normalized = []; + + foreach ($files as $key => $value) { + if ($value instanceof UploadedFileInterface) { + $normalized[$key] = $value; + } elseif (\is_array($value) && isset($value['tmp_name'])) { + $normalized[$key] = $this->createUploadedFileFromSpec($value); + } elseif (\is_array($value)) { + $normalized[$key] = $this->normalizeFiles($value); + } else { + throw new \InvalidArgumentException('Invalid value in files specification'); + } + } + + return $normalized; + } + + /** + * Create and return an UploadedFile instance from a $_FILES specification. + * + * If the specification represents an array of values, this method will + * delegate to normalizeNestedFileSpec() and return that return value. + * + * @param array $value $_FILES struct + * + * @return array|UploadedFileInterface + */ + private function createUploadedFileFromSpec(array $value) + { + if (\is_array($value['tmp_name'])) { + return $this->normalizeNestedFileSpec($value); + } + + try { + $stream = $this->streamFactory->createStreamFromFile($value['tmp_name']); + } catch (\RuntimeException $e) { + $stream = $this->streamFactory->createStream(); + } + + return $this->uploadedFileFactory->createUploadedFile( + $stream, + (int) $value['size'], + (int) $value['error'], + $value['name'], + $value['type'] + ); + } + + /** + * Normalize an array of file specifications. + * + * Loops through all nested files and returns a normalized array of + * UploadedFileInterface instances. + * + * @return UploadedFileInterface[] + */ + private function normalizeNestedFileSpec(array $files = []): array + { + $normalizedFiles = []; + + foreach (\array_keys($files['tmp_name']) as $key) { + $spec = [ + 'tmp_name' => $files['tmp_name'][$key], + 'size' => $files['size'][$key], + 'error' => $files['error'][$key], + 'name' => $files['name'][$key], + 'type' => $files['type'][$key], + ]; + $normalizedFiles[$key] = $this->createUploadedFileFromSpec($spec); + } + + return $normalizedFiles; + } + + /** + * Create a new uri from server variable. + * + * @param array $server typically $_SERVER or similar structure + */ + private function createUriFromArray(array $server): UriInterface + { + $uri = $this->uriFactory->createUri(''); + + if (isset($server['HTTP_X_FORWARDED_PROTO'])) { + $uri = $uri->withScheme($server['HTTP_X_FORWARDED_PROTO']); + } else { + if (isset($server['REQUEST_SCHEME'])) { + $uri = $uri->withScheme($server['REQUEST_SCHEME']); + } elseif (isset($server['HTTPS'])) { + $uri = $uri->withScheme('on' === $server['HTTPS'] ? 'https' : 'http'); + } + + if (isset($server['SERVER_PORT'])) { + $uri = $uri->withPort($server['SERVER_PORT']); + } + } + + if (isset($server['HTTP_HOST'])) { + if (1 === \preg_match('/^(.+)\:(\d+)$/', $server['HTTP_HOST'], $matches)) { + $uri = $uri->withHost($matches[1])->withPort($matches[2]); + } else { + $uri = $uri->withHost($server['HTTP_HOST']); + } + } elseif (isset($server['SERVER_NAME'])) { + $uri = $uri->withHost($server['SERVER_NAME']); + } + + if (isset($server['REQUEST_URI'])) { + $uri = $uri->withPath(\current(\explode('?', $server['REQUEST_URI']))); + } + + if (isset($server['QUERY_STRING'])) { + $uri = $uri->withQuery($server['QUERY_STRING']); + } + + return $uri; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreatorInterface.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreatorInterface.php new file mode 100644 index 00000000..a5ab6889 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7-server/src/ServerRequestCreatorInterface.php @@ -0,0 +1,56 @@ + + * @author Martijn van der Ven + */ +interface ServerRequestCreatorInterface +{ + /** + * Create a new server request from the current environment variables. + * Defaults to a GET request to minimise the risk of an \InvalidArgumentException. + * Includes the current request headers as supplied by the server through `getallheaders()`. + * If `getallheaders()` is unavailable on the current server it will fallback to its own `getHeadersFromServer()` method. + * Defaults to php://input for the request body. + * + * @throws \InvalidArgumentException if no valid method or URI can be determined + */ + public function fromGlobals(): ServerRequestInterface; + + /** + * Create a new server request from a set of arrays. + * + * @param array $server typically $_SERVER or similar structure + * @param array $headers typically the output of getallheaders() or similar structure + * @param array $cookie typically $_COOKIE or similar structure + * @param array $get typically $_GET or similar structure + * @param array $post typically $_POST or similar structure + * @param array $files typically $_FILES or similar structure + * @param StreamInterface|resource|string|null $body Typically stdIn + * + * @throws \InvalidArgumentException if no valid method or URI can be determined + */ + public function fromArrays( + array $server, + array $headers = [], + array $cookie = [], + array $get = [], + array $post = [], + array $files = [], + $body = null + ): ServerRequestInterface; + + /** + * Get parsed headers from ($_SERVER) array. + * + * @param array $server typically $_SERVER or similar structure + */ + public static function getHeadersFromServer(array $server): array; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/CHANGELOG.md b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/CHANGELOG.md new file mode 100644 index 00000000..78a633ca --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/CHANGELOG.md @@ -0,0 +1,132 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.5.0 + +### Added + +- Add explicit `@return mixed` +- Add explicit return types to HttplugFactory + +### Fixed + +- Improve error handling with streams + +## 1.4.1 + +### Fixed + +- `Psr17Factory::createStreamFromFile`, `UploadedFile::moveTo`, and + `UploadedFile::getStream` no longer throw `ValueError` in PHP 8. + +## 1.4.0 + +### Removed + +The `final` keyword was replaced by `@final` annotation. + +## 1.3.2 + +### Fixed + +- `Stream::read()` must not return boolean. +- Improved exception message when using wrong HTTP status code. + +## 1.3.1 + +### Fixed + +- Allow installation on PHP8 + +## 1.3.0 + +### Added + +- Make Stream::__toString() compatible with throwing exceptions on PHP 7.4. + +### Fixed + +- Support for UTF-8 hostnames +- Support for numeric header names + +## 1.2.1 + +### Changed + +- Added `.github` and `phpstan.neon.dist` to `.gitattributes`. + +## 1.2.0 + +### Changed + +- Change minimal port number to 0 (unix socket) +- Updated `Psr17Factory::createResponse` to respect the specification. If second + argument is not used, a standard reason phrase. If an empty string is passed, + then the reason phrase will be empty. + +### Fixed + +- Check for seekable on the stream resource. +- Fixed the `Response::$reason` should never be null. + +## 1.1.0 + +### Added + +- Improved performance +- More tests for `UploadedFile` and `HttplugFactory` + +### Removed + +- Dead code + +## 1.0.1 + +### Fixed + +- Handle `fopen` failing in createStreamFromFile according to PSR-7. +- Reduce execution path to speed up performance. +- Fixed typos. +- Code style. + +## 1.0.0 + +### Added + +- Support for final PSR-17 (HTTP factories). (`Psr17Factory`) +- Support for numeric header values. +- Support for empty header values. +- All classes are final +- `HttplugFactory` that implements factory interfaces from HTTPlug. + +### Changed + +- `ServerRequest` does not extend `Request`. + +### Removed + +- The HTTPlug discovery strategy was removed since it is included in php-http/discovery 1.4. +- `UploadedFileFactory()` was removed in favor for `Psr17Factory`. +- `ServerRequestFactory()` was removed in favor for `Psr17Factory`. +- `StreamFactory`, `UriFactory`, abd `MessageFactory`. Use `HttplugFactory` instead. +- `ServerRequestFactory::createServerRequestFromArray`, `ServerRequestFactory::createServerRequestFromArrays` and + `ServerRequestFactory::createServerRequestFromGlobals`. Please use the new `nyholm/psr7-server` instead. + +## 0.3.0 + +### Added + +- Return types. +- Many `InvalidArgumentException`s are thrown when you use invalid arguments. +- Integration tests for `UploadedFile` and `ServerRequest`. + +### Changed + +- We dropped PHP7.0 support. +- PSR-17 factories have been marked as internal. They do not fall under our BC promise until PSR-17 is accepted. +- `UploadedFileFactory::createUploadedFile` does not accept a string file path. + +## 0.2.3 + +No changelog before this release diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/LICENSE b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/LICENSE new file mode 100644 index 00000000..d6c52312 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Tobias Nyholm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/README.md b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/README.md new file mode 100644 index 00000000..9f929330 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/README.md @@ -0,0 +1,110 @@ +# PSR-7 implementation + +[![Latest Version](https://img.shields.io/github/release/Nyholm/psr7.svg?style=flat-square)](https://github.com/Nyholm/psr7/releases) +[![Build Status](https://img.shields.io/travis/Nyholm/psr7/master.svg?style=flat-square)](https://travis-ci.org/Nyholm/psr7) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/Nyholm/psr7.svg?style=flat-square)](https://scrutinizer-ci.com/g/Nyholm/psr7) +[![Quality Score](https://img.shields.io/scrutinizer/g/Nyholm/psr7.svg?style=flat-square)](https://scrutinizer-ci.com/g/Nyholm/psr7) +[![Total Downloads](https://poser.pugx.org/nyholm/psr7/downloads)](https://packagist.org/packages/nyholm/psr7) +[![Monthly Downloads](https://poser.pugx.org/nyholm/psr7/d/monthly.png)](https://packagist.org/packages/nyholm/psr7) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) + + +A super lightweight PSR-7 implementation. Very strict and very fast. + +| Description | Guzzle | Laminas | Slim | Nyholm | +| ---- | ------ | ---- | ---- | ------ | +| Lines of code | 3.300 | 3.100 | 1.900 | 1.000 | +| PSR-7* | 66% | 100% | 75% | 100% | +| PSR-17 | No | Yes | Yes | Yes | +| HTTPlug | No | No | No | Yes | +| Performance (runs per second)** | 14.553 | 14.703 | 13.416 | 17.734 | + +\* Percent of completed tests in https://github.com/php-http/psr7-integration-tests + +\** Benchmark with 50.000 runs. See https://github.com/devanych/psr-http-benchmark (higher is better) + +## Installation + +```bash +composer require nyholm/psr7 +``` + +If you are using Symfony Flex then you get all message factories registered as services. + +## Usage + +The PSR-7 objects do not contain any other public methods than those defined in +the [PSR-7 specification](https://www.php-fig.org/psr/psr-7/). + +### Create objects + +Use the PSR-17 factory to create requests, streams, URIs etc. + +```php +$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); +$request = $psr17Factory->createRequest('GET', 'http://tnyholm.se'); +$stream = $psr17Factory->createStream('foobar'); +``` + +### Sending a request + +With [HTTPlug](http://httplug.io/) or any other PSR-18 (HTTP client) you may send +requests like: + +```bash +composer require kriswallsmith/buzz +``` + +```php +$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); +$psr18Client = new \Buzz\Client\Curl($psr17Factory); + +$request = $psr17Factory->createRequest('GET', 'http://tnyholm.se'); +$response = $psr18Client->sendRequest($request); +``` + +### Create server requests + +The [`nyholm/psr7-server`](https://github.com/Nyholm/psr7-server) package can be used +to create server requests from PHP superglobals. + +```bash +composer require nyholm/psr7-server +``` + +```php +$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); + +$creator = new \Nyholm\Psr7Server\ServerRequestCreator( + $psr17Factory, // ServerRequestFactory + $psr17Factory, // UriFactory + $psr17Factory, // UploadedFileFactory + $psr17Factory // StreamFactory +); + +$serverRequest = $creator->fromGlobals(); +``` + +### Emitting a response + +```bash +composer require laminas/laminas-httphandlerrunner +``` + +```php +$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); + +$responseBody = $psr17Factory->createStream('Hello world'); +$response = $psr17Factory->createResponse(200)->withBody($responseBody); +(new \Laminas\HttpHandlerRunner\Emitter\SapiEmitter())->emit($response); +``` + +## Our goal + +This package is currently maintained by [Tobias Nyholm](http://nyholm.se) and +[Martijn van der Ven](https://vanderven.se/martijn/). They have decided that the +goal of this library should be to provide a super strict implementation of +[PSR-7](https://www.php-fig.org/psr/psr-7/) that is blazing fast. + +The package will never include any extra features nor helper methods. All our classes +and functions exist because they are required to fulfill the PSR-7 specification. diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/composer.json b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/composer.json new file mode 100644 index 00000000..fffdec0b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/composer.json @@ -0,0 +1,48 @@ +{ + "name": "nyholm/psr7", + "description": "A fast PHP7 implementation of PSR-7", + "license": "MIT", + "keywords": ["psr-7", "psr-17"], + "homepage": "https://tnyholm.se", + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0", + "php-http/message-factory": "^1.0", + "psr/http-factory": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || 8.5 || 9.4", + "php-http/psr7-integration-tests": "^1.0", + "http-interop/http-factory-tests": "^0.9", + "symfony/error-handler": "^4.4" + }, + "provide": { + "psr/http-message-implementation": "1.0", + "psr/http-factory-implementation": "1.0" + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\Nyholm\\Psr7\\": "tests/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/HttplugFactory.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/HttplugFactory.php new file mode 100644 index 00000000..4cf8e27e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/HttplugFactory.php @@ -0,0 +1,45 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class HttplugFactory implements MessageFactory, StreamFactory, UriFactory +{ + public function createRequest($method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1'): RequestInterface + { + return new Request($method, $uri, $headers, $body, $protocolVersion); + } + + public function createResponse($statusCode = 200, $reasonPhrase = null, array $headers = [], $body = null, $version = '1.1'): ResponseInterface + { + return new Response((int) $statusCode, $headers, $body, $version, $reasonPhrase); + } + + public function createStream($body = null): StreamInterface + { + return Stream::create($body ?? ''); + } + + public function createUri($uri = ''): UriInterface + { + if ($uri instanceof UriInterface) { + return $uri; + } + + return new Uri($uri); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/Psr17Factory.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/Psr17Factory.php new file mode 100644 index 00000000..440bec34 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Factory/Psr17Factory.php @@ -0,0 +1,78 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class Psr17Factory implements RequestFactoryInterface, ResponseFactoryInterface, ServerRequestFactoryInterface, StreamFactoryInterface, UploadedFileFactoryInterface, UriFactoryInterface +{ + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } + + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface + { + if (2 > \func_num_args()) { + // This will make the Response class to use a custom reasonPhrase + $reasonPhrase = null; + } + + return new Response($code, [], null, '1.1', $reasonPhrase); + } + + public function createStream(string $content = ''): StreamInterface + { + return Stream::create($content); + } + + public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface + { + if ('' === $filename) { + throw new \RuntimeException('Path cannot be empty'); + } + + if (false === $resource = @\fopen($filename, $mode)) { + if ('' === $mode || false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], true)) { + throw new \InvalidArgumentException(\sprintf('The mode "%s" is invalid.', $mode)); + } + + throw new \RuntimeException(\sprintf('The file "%s" cannot be opened: %s', $filename, \error_get_last()['message'] ?? '')); + } + + return Stream::create($resource); + } + + public function createStreamFromResource($resource): StreamInterface + { + return Stream::create($resource); + } + + public function createUploadedFile(StreamInterface $stream, int $size = null, int $error = \UPLOAD_ERR_OK, string $clientFilename = null, string $clientMediaType = null): UploadedFileInterface + { + if (null === $size) { + $size = $stream->getSize(); + } + + return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); + } + + public function createUri(string $uri = ''): UriInterface + { + return new Uri($uri); + } + + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface + { + return new ServerRequest($method, $uri, [], null, '1.1', $serverParams); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/MessageTrait.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/MessageTrait.php new file mode 100644 index 00000000..595258bb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/MessageTrait.php @@ -0,0 +1,207 @@ + + * @author Martijn van der Ven + * + * @internal should not be used outside of Nyholm/Psr7 as it does not fall under our BC promise + */ +trait MessageTrait +{ + /** @var array Map of all registered headers, as original name => array of values */ + private $headers = []; + + /** @var array Map of lowercase header name => original name at registration */ + private $headerNames = []; + + /** @var string */ + private $protocol = '1.1'; + + /** @var StreamInterface|null */ + private $stream; + + public function getProtocolVersion(): string + { + return $this->protocol; + } + + public function withProtocolVersion($version): self + { + if ($this->protocol === $version) { + return $this; + } + + $new = clone $this; + $new->protocol = $version; + + return $new; + } + + public function getHeaders(): array + { + return $this->headers; + } + + public function hasHeader($header): bool + { + return isset($this->headerNames[\strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')]); + } + + public function getHeader($header): array + { + $header = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + if (!isset($this->headerNames[$header])) { + return []; + } + + $header = $this->headerNames[$header]; + + return $this->headers[$header]; + } + + public function getHeaderLine($header): string + { + return \implode(', ', $this->getHeader($header)); + } + + public function withHeader($header, $value): self + { + $value = $this->validateAndTrimHeader($header, $value); + $normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + unset($new->headers[$new->headerNames[$normalized]]); + } + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + + return $new; + } + + public function withAddedHeader($header, $value): self + { + if (!\is_string($header) || '' === $header) { + throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string.'); + } + + $new = clone $this; + $new->setHeaders([$header => $value]); + + return $new; + } + + public function withoutHeader($header): self + { + $normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + if (!isset($this->headerNames[$normalized])) { + return $this; + } + + $header = $this->headerNames[$normalized]; + $new = clone $this; + unset($new->headers[$header], $new->headerNames[$normalized]); + + return $new; + } + + public function getBody(): StreamInterface + { + if (null === $this->stream) { + $this->stream = Stream::create(''); + } + + return $this->stream; + } + + public function withBody(StreamInterface $body): self + { + if ($body === $this->stream) { + return $this; + } + + $new = clone $this; + $new->stream = $body; + + return $new; + } + + private function setHeaders(array $headers): void + { + foreach ($headers as $header => $value) { + if (\is_int($header)) { + // If a header name was set to a numeric string, PHP will cast the key to an int. + // We must cast it back to a string in order to comply with validation. + $header = (string) $header; + } + $value = $this->validateAndTrimHeader($header, $value); + $normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + if (isset($this->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $this->headers[$header] = \array_merge($this->headers[$header], $value); + } else { + $this->headerNames[$normalized] = $header; + $this->headers[$header] = $value; + } + } + } + + /** + * Make sure the header complies with RFC 7230. + * + * Header names must be a non-empty string consisting of token characters. + * + * Header values must be strings consisting of visible characters with all optional + * leading and trailing whitespace stripped. This method will always strip such + * optional whitespace. Note that the method does not allow folding whitespace within + * the values as this was deprecated for almost all instances by the RFC. + * + * header-field = field-name ":" OWS field-value OWS + * field-name = 1*( "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" + * / "_" / "`" / "|" / "~" / %x30-39 / ( %x41-5A / %x61-7A ) ) + * OWS = *( SP / HTAB ) + * field-value = *( ( %x21-7E / %x80-FF ) [ 1*( SP / HTAB ) ( %x21-7E / %x80-FF ) ] ) + * + * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 + */ + private function validateAndTrimHeader($header, $values): array + { + if (!\is_string($header) || 1 !== \preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@", $header)) { + throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string.'); + } + + if (!\is_array($values)) { + // This is simple, just one value. + if ((!\is_numeric($values) && !\is_string($values)) || 1 !== \preg_match("@^[ \t\x21-\x7E\x80-\xFF]*$@", (string) $values)) { + throw new \InvalidArgumentException('Header values must be RFC 7230 compatible strings.'); + } + + return [\trim((string) $values, " \t")]; + } + + if (empty($values)) { + throw new \InvalidArgumentException('Header values must be a string or an array of strings, empty array given.'); + } + + // Assert Non empty array + $returnValues = []; + foreach ($values as $v) { + if ((!\is_numeric($v) && !\is_string($v)) || 1 !== \preg_match("@^[ \t\x21-\x7E\x80-\xFF]*$@", (string) $v)) { + throw new \InvalidArgumentException('Header values must be RFC 7230 compatible strings.'); + } + + $returnValues[] = \trim((string) $v, " \t"); + } + + return $returnValues; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Request.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Request.php new file mode 100644 index 00000000..d50744ee --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Request.php @@ -0,0 +1,47 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class Request implements RequestInterface +{ + use MessageTrait; + use RequestTrait; + + /** + * @param string $method HTTP method + * @param string|UriInterface $uri URI + * @param array $headers Request headers + * @param string|resource|StreamInterface|null $body Request body + * @param string $version Protocol version + */ + public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1') + { + if (!($uri instanceof UriInterface)) { + $uri = new Uri($uri); + } + + $this->method = $method; + $this->uri = $uri; + $this->setHeaders($headers); + $this->protocol = $version; + + if (!$this->hasHeader('Host')) { + $this->updateHostFromUri(); + } + + // If we got no body, defer initialization of the stream until Request::getBody() + if ('' !== $body && null !== $body) { + $this->stream = Stream::create($body); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/RequestTrait.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/RequestTrait.php new file mode 100644 index 00000000..f39993a1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/RequestTrait.php @@ -0,0 +1,113 @@ + + * @author Martijn van der Ven + * + * @internal should not be used outside of Nyholm/Psr7 as it does not fall under our BC promise + */ +trait RequestTrait +{ + /** @var string */ + private $method; + + /** @var string|null */ + private $requestTarget; + + /** @var UriInterface|null */ + private $uri; + + public function getRequestTarget(): string + { + if (null !== $this->requestTarget) { + return $this->requestTarget; + } + + if ('' === $target = $this->uri->getPath()) { + $target = '/'; + } + if ('' !== $this->uri->getQuery()) { + $target .= '?' . $this->uri->getQuery(); + } + + return $target; + } + + public function withRequestTarget($requestTarget): self + { + if (\preg_match('#\s#', $requestTarget)) { + throw new \InvalidArgumentException('Invalid request target provided; cannot contain whitespace'); + } + + $new = clone $this; + $new->requestTarget = $requestTarget; + + return $new; + } + + public function getMethod(): string + { + return $this->method; + } + + public function withMethod($method): self + { + if (!\is_string($method)) { + throw new \InvalidArgumentException('Method must be a string'); + } + + $new = clone $this; + $new->method = $method; + + return $new; + } + + public function getUri(): UriInterface + { + return $this->uri; + } + + public function withUri(UriInterface $uri, $preserveHost = false): self + { + if ($uri === $this->uri) { + return $this; + } + + $new = clone $this; + $new->uri = $uri; + + if (!$preserveHost || !$this->hasHeader('Host')) { + $new->updateHostFromUri(); + } + + return $new; + } + + private function updateHostFromUri(): void + { + if ('' === $host = $this->uri->getHost()) { + return; + } + + if (null !== ($port = $this->uri->getPort())) { + $host .= ':' . $port; + } + + if (isset($this->headerNames['host'])) { + $header = $this->headerNames['host']; + } else { + $this->headerNames['host'] = $header = 'Host'; + } + + // Ensure Host is the first header. + // See: http://tools.ietf.org/html/rfc7230#section-5.4 + $this->headers = [$header => [$host]] + $this->headers; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Response.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Response.php new file mode 100644 index 00000000..9a26d2cb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Response.php @@ -0,0 +1,90 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class Response implements ResponseInterface +{ + use MessageTrait; + + /** @var array Map of standard HTTP status code/reason phrases */ + private const PHRASES = [ + 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', + 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', + 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', + 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', + 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 511 => 'Network Authentication Required', + ]; + + /** @var string */ + private $reasonPhrase = ''; + + /** @var int */ + private $statusCode; + + /** + * @param int $status Status code + * @param array $headers Response headers + * @param string|resource|StreamInterface|null $body Response body + * @param string $version Protocol version + * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) + */ + public function __construct(int $status = 200, array $headers = [], $body = null, string $version = '1.1', string $reason = null) + { + // If we got no body, defer initialization of the stream until Response::getBody() + if ('' !== $body && null !== $body) { + $this->stream = Stream::create($body); + } + + $this->statusCode = $status; + $this->setHeaders($headers); + if (null === $reason && isset(self::PHRASES[$this->statusCode])) { + $this->reasonPhrase = self::PHRASES[$status]; + } else { + $this->reasonPhrase = $reason ?? ''; + } + + $this->protocol = $version; + } + + public function getStatusCode(): int + { + return $this->statusCode; + } + + public function getReasonPhrase(): string + { + return $this->reasonPhrase; + } + + public function withStatus($code, $reasonPhrase = ''): self + { + if (!\is_int($code) && !\is_string($code)) { + throw new \InvalidArgumentException('Status code has to be an integer'); + } + + $code = (int) $code; + if ($code < 100 || $code > 599) { + throw new \InvalidArgumentException(\sprintf('Status code has to be an integer between 100 and 599. A status code of %d was given', $code)); + } + + $new = clone $this; + $new->statusCode = $code; + if ((null === $reasonPhrase || '' === $reasonPhrase) && isset(self::PHRASES[$new->statusCode])) { + $reasonPhrase = self::PHRASES[$new->statusCode]; + } + $new->reasonPhrase = $reasonPhrase; + + return $new; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/ServerRequest.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/ServerRequest.php new file mode 100644 index 00000000..bde46cd6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/ServerRequest.php @@ -0,0 +1,167 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class ServerRequest implements ServerRequestInterface +{ + use MessageTrait; + use RequestTrait; + + /** @var array */ + private $attributes = []; + + /** @var array */ + private $cookieParams = []; + + /** @var array|object|null */ + private $parsedBody; + + /** @var array */ + private $queryParams = []; + + /** @var array */ + private $serverParams; + + /** @var UploadedFileInterface[] */ + private $uploadedFiles = []; + + /** + * @param string $method HTTP method + * @param string|UriInterface $uri URI + * @param array $headers Request headers + * @param string|resource|StreamInterface|null $body Request body + * @param string $version Protocol version + * @param array $serverParams Typically the $_SERVER superglobal + */ + public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1', array $serverParams = []) + { + $this->serverParams = $serverParams; + + if (!($uri instanceof UriInterface)) { + $uri = new Uri($uri); + } + + $this->method = $method; + $this->uri = $uri; + $this->setHeaders($headers); + $this->protocol = $version; + + if (!$this->hasHeader('Host')) { + $this->updateHostFromUri(); + } + + // If we got no body, defer initialization of the stream until ServerRequest::getBody() + if ('' !== $body && null !== $body) { + $this->stream = Stream::create($body); + } + } + + public function getServerParams(): array + { + return $this->serverParams; + } + + public function getUploadedFiles(): array + { + return $this->uploadedFiles; + } + + public function withUploadedFiles(array $uploadedFiles) + { + $new = clone $this; + $new->uploadedFiles = $uploadedFiles; + + return $new; + } + + public function getCookieParams(): array + { + return $this->cookieParams; + } + + public function withCookieParams(array $cookies) + { + $new = clone $this; + $new->cookieParams = $cookies; + + return $new; + } + + public function getQueryParams(): array + { + return $this->queryParams; + } + + public function withQueryParams(array $query) + { + $new = clone $this; + $new->queryParams = $query; + + return $new; + } + + public function getParsedBody() + { + return $this->parsedBody; + } + + public function withParsedBody($data) + { + if (!\is_array($data) && !\is_object($data) && null !== $data) { + throw new \InvalidArgumentException('First parameter to withParsedBody MUST be object, array or null'); + } + + $new = clone $this; + $new->parsedBody = $data; + + return $new; + } + + public function getAttributes(): array + { + return $this->attributes; + } + + /** + * @return mixed + */ + public function getAttribute($attribute, $default = null) + { + if (false === \array_key_exists($attribute, $this->attributes)) { + return $default; + } + + return $this->attributes[$attribute]; + } + + public function withAttribute($attribute, $value): self + { + $new = clone $this; + $new->attributes[$attribute] = $value; + + return $new; + } + + public function withoutAttribute($attribute): self + { + if (false === \array_key_exists($attribute, $this->attributes)) { + return $this; + } + + $new = clone $this; + unset($new->attributes[$attribute]); + + return $new; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Stream.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Stream.php new file mode 100644 index 00000000..71515e5c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Stream.php @@ -0,0 +1,306 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class Stream implements StreamInterface +{ + /** @var resource|null A resource reference */ + private $stream; + + /** @var bool */ + private $seekable; + + /** @var bool */ + private $readable; + + /** @var bool */ + private $writable; + + /** @var array|mixed|void|bool|null */ + private $uri; + + /** @var int|null */ + private $size; + + /** @var array Hash of readable and writable stream types */ + private const READ_WRITE_HASH = [ + 'read' => [ + 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, + 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, + 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a+' => true, + ], + 'write' => [ + 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, + 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, + 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true, + ], + ]; + + private function __construct() + { + } + + /** + * Creates a new PSR-7 stream. + * + * @param string|resource|StreamInterface $body + * + * @throws \InvalidArgumentException + */ + public static function create($body = ''): StreamInterface + { + if ($body instanceof StreamInterface) { + return $body; + } + + if (\is_string($body)) { + $resource = \fopen('php://temp', 'rw+'); + \fwrite($resource, $body); + $body = $resource; + } + + if (\is_resource($body)) { + $new = new self(); + $new->stream = $body; + $meta = \stream_get_meta_data($new->stream); + $new->seekable = $meta['seekable'] && 0 === \fseek($new->stream, 0, \SEEK_CUR); + $new->readable = isset(self::READ_WRITE_HASH['read'][$meta['mode']]); + $new->writable = isset(self::READ_WRITE_HASH['write'][$meta['mode']]); + + return $new; + } + + throw new \InvalidArgumentException('First argument to Stream::create() must be a string, resource or StreamInterface.'); + } + + /** + * Closes the stream when the destructed. + */ + public function __destruct() + { + $this->close(); + } + + /** + * @return string + */ + public function __toString() + { + try { + if ($this->isSeekable()) { + $this->seek(0); + } + + return $this->getContents(); + } catch (\Throwable $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + + if (\is_array($errorHandler = \set_error_handler('var_dump'))) { + $errorHandler = $errorHandler[0] ?? null; + } + \restore_error_handler(); + + if ($e instanceof \Error || $errorHandler instanceof SymfonyErrorHandler || $errorHandler instanceof SymfonyLegacyErrorHandler) { + return \trigger_error((string) $e, \E_USER_ERROR); + } + + return ''; + } + } + + public function close(): void + { + if (isset($this->stream)) { + if (\is_resource($this->stream)) { + \fclose($this->stream); + } + $this->detach(); + } + } + + public function detach() + { + if (!isset($this->stream)) { + return null; + } + + $result = $this->stream; + unset($this->stream); + $this->size = $this->uri = null; + $this->readable = $this->writable = $this->seekable = false; + + return $result; + } + + private function getUri() + { + if (false !== $this->uri) { + $this->uri = $this->getMetadata('uri') ?? false; + } + + return $this->uri; + } + + public function getSize(): ?int + { + if (null !== $this->size) { + return $this->size; + } + + if (!isset($this->stream)) { + return null; + } + + // Clear the stat cache if the stream has a URI + if ($uri = $this->getUri()) { + \clearstatcache(true, $uri); + } + + $stats = \fstat($this->stream); + if (isset($stats['size'])) { + $this->size = $stats['size']; + + return $this->size; + } + + return null; + } + + public function tell(): int + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + + if (false === $result = @\ftell($this->stream)) { + throw new \RuntimeException('Unable to determine stream position: ' . (\error_get_last()['message'] ?? '')); + } + + return $result; + } + + public function eof(): bool + { + return !isset($this->stream) || \feof($this->stream); + } + + public function isSeekable(): bool + { + return $this->seekable; + } + + public function seek($offset, $whence = \SEEK_SET): void + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + + if (!$this->seekable) { + throw new \RuntimeException('Stream is not seekable'); + } + + if (-1 === \fseek($this->stream, $offset, $whence)) { + throw new \RuntimeException('Unable to seek to stream position "' . $offset . '" with whence ' . \var_export($whence, true)); + } + } + + public function rewind(): void + { + $this->seek(0); + } + + public function isWritable(): bool + { + return $this->writable; + } + + public function write($string): int + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + + if (!$this->writable) { + throw new \RuntimeException('Cannot write to a non-writable stream'); + } + + // We can't know the size after writing anything + $this->size = null; + + if (false === $result = @\fwrite($this->stream, $string)) { + throw new \RuntimeException('Unable to write to stream: ' . (\error_get_last()['message'] ?? '')); + } + + return $result; + } + + public function isReadable(): bool + { + return $this->readable; + } + + public function read($length): string + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + + if (!$this->readable) { + throw new \RuntimeException('Cannot read from non-readable stream'); + } + + if (false === $result = @\fread($this->stream, $length)) { + throw new \RuntimeException('Unable to read from stream: ' . (\error_get_last()['message'] ?? '')); + } + + return $result; + } + + public function getContents(): string + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + + if (false === $contents = @\stream_get_contents($this->stream)) { + throw new \RuntimeException('Unable to read stream contents: ' . (\error_get_last()['message'] ?? '')); + } + + return $contents; + } + + /** + * @return mixed + */ + public function getMetadata($key = null) + { + if (!isset($this->stream)) { + return $key ? null : []; + } + + $meta = \stream_get_meta_data($this->stream); + + if (null === $key) { + return $meta; + } + + return $meta[$key] ?? null; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/UploadedFile.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/UploadedFile.php new file mode 100644 index 00000000..bf47b781 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/UploadedFile.php @@ -0,0 +1,179 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class UploadedFile implements UploadedFileInterface +{ + /** @var array */ + private const ERRORS = [ + \UPLOAD_ERR_OK => 1, + \UPLOAD_ERR_INI_SIZE => 1, + \UPLOAD_ERR_FORM_SIZE => 1, + \UPLOAD_ERR_PARTIAL => 1, + \UPLOAD_ERR_NO_FILE => 1, + \UPLOAD_ERR_NO_TMP_DIR => 1, + \UPLOAD_ERR_CANT_WRITE => 1, + \UPLOAD_ERR_EXTENSION => 1, + ]; + + /** @var string */ + private $clientFilename; + + /** @var string */ + private $clientMediaType; + + /** @var int */ + private $error; + + /** @var string|null */ + private $file; + + /** @var bool */ + private $moved = false; + + /** @var int */ + private $size; + + /** @var StreamInterface|null */ + private $stream; + + /** + * @param StreamInterface|string|resource $streamOrFile + * @param int $size + * @param int $errorStatus + * @param string|null $clientFilename + * @param string|null $clientMediaType + */ + public function __construct($streamOrFile, $size, $errorStatus, $clientFilename = null, $clientMediaType = null) + { + if (false === \is_int($errorStatus) || !isset(self::ERRORS[$errorStatus])) { + throw new \InvalidArgumentException('Upload file error status must be an integer value and one of the "UPLOAD_ERR_*" constants.'); + } + + if (false === \is_int($size)) { + throw new \InvalidArgumentException('Upload file size must be an integer'); + } + + if (null !== $clientFilename && !\is_string($clientFilename)) { + throw new \InvalidArgumentException('Upload file client filename must be a string or null'); + } + + if (null !== $clientMediaType && !\is_string($clientMediaType)) { + throw new \InvalidArgumentException('Upload file client media type must be a string or null'); + } + + $this->error = $errorStatus; + $this->size = $size; + $this->clientFilename = $clientFilename; + $this->clientMediaType = $clientMediaType; + + if (\UPLOAD_ERR_OK === $this->error) { + // Depending on the value set file or stream variable. + if (\is_string($streamOrFile) && '' !== $streamOrFile) { + $this->file = $streamOrFile; + } elseif (\is_resource($streamOrFile)) { + $this->stream = Stream::create($streamOrFile); + } elseif ($streamOrFile instanceof StreamInterface) { + $this->stream = $streamOrFile; + } else { + throw new \InvalidArgumentException('Invalid stream or file provided for UploadedFile'); + } + } + } + + /** + * @throws \RuntimeException if is moved or not ok + */ + private function validateActive(): void + { + if (\UPLOAD_ERR_OK !== $this->error) { + throw new \RuntimeException('Cannot retrieve stream due to upload error'); + } + + if ($this->moved) { + throw new \RuntimeException('Cannot retrieve stream after it has already been moved'); + } + } + + public function getStream(): StreamInterface + { + $this->validateActive(); + + if ($this->stream instanceof StreamInterface) { + return $this->stream; + } + + if (false === $resource = @\fopen($this->file, 'r')) { + throw new \RuntimeException(\sprintf('The file "%s" cannot be opened: %s', $this->file, \error_get_last()['message'] ?? '')); + } + + return Stream::create($resource); + } + + public function moveTo($targetPath): void + { + $this->validateActive(); + + if (!\is_string($targetPath) || '' === $targetPath) { + throw new \InvalidArgumentException('Invalid path provided for move operation; must be a non-empty string'); + } + + if (null !== $this->file) { + $this->moved = 'cli' === \PHP_SAPI ? @\rename($this->file, $targetPath) : @\move_uploaded_file($this->file, $targetPath); + + if (false === $this->moved) { + throw new \RuntimeException(\sprintf('Uploaded file could not be moved to "%s": %s', $targetPath, \error_get_last()['message'] ?? '')); + } + } else { + $stream = $this->getStream(); + if ($stream->isSeekable()) { + $stream->rewind(); + } + + if (false === $resource = @\fopen($targetPath, 'w')) { + throw new \RuntimeException(\sprintf('The file "%s" cannot be opened: %s', $targetPath, \error_get_last()['message'] ?? '')); + } + + $dest = Stream::create($resource); + + while (!$stream->eof()) { + if (!$dest->write($stream->read(1048576))) { + break; + } + } + + $this->moved = true; + } + } + + public function getSize(): int + { + return $this->size; + } + + public function getError(): int + { + return $this->error; + } + + public function getClientFilename(): ?string + { + return $this->clientFilename; + } + + public function getClientMediaType(): ?string + { + return $this->clientMediaType; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Uri.php b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Uri.php new file mode 100644 index 00000000..13fbf72e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/nyholm/psr7/src/Uri.php @@ -0,0 +1,312 @@ + + * @author Martijn van der Ven + * + * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md + */ +class Uri implements UriInterface +{ + private const SCHEMES = ['http' => 80, 'https' => 443]; + + private const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; + + private const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; + + /** @var string Uri scheme. */ + private $scheme = ''; + + /** @var string Uri user info. */ + private $userInfo = ''; + + /** @var string Uri host. */ + private $host = ''; + + /** @var int|null Uri port. */ + private $port; + + /** @var string Uri path. */ + private $path = ''; + + /** @var string Uri query string. */ + private $query = ''; + + /** @var string Uri fragment. */ + private $fragment = ''; + + public function __construct(string $uri = '') + { + if ('' !== $uri) { + if (false === $parts = \parse_url($uri)) { + throw new \InvalidArgumentException(\sprintf('Unable to parse URI: "%s"', $uri)); + } + + // Apply parse_url parts to a URI. + $this->scheme = isset($parts['scheme']) ? \strtr($parts['scheme'], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') : ''; + $this->userInfo = $parts['user'] ?? ''; + $this->host = isset($parts['host']) ? \strtr($parts['host'], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') : ''; + $this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null; + $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; + $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; + $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; + if (isset($parts['pass'])) { + $this->userInfo .= ':' . $parts['pass']; + } + } + } + + public function __toString(): string + { + return self::createUriString($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment); + } + + public function getScheme(): string + { + return $this->scheme; + } + + public function getAuthority(): string + { + if ('' === $this->host) { + return ''; + } + + $authority = $this->host; + if ('' !== $this->userInfo) { + $authority = $this->userInfo . '@' . $authority; + } + + if (null !== $this->port) { + $authority .= ':' . $this->port; + } + + return $authority; + } + + public function getUserInfo(): string + { + return $this->userInfo; + } + + public function getHost(): string + { + return $this->host; + } + + public function getPort(): ?int + { + return $this->port; + } + + public function getPath(): string + { + return $this->path; + } + + public function getQuery(): string + { + return $this->query; + } + + public function getFragment(): string + { + return $this->fragment; + } + + public function withScheme($scheme): self + { + if (!\is_string($scheme)) { + throw new \InvalidArgumentException('Scheme must be a string'); + } + + if ($this->scheme === $scheme = \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')) { + return $this; + } + + $new = clone $this; + $new->scheme = $scheme; + $new->port = $new->filterPort($new->port); + + return $new; + } + + public function withUserInfo($user, $password = null): self + { + $info = $user; + if (null !== $password && '' !== $password) { + $info .= ':' . $password; + } + + if ($this->userInfo === $info) { + return $this; + } + + $new = clone $this; + $new->userInfo = $info; + + return $new; + } + + public function withHost($host): self + { + if (!\is_string($host)) { + throw new \InvalidArgumentException('Host must be a string'); + } + + if ($this->host === $host = \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')) { + return $this; + } + + $new = clone $this; + $new->host = $host; + + return $new; + } + + public function withPort($port): self + { + if ($this->port === $port = $this->filterPort($port)) { + return $this; + } + + $new = clone $this; + $new->port = $port; + + return $new; + } + + public function withPath($path): self + { + if ($this->path === $path = $this->filterPath($path)) { + return $this; + } + + $new = clone $this; + $new->path = $path; + + return $new; + } + + public function withQuery($query): self + { + if ($this->query === $query = $this->filterQueryAndFragment($query)) { + return $this; + } + + $new = clone $this; + $new->query = $query; + + return $new; + } + + public function withFragment($fragment): self + { + if ($this->fragment === $fragment = $this->filterQueryAndFragment($fragment)) { + return $this; + } + + $new = clone $this; + $new->fragment = $fragment; + + return $new; + } + + /** + * Create a URI string from its various parts. + */ + private static function createUriString(string $scheme, string $authority, string $path, string $query, string $fragment): string + { + $uri = ''; + if ('' !== $scheme) { + $uri .= $scheme . ':'; + } + + if ('' !== $authority) { + $uri .= '//' . $authority; + } + + if ('' !== $path) { + if ('/' !== $path[0]) { + if ('' !== $authority) { + // If the path is rootless and an authority is present, the path MUST be prefixed by "/" + $path = '/' . $path; + } + } elseif (isset($path[1]) && '/' === $path[1]) { + if ('' === $authority) { + // If the path is starting with more than one "/" and no authority is present, the + // starting slashes MUST be reduced to one. + $path = '/' . \ltrim($path, '/'); + } + } + + $uri .= $path; + } + + if ('' !== $query) { + $uri .= '?' . $query; + } + + if ('' !== $fragment) { + $uri .= '#' . $fragment; + } + + return $uri; + } + + /** + * Is a given port non-standard for the current scheme? + */ + private static function isNonStandardPort(string $scheme, int $port): bool + { + return !isset(self::SCHEMES[$scheme]) || $port !== self::SCHEMES[$scheme]; + } + + private function filterPort($port): ?int + { + if (null === $port) { + return null; + } + + $port = (int) $port; + if (0 > $port || 0xffff < $port) { + throw new \InvalidArgumentException(\sprintf('Invalid port: %d. Must be between 0 and 65535', $port)); + } + + return self::isNonStandardPort($this->scheme, $port) ? $port : null; + } + + private function filterPath($path): string + { + if (!\is_string($path)) { + throw new \InvalidArgumentException('Path must be a string'); + } + + return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', [__CLASS__, 'rawurlencodeMatchZero'], $path); + } + + private function filterQueryAndFragment($str): string + { + if (!\is_string($str)) { + throw new \InvalidArgumentException('Query and fragment must be a string'); + } + + return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', [__CLASS__, 'rawurlencodeMatchZero'], $str); + } + + private static function rawurlencodeMatchZero(array $match): string + { + return \rawurlencode($match[0]); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/CHANGELOG.md b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/CHANGELOG.md new file mode 100644 index 00000000..4711924c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/CHANGELOG.md @@ -0,0 +1,65 @@ +# Change Log + + +## 1.0.2 - 2015-12-19 + +### Added + +- Request and Response factory binding types to Puli + + +## 1.0.1 - 2015-12-17 + +### Added + +- Puli configuration and binding types + + +## 1.0.0 - 2015-12-15 + +### Added + +- Response Factory in order to be reused in Message and Server Message factories +- Request Factory + +### Changed + +- Message Factory extends Request and Response factories + + +## 1.0.0-RC1 - 2015-12-14 + +### Added + +- CS check + +### Changed + +- RuntimeException is thrown when the StreamFactory cannot write to the underlying stream + + +## 0.3.0 - 2015-11-16 + +### Removed + +- Client Context Factory +- Factory Awares and Templates + + +## 0.2.0 - 2015-11-16 + +### Changed + +- Reordered the parameters when creating a message to have the protocol last, +as its the least likely to need to be changed. + + +## 0.1.0 - 2015-06-01 + +### Added + +- Initial release + +### Changed + +- Helpers are renamed to templates diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/LICENSE b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/LICENSE new file mode 100644 index 00000000..8e2c4a0b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 PHP HTTP Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/README.md b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/README.md new file mode 100644 index 00000000..4654495a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/README.md @@ -0,0 +1,36 @@ +# PSR-7 Message Factory + +[![Latest Version](https://img.shields.io/github/release/php-http/message-factory.svg?style=flat-square)](https://github.com/php-http/message-factory/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/message-factory.svg?style=flat-square)](https://packagist.org/packages/php-http/message-factory) + +**Factory interfaces for PSR-7 HTTP Message.** + + +## Install + +Via Composer + +``` bash +$ composer require php-http/message-factory +``` + + +## Documentation + +Please see the [official documentation](http://php-http.readthedocs.org/en/latest/message-factory/). + + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details. + + +## Security + +If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org). + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/composer.json b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/composer.json new file mode 100644 index 00000000..7c72febe --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/composer.json @@ -0,0 +1,27 @@ +{ + "name": "php-http/message-factory", + "description": "Factory interfaces for PSR-7 HTTP Message", + "license": "MIT", + "keywords": ["http", "factory", "message", "stream", "uri"], + "homepage": "http://php-http.org", + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/puli.json b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/puli.json new file mode 100644 index 00000000..08d37627 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/puli.json @@ -0,0 +1,43 @@ +{ + "version": "1.0", + "binding-types": { + "Http\\Message\\MessageFactory": { + "description": "PSR-7 Message Factory", + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\RequestFactory": { + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\ResponseFactory": { + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\StreamFactory": { + "description": "PSR-7 Stream Factory", + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\UriFactory": { + "description": "PSR-7 URI Factory", + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/MessageFactory.php b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/MessageFactory.php new file mode 100644 index 00000000..965aaa80 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/MessageFactory.php @@ -0,0 +1,12 @@ + + */ +interface MessageFactory extends RequestFactory, ResponseFactory +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/RequestFactory.php b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/RequestFactory.php new file mode 100644 index 00000000..624e82f3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/RequestFactory.php @@ -0,0 +1,34 @@ + + */ +interface RequestFactory +{ + /** + * Creates a new PSR-7 request. + * + * @param string $method + * @param string|UriInterface $uri + * @param array $headers + * @param resource|string|StreamInterface|null $body + * @param string $protocolVersion + * + * @return RequestInterface + */ + public function createRequest( + $method, + $uri, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/ResponseFactory.php b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/ResponseFactory.php new file mode 100644 index 00000000..2411ed3a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/ResponseFactory.php @@ -0,0 +1,35 @@ + + */ +interface ResponseFactory +{ + /** + * Creates a new PSR-7 response. + * + * @param int $statusCode + * @param string|null $reasonPhrase + * @param array $headers + * @param resource|string|StreamInterface|null $body + * @param string $protocolVersion + * + * @return ResponseInterface + */ + public function createResponse( + $statusCode = 200, + $reasonPhrase = null, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/StreamFactory.php b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/StreamFactory.php new file mode 100644 index 00000000..327a902f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/StreamFactory.php @@ -0,0 +1,25 @@ + + */ +interface StreamFactory +{ + /** + * Creates a new PSR-7 stream. + * + * @param string|resource|StreamInterface|null $body + * + * @return StreamInterface + * + * @throws \InvalidArgumentException If the stream body is invalid. + * @throws \RuntimeException If creating the stream from $body fails. + */ + public function createStream($body = null); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/UriFactory.php b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/UriFactory.php new file mode 100644 index 00000000..f05e6252 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/php-http/message-factory/src/UriFactory.php @@ -0,0 +1,24 @@ + + */ +interface UriFactory +{ + /** + * Creates an PSR-7 URI. + * + * @param string|UriInterface $uri + * + * @return UriInterface + * + * @throws \InvalidArgumentException If the $uri argument can not be converted into a valid URI. + */ + public function createUri($uri); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-client/CHANGELOG.md b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/CHANGELOG.md new file mode 100644 index 00000000..e2dc25f5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.1 + +Allow installation with PHP 8. No code changes. + +## 1.0.0 + +First stable release. No changes since 0.3.0. + +## 0.3.0 + +Added Interface suffix on exceptions + +## 0.2.0 + +All exceptions are in `Psr\Http\Client` namespace + +## 0.1.0 + +First release diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-client/LICENSE b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/LICENSE new file mode 100644 index 00000000..cd5e0020 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-client/README.md b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/README.md new file mode 100644 index 00000000..6876b840 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/README.md @@ -0,0 +1,12 @@ +HTTP Client +=========== + +This repository holds all the common code related to [PSR-18 (HTTP Client)][psr-url]. + +Note that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: http://www.php-fig.org/psr/psr-18 +[package-url]: https://packagist.org/packages/psr/http-client +[implementation-url]: https://packagist.org/providers/psr/http-client-implementation diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-client/composer.json b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/composer.json new file mode 100644 index 00000000..c195f8ff --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/composer.json @@ -0,0 +1,27 @@ +{ + "name": "psr/http-client", + "description": "Common interface for HTTP clients", + "keywords": ["psr", "psr-18", "http", "http-client"], + "homepage": "https://github.com/php-fig/http-client", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-client/src/ClientExceptionInterface.php b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/src/ClientExceptionInterface.php new file mode 100644 index 00000000..aa0b9cf1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-client/src/ClientExceptionInterface.php @@ -0,0 +1,10 @@ +=7.0.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/RequestFactoryInterface.php b/wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 00000000..cb39a08b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ +=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/MessageInterface.php b/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/MessageInterface.php new file mode 100644 index 00000000..dd46e5ec --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/MessageInterface.php @@ -0,0 +1,187 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return string[][] Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name); + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name); + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name); + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value); + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value); + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader($name); + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/RequestInterface.php b/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/RequestInterface.php new file mode 100644 index 00000000..a96d4fd6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/RequestInterface.php @@ -0,0 +1,129 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return static + */ + public function withQueryParams(array $query); + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return static + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return static + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null); + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return static + */ + public function withAttribute($name, $value); + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return static + */ + public function withoutAttribute($name); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/StreamInterface.php b/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/StreamInterface.php new file mode 100644 index 00000000..f68f3912 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/http-message/src/StreamInterface.php @@ -0,0 +1,158 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return static A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme); + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return static A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null); + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return static A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host); + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return static A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port); + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return static A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path); + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return static A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query); + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return static A new instance with the specified fragment. + */ + public function withFragment($fragment); + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/LICENSE b/wp-content/plugins/wp-webauthn/vendor/psr/log/LICENSE new file mode 100644 index 00000000..474c952b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/AbstractLogger.php b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/AbstractLogger.php new file mode 100644 index 00000000..e02f9daf --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/AbstractLogger.php @@ -0,0 +1,128 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/InvalidArgumentException.php new file mode 100644 index 00000000..67f852d1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/InvalidArgumentException.php @@ -0,0 +1,7 @@ +logger = $logger; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LoggerInterface.php b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LoggerInterface.php new file mode 100644 index 00000000..2206cfde --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/LoggerInterface.php @@ -0,0 +1,125 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + abstract public function log($level, $message, array $context = array()); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/NullLogger.php b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/NullLogger.php new file mode 100644 index 00000000..c8f7293b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/NullLogger.php @@ -0,0 +1,30 @@ +logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + public function log($level, $message, array $context = array()) + { + // noop + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/DummyTest.php b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/DummyTest.php new file mode 100644 index 00000000..9638c110 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/DummyTest.php @@ -0,0 +1,18 @@ + ". + * + * Example ->error('Foo') would yield "error Foo". + * + * @return string[] + */ + abstract public function getLogs(); + + public function testImplements() + { + $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, array('user' => 'Bob')); + $logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + $level.' message of level '.$level.' with context: Bob', + $level.' message of level '.$level.' with context: Bob', + ); + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $logger = $this->getLogger(); + $logger->log('invalid level', 'Foo'); + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('info {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + if (method_exists($this, 'createPartialMock')) { + $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString')); + } else { + $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); + } + $dummy->expects($this->once()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + + $expected = array('warning DUMMY'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $closed = fopen('php://memory', 'r'); + fclose($closed); + + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest), + 'object' => new \DateTime, + 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, + ); + + $this->getLogger()->warning('Crazy context data', $context); + + $expected = array('warning Crazy context data'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->getLogger(); + $logger->warning('Random message', array('exception' => 'oops')); + $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + + $expected = array( + 'warning Random message', + 'critical Uncaught Exception!' + ); + $this->assertEquals($expected, $this->getLogs()); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/TestLogger.php b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/TestLogger.php new file mode 100644 index 00000000..1be32304 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/Psr/Log/Test/TestLogger.php @@ -0,0 +1,147 @@ + $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/README.md b/wp-content/plugins/wp-webauthn/vendor/psr/log/README.md new file mode 100644 index 00000000..a9f20c43 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/README.md @@ -0,0 +1,58 @@ +PSR Log +======= + +This repository holds all interfaces/classes/traits related to +[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). + +Note that this is not a logger of its own. It is merely an interface that +describes a logger. See the specification for more details. + +Installation +------------ + +```bash +composer require psr/log +``` + +Usage +----- + +If you need a logger, you can use the interface like this: + +```php +logger = $logger; + } + + public function doSomething() + { + if ($this->logger) { + $this->logger->info('Doing work'); + } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } + + // do something useful + } +} +``` + +You can then pick one of the implementations of the interface to get a logger. + +If you want to implement the interface, you can require this package and +implement `Psr\Log\LoggerInterface` in your code. Please read the +[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +for details. diff --git a/wp-content/plugins/wp-webauthn/vendor/psr/log/composer.json b/wp-content/plugins/wp-webauthn/vendor/psr/log/composer.json new file mode 100644 index 00000000..ca056953 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/psr/log/composer.json @@ -0,0 +1,26 @@ +{ + "name": "psr/log", + "description": "Common interface for logging libraries", + "keywords": ["psr", "psr-3", "log"], + "homepage": "https://github.com/php-fig/log", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/LICENSE b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/LICENSE new file mode 100644 index 00000000..ae15f590 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2021 Ben Ramsey + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/README.md b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/README.md new file mode 100644 index 00000000..9124dd77 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/README.md @@ -0,0 +1,82 @@ +

ramsey/collection

+ +

+ A PHP library for representing and manipulating collections. +

+ +

+ Source Code + Download Package + PHP Programming Language + Read License + Build Status + Codecov Code Coverage + Psalm Type Coverage +

+ +## About + +ramsey/collection is a PHP library for representing and manipulating collections. + +Much inspiration for this library came from the [Java Collections Framework][java]. + +This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). +By participating in this project and its community, you are expected to +uphold this code. + +## Installation + +Install this package as a dependency using [Composer](https://getcomposer.org). + +``` bash +composer require ramsey/collection +``` + +## Usage + +Examples of how to use this framework can be found in the +[Wiki pages](https://github.com/ramsey/collection/wiki/Examples). + +## Contributing + +Contributions are welcome! Before contributing to this project, familiarize +yourself with [CONTRIBUTING.md](CONTRIBUTING.md). + +To develop this project, you will need [PHP](https://www.php.net) 7.3 or greater +and [Composer](https://getcomposer.org). + +After cloning this repository locally, execute the following commands: + +``` bash +cd /path/to/repository +composer install +``` + +Now, you are ready to develop! + +## Coordinated Disclosure + +Keeping user information safe and secure is a top priority, and we welcome the +contribution of external security researchers. If you believe you've found a +security issue in software that is maintained in this repository, please read +[SECURITY.md][] for instructions on submitting a vulnerability report. + +## ramsey/collection for Enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of ramsey/collection and thousands of other packages are working +with Tidelift to deliver commercial support and maintenance for the open source +packages you use to build your applications. Save time, reduce risk, and improve +code health, while paying the maintainers of the exact packages you use. +[Learn more.](https://tidelift.com/subscription/pkg/packagist-ramsey-collection?utm_source=undefined&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +## Copyright and License + +The ramsey/collection library is copyright © [Ben Ramsey](https://benramsey.com) +and licensed for use under the terms of the +MIT License (MIT). Please see [LICENSE](LICENSE) for more information. + + +[java]: http://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html +[security.md]: https://github.com/ramsey/collection/blob/master/SECURITY.md diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/SECURITY.md b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/SECURITY.md new file mode 100644 index 00000000..b052f3b6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/SECURITY.md @@ -0,0 +1,113 @@ + + +# Vulnerability Disclosure Policy + +Keeping user information safe and secure is a top priority, and we welcome the +contribution of external security researchers. + +## Scope + +If you believe you've found a security issue in software that is maintained in +this repository, we encourage you to notify us. + +| Version | In scope | Source code | +| :-----: | :------: | :---------- | +| latest | ✅ | https://github.com/ramsey/collection | + +## How to Submit a Report + +To submit a vulnerability report, please contact us at . +Your submission will be reviewed and validated by a member of our team. + +## Safe Harbor + +We support safe harbor for security researchers who: + +* Make a good faith effort to avoid privacy violations, destruction of data, and + interruption or degradation of our services. +* Only interact with accounts you own or with explicit permission of the account + holder. If you do encounter Personally Identifiable Information (PII) contact + us immediately, do not proceed with access, and immediately purge any local + information. +* Provide us with a reasonable amount of time to resolve vulnerabilities prior + to any disclosure to the public or a third-party. + +We will consider activities conducted consistent with this policy to constitute +"authorized" conduct and will not pursue civil action or initiate a complaint to +law enforcement. We will help to the extent we can if legal action is initiated +by a third party against you. + +Please submit a report to us before engaging in conduct that may be inconsistent +with or unaddressed by this policy. + +## Preferences + +* Please provide detailed reports with reproducible steps and a clearly defined + impact. +* Include the version number of the vulnerable package in your report +* Social engineering (e.g. phishing, vishing, smishing) is prohibited. + +## Encryption Key for security@ramsey.dev + +For increased privacy when reporting sensitive issues, you may encrypt your +messages using the following key: + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBF+Z9gEBEACbT/pIx8RR0K18t8Z2rDnmEV44YdT7HNsMdq+D6SAlx8UUb6AU +jGIbV9dgBgGNtOLU1pxloaJwL9bWIRbj+X/Qb2WNIP//Vz1Y40ox1dSpfCUrizXx +kb4p58Xml0PsB8dg3b4RDUgKwGC37ne5xmDnigyJPbiB2XJ6Xc46oPCjh86XROTK +wEBB2lY67ClBlSlvC2V9KmbTboRQkLdQDhOaUosMb99zRb0EWqDLaFkZVjY5HI7i +0pTveE6dI12NfHhTwKjZ5pUiAZQGlKA6J1dMjY2unxHZkQj5MlMfrLSyJHZxccdJ +xD94T6OTcTHt/XmMpI2AObpewZDdChDQmcYDZXGfAhFoJmbvXsmLMGXKgzKoZ/ls +RmLsQhh7+/r8E+Pn5r+A6Hh4uAc14ApyEP0ckKeIXw1C6pepHM4E8TEXVr/IA6K/ +z6jlHORixIFX7iNOnfHh+qwOgZw40D6JnBfEzjFi+T2Cy+JzN2uy7I8UnecTMGo3 +5t6astPy6xcH6kZYzFTV7XERR6LIIVyLAiMFd8kF5MbJ8N5ElRFsFHPW+82N2HDX +c60iSaTB85k6R6xd8JIKDiaKE4sSuw2wHFCKq33d/GamYezp1wO+bVUQg88efljC +2JNFyD+vl30josqhw1HcmbE1TP3DlYeIL5jQOlxCMsgai6JtTfHFM/5MYwARAQAB +tBNzZWN1cml0eUByYW1zZXkuZGV2iQJUBBMBCAA+FiEE4drPD+/ofZ570fAYq0bv +vXQCywIFAl+Z9gECGwMFCQeGH4AFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ +q0bvvXQCywIkEA//Qcwv8MtTCy01LHZd9c7VslwhNdXQDYymcTyjcYw8x7O22m4B +3hXE6vqAplFhVxxkqXB2ef0tQuzxhPHNJgkCE4Wq4i+V6qGpaSVHQT2W6DN/NIhL +vS8OdScc6zddmIbIkSrzVVAtjwehFNEIrX3DnbbbK+Iku7vsKT5EclOluIsjlYoX +goW8IeReyDBqOe2H3hoCGw6EA0D/NYV2bJnfy53rXVIyarsXXeOLp7eNEH6Td7aW +PVSrMZJe1t+knrEGnEdrXWzlg4lCJJCtemGv+pKBUomnyISXSdqyoRCCzvQjqyig +2kRebUX8BXPW33p4OXPj9sIboUOjZwormWwqqbFMO+J4TiVCUoEoheI7emPFRcNN +QtPJrjbY1++OznBc0GRpfeUkGoU1cbRl1bnepnFIZMTDLkrVW6I1Y4q8ZVwX3BkE +N81ctFrRpHBlU36EdHvjPQmGtuiL77Qq3fWmMv7yTvK1wHJAXfEb0ZJWHZCbck3w +l0CVq0Z+UUAOM8Rp1N0N8m92xtapav0qCFU9qzf2J5qX6GRmWv+d29wPgFHzDWBm +nnrYYIA4wJLx00U6SMcVBSnNe91B+RfGY5XQhbWPjQQecOGCSDsxaFAq2MeOVJyZ +bIjLYfG9GxoLKr5R7oLRJvZI4nKKBc1Kci/crZbdiSdQhSQGlDz88F1OHeCIdQQQ +EQgAHRYhBOhdAxHd+lus86YQ57Atl5icjAcbBQJfmfdIAAoJELAtl5icjAcbFVcA +/1LqB3ZjsnXDAvvAXZVjSPqofSlpMLeRQP6IM/A9Odq0AQCZrtZc1knOMGEcjppK +Rk+sy/R0Mshy8TDuaZIRgh2Ux7kCDQRfmfYBARAAmchKzzVz7IaEq7PnZDb3szQs +T/+E9F3m39yOpV4fEB1YzObonFakXNT7Gw2tZEx0eitUMqQ/13jjfu3UdzlKl2bR +qA8LrSQRhB+PTC9A1XvwxCUYhhjGiLzJ9CZL6hBQB43qHOmE9XJPme90geLsF+gK +u39Waj1SNWzwGg+Gy1Gl5f2AJoDTxznreCuFGj+Vfaczt/hlfgqpOdb9jsmdoE7t +3DSWppA9dRHWwQSgE6J28rR4QySBcqyXS6IMykqaJn7Z26yNIaITLnHCZOSY8zhP +ha7GFsN549EOCgECbrnPt9dmI2+hQE0RO0e7SOBNsIf5sz/i7urhwuj0CbOqhjc2 +X1AEVNFCVcb6HPi/AWefdFCRu0gaWQxn5g+9nkq5slEgvzCCiKYzaBIcr8qR6Hb4 +FaOPVPxO8vndRouq57Ws8XpAwbPttioFuCqF4u9K+tK/8e2/R8QgRYJsE3Cz/Fu8 ++pZFpMnqbDEbK3DL3ss+1ed1sky+mDV8qXXeI33XW5hMFnk1JWshUjHNlQmE6ftC +U0xSTMVUtwJhzH2zDp8lEdu7qi3EsNULOl68ozDr6soWAvCbHPeTdTOnFySGCleG +/3TonsoZJs/sSPPJnxFQ1DtgQL6EbhIwa0ZwU4eKYVHZ9tjxuMX3teFzRvOrJjgs ++ywGlsIURtEckT5Y6nMAEQEAAYkCPAQYAQgAJhYhBOHazw/v6H2ee9HwGKtG7710 +AssCBQJfmfYBAhsMBQkHhh+AAAoJEKtG7710AssC8NcP/iDAcy1aZFvkA0EbZ85p +i7/+ywtE/1wF4U4/9OuLcoskqGGnl1pJNPooMOSBCfreoTB8HimT0Fln0CoaOm4Q +pScNq39JXmf4VxauqUJVARByP6zUfgYarqoaZNeuFF0S4AZJ2HhGzaQPjDz1uKVM +PE6tQSgQkFzdZ9AtRA4vElTH6yRAgmepUsOihk0b0gUtVnwtRYZ8e0Qt3ie97a73 +DxLgAgedFRUbLRYiT0vNaYbainBsLWKpN/T8odwIg/smP0Khjp/ckV60cZTdBiPR +szBTPJESMUTu0VPntc4gWwGsmhZJg/Tt/qP08XYo3VxNYBegyuWwNR66zDWvwvGH +muMv5UchuDxp6Rt3JkIO4voMT1JSjWy9p8krkPEE4V6PxAagLjdZSkt92wVLiK5x +y5gNrtPhU45YdRAKHr36OvJBJQ42CDaZ6nzrzghcIp9CZ7ANHrI+QLRM/csz+AGA +szSp6S4mc1lnxxfbOhPPpebZPn0nIAXoZnnoVKdrxBVedPQHT59ZFvKTQ9Fs7gd3 +sYNuc7tJGFGC2CxBH4ANDpOQkc5q9JJ1HSGrXU3juxIiRgfA26Q22S9c71dXjElw +Ri584QH+bL6kkYmm8xpKF6TVwhwu5xx/jBPrbWqFrtbvLNrnfPoapTihBfdIhkT6 +nmgawbBHA02D5xEqB5SU3WJu +=eJNx +-----END PGP PUBLIC KEY BLOCK----- +``` diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/composer.json b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/composer.json new file mode 100644 index 00000000..98862ee4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/composer.json @@ -0,0 +1,102 @@ +{ + "name": "ramsey/collection", + "type": "library", + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "license": "MIT", + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "require": { + "php": "^7.3 || ^8", + "symfony/polyfill-php81": "^1.23" + }, + "require-dev": { + "captainhook/captainhook": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "ergebnis/composer-normalize": "^2.6", + "fakerphp/faker": "^1.5", + "hamcrest/hamcrest-php": "^2", + "jangregor/phpstan-prophecy": "^0.8", + "mockery/mockery": "^1.3", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12.32", + "phpstan/phpstan-mockery": "^0.12.5", + "phpstan/phpstan-phpunit": "^0.12.11", + "phpunit/phpunit": "^8.5 || ^9", + "psy/psysh": "^0.10.4", + "slevomat/coding-standard": "^6.3", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.4" + }, + "config": { + "sort-packages": true + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Ramsey\\Console\\": "resources/console/", + "Ramsey\\Collection\\Test\\": "tests/", + "Ramsey\\Test\\Generics\\": "tests/generics/" + }, + "files": [ + "vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php" + ] + }, + "scripts": { + "post-autoload-dump": "captainhook install --ansi -f -s", + "dev:analyze": [ + "@dev:analyze:phpstan", + "@dev:analyze:psalm" + ], + "dev:analyze:phpstan": "phpstan --memory-limit=1G analyse", + "dev:analyze:psalm": "psalm --diff --config=psalm.xml", + "dev:build:clean": "git clean -fX build/.", + "dev:build:clear-cache": "git clean -fX build/cache/.", + "dev:lint": "phpcs --cache=build/cache/phpcs.cache", + "dev:lint:fix": "./bin/lint-fix.sh", + "dev:repl": [ + "echo ; echo 'Type ./bin/repl to start the REPL.'" + ], + "dev:test": "phpunit", + "dev:test:all": [ + "@dev:lint", + "@dev:analyze", + "@dev:test" + ], + "dev:test:coverage:ci": "phpunit --coverage-clover build/logs/clover.xml", + "dev:test:coverage:html": "phpunit --coverage-html build/coverage", + "test": "@dev:test:all" + }, + "scripts-descriptions": { + "dev:analyze": "Performs static analysis on the code base.", + "dev:analyze:phpstan": "Runs the PHPStan static analyzer.", + "dev:analyze:psalm": "Runs the Psalm static analyzer.", + "dev:build:clean": "Removes everything not under version control from the build directory.", + "dev:build:clear-cache": "Removes everything not under version control from build/cache/.", + "dev:lint": "Checks all source code for coding standards issues.", + "dev:lint:fix": "Checks source code for coding standards issues and fixes them, if possible.", + "dev:repl": "Note: Use ./bin/repl to run the REPL.", + "dev:test": "Runs the full unit test suite.", + "dev:test:all": "Runs linting, static analysis, and unit tests.", + "dev:test:coverage:ci": "Runs the unit test suite and generates a Clover coverage report.", + "dev:test:coverage:html": "Runs the unit tests suite and generates an HTML coverage report.", + "test": "Shortcut to run the full test suite." + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractArray.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractArray.php new file mode 100644 index 00000000..d72dbe69 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractArray.php @@ -0,0 +1,209 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +use ArrayIterator; +use Traversable; + +use function serialize; +use function unserialize; + +/** + * This class provides a basic implementation of `ArrayInterface`, to minimize + * the effort required to implement this interface. + * + * @template T + * @implements ArrayInterface + */ +abstract class AbstractArray implements ArrayInterface +{ + /** + * The items of this array. + * + * @var array + */ + protected $data = []; + + /** + * Constructs a new array object. + * + * @param array $data The initial items to add to this array. + */ + public function __construct(array $data = []) + { + // Invoke offsetSet() for each value added; in this way, sub-classes + // may provide additional logic about values added to the array object. + foreach ($data as $key => $value) { + $this[$key] = $value; + } + } + + /** + * Returns an iterator for this array. + * + * @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator() + * + * @return Traversable + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->data); + } + + /** + * Returns `true` if the given offset exists in this array. + * + * @link http://php.net/manual/en/arrayaccess.offsetexists.php ArrayAccess::offsetExists() + * + * @param array-key $offset The offset to check. + */ + public function offsetExists($offset): bool + { + return isset($this->data[$offset]); + } + + /** + * Returns the value at the specified offset. + * + * @link http://php.net/manual/en/arrayaccess.offsetget.php ArrayAccess::offsetGet() + * + * @param array-key $offset The offset for which a value should be returned. + * + * @return T|null the value stored at the offset, or null if the offset + * does not exist. + * + * @psalm-suppress InvalidAttribute + */ + #[\ReturnTypeWillChange] // phpcs:ignore + public function offsetGet($offset) + { + return $this->data[$offset] ?? null; + } + + /** + * Sets the given value to the given offset in the array. + * + * @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet() + * + * @param array-key|null $offset The offset to set. If `null`, the value may be + * set at a numerically-indexed offset. + * @param T $value The value to set at the given offset. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function offsetSet($offset, $value): void + { + if ($offset === null) { + $this->data[] = $value; + } else { + $this->data[$offset] = $value; + } + } + + /** + * Removes the given offset and its value from the array. + * + * @link http://php.net/manual/en/arrayaccess.offsetunset.php ArrayAccess::offsetUnset() + * + * @param array-key $offset The offset to remove from the array. + */ + public function offsetUnset($offset): void + { + unset($this->data[$offset]); + } + + /** + * Returns a serialized string representation of this array object. + * + * @deprecated The Serializable interface will go away in PHP 9. + * + * @link http://php.net/manual/en/serializable.serialize.php Serializable::serialize() + * + * @return string a PHP serialized string. + */ + public function serialize(): string + { + return serialize($this->data); + } + + /** + * Returns data suitable for PHP serialization. + * + * @link https://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.serialize + * @link https://www.php.net/serialize + * + * @return array + */ + public function __serialize(): array + { + return $this->data; + } + + /** + * Converts a serialized string representation into an instance object. + * + * @deprecated The Serializable interface will go away in PHP 9. + * + * @link http://php.net/manual/en/serializable.unserialize.php Serializable::unserialize() + * + * @param string $serialized A PHP serialized string to unserialize. + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function unserialize($serialized): void + { + /** @var array $data */ + $data = unserialize($serialized, ['allowed_classes' => false]); + + $this->data = $data; + } + + /** + * Adds unserialized data to the object. + * + * @param array $data + */ + public function __unserialize(array $data): void + { + $this->data = $data; + } + + /** + * Returns the number of items in this array. + * + * @link http://php.net/manual/en/countable.count.php Countable::count() + */ + public function count(): int + { + return count($this->data); + } + + public function clear(): void + { + $this->data = []; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return $this->data; + } + + public function isEmpty(): bool + { + return count($this->data) === 0; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractCollection.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractCollection.php new file mode 100644 index 00000000..d2cd1151 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractCollection.php @@ -0,0 +1,318 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +use Closure; +use Ramsey\Collection\Exception\CollectionMismatchException; +use Ramsey\Collection\Exception\InvalidArgumentException; +use Ramsey\Collection\Exception\InvalidSortOrderException; +use Ramsey\Collection\Exception\OutOfBoundsException; +use Ramsey\Collection\Tool\TypeTrait; +use Ramsey\Collection\Tool\ValueExtractorTrait; +use Ramsey\Collection\Tool\ValueToStringTrait; + +use function array_filter; +use function array_map; +use function array_merge; +use function array_search; +use function array_udiff; +use function array_uintersect; +use function current; +use function end; +use function in_array; +use function is_int; +use function reset; +use function sprintf; +use function unserialize; +use function usort; + +/** + * This class provides a basic implementation of `CollectionInterface`, to + * minimize the effort required to implement this interface + * + * @template T + * @extends AbstractArray + * @implements CollectionInterface + */ +abstract class AbstractCollection extends AbstractArray implements CollectionInterface +{ + use TypeTrait; + use ValueToStringTrait; + use ValueExtractorTrait; + + /** + * @inheritDoc + */ + public function add($element): bool + { + $this[] = $element; + + return true; + } + + /** + * @inheritDoc + */ + public function contains($element, bool $strict = true): bool + { + return in_array($element, $this->data, $strict); + } + + /** + * @inheritDoc + */ + public function offsetSet($offset, $value): void + { + if ($this->checkType($this->getType(), $value) === false) { + throw new InvalidArgumentException( + 'Value must be of type ' . $this->getType() . '; value is ' + . $this->toolValueToString($value) + ); + } + + if ($offset === null) { + $this->data[] = $value; + } else { + $this->data[$offset] = $value; + } + } + + /** + * @inheritDoc + */ + public function remove($element): bool + { + if (($position = array_search($element, $this->data, true)) !== false) { + unset($this->data[$position]); + + return true; + } + + return false; + } + + /** + * @inheritDoc + */ + public function column(string $propertyOrMethod): array + { + $temp = []; + + foreach ($this->data as $item) { + /** @var mixed $value */ + $value = $this->extractValue($item, $propertyOrMethod); + + /** @psalm-suppress MixedAssignment */ + $temp[] = $value; + } + + return $temp; + } + + /** + * @inheritDoc + */ + public function first() + { + if ($this->isEmpty()) { + throw new OutOfBoundsException('Can\'t determine first item. Collection is empty'); + } + + reset($this->data); + + /** @var T $first */ + $first = current($this->data); + + return $first; + } + + /** + * @inheritDoc + */ + public function last() + { + if ($this->isEmpty()) { + throw new OutOfBoundsException('Can\'t determine last item. Collection is empty'); + } + + /** @var T $item */ + $item = end($this->data); + reset($this->data); + + return $item; + } + + public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): CollectionInterface + { + if (!in_array($order, [self::SORT_ASC, self::SORT_DESC], true)) { + throw new InvalidSortOrderException('Invalid sort order given: ' . $order); + } + + $collection = clone $this; + + usort( + $collection->data, + /** + * @param T $a + * @param T $b + */ + function ($a, $b) use ($propertyOrMethod, $order): int { + /** @var mixed $aValue */ + $aValue = $this->extractValue($a, $propertyOrMethod); + + /** @var mixed $bValue */ + $bValue = $this->extractValue($b, $propertyOrMethod); + + return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1); + } + ); + + return $collection; + } + + public function filter(callable $callback): CollectionInterface + { + $collection = clone $this; + $collection->data = array_merge([], array_filter($collection->data, $callback)); + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function where(string $propertyOrMethod, $value): CollectionInterface + { + return $this->filter(function ($item) use ($propertyOrMethod, $value) { + /** @var mixed $accessorValue */ + $accessorValue = $this->extractValue($item, $propertyOrMethod); + + return $accessorValue === $value; + }); + } + + public function map(callable $callback): CollectionInterface + { + return new Collection('mixed', array_map($callback, $this->data)); + } + + public function diff(CollectionInterface $other): CollectionInterface + { + $this->compareCollectionTypes($other); + + $diffAtoB = array_udiff($this->data, $other->toArray(), $this->getComparator()); + $diffBtoA = array_udiff($other->toArray(), $this->data, $this->getComparator()); + + /** @var array $diff */ + $diff = array_merge($diffAtoB, $diffBtoA); + + $collection = clone $this; + $collection->data = $diff; + + return $collection; + } + + public function intersect(CollectionInterface $other): CollectionInterface + { + $this->compareCollectionTypes($other); + + /** @var array $intersect */ + $intersect = array_uintersect($this->data, $other->toArray(), $this->getComparator()); + + $collection = clone $this; + $collection->data = $intersect; + + return $collection; + } + + public function merge(CollectionInterface ...$collections): CollectionInterface + { + $mergedCollection = clone $this; + + foreach ($collections as $index => $collection) { + if (!$collection instanceof static) { + throw new CollectionMismatchException( + sprintf('Collection with index %d must be of type %s', $index, static::class) + ); + } + + // When using generics (Collection.php, Set.php, etc), + // we also need to make sure that the internal types match each other + if ($collection->getType() !== $this->getType()) { + throw new CollectionMismatchException( + sprintf('Collection items in collection with index %d must be of type %s', $index, $this->getType()) + ); + } + + foreach ($collection as $key => $value) { + if (is_int($key)) { + $mergedCollection[] = $value; + } else { + $mergedCollection[$key] = $value; + } + } + } + + return $mergedCollection; + } + + /** + * @inheritDoc + */ + public function unserialize($serialized): void + { + /** @var array $data */ + $data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]); + + $this->data = $data; + } + + /** + * @param CollectionInterface $other + */ + private function compareCollectionTypes(CollectionInterface $other): void + { + if (!$other instanceof static) { + throw new CollectionMismatchException('Collection must be of type ' . static::class); + } + + // When using generics (Collection.php, Set.php, etc), + // we also need to make sure that the internal types match each other + if ($other->getType() !== $this->getType()) { + throw new CollectionMismatchException('Collection items must be of type ' . $this->getType()); + } + } + + private function getComparator(): Closure + { + return /** + * @param T $a + * @param T $b + */ + function ($a, $b): int { + // If the two values are object, we convert them to unique scalars. + // If the collection contains mixed values (unlikely) where some are objects + // and some are not, we leave them as they are. + // The comparator should still work and the result of $a < $b should + // be consistent but unpredictable since not documented. + if (is_object($a) && is_object($b)) { + $a = spl_object_id($a); + $b = spl_object_id($b); + } + + return $a === $b ? 0 : ($a < $b ? 1 : -1); + }; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractSet.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractSet.php new file mode 100644 index 00000000..1126ccb0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/AbstractSet.php @@ -0,0 +1,50 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +/** + * This class contains the basic implementation of a collection that does not + * allow duplicated values (a set), to minimize the effort required to implement + * this specific type of collection. + * + * @template T + * @extends AbstractCollection + */ +abstract class AbstractSet extends AbstractCollection +{ + /** + * @inheritDoc + */ + public function add($element): bool + { + if ($this->contains($element)) { + return false; + } + + return parent::add($element); + } + + /** + * @inheritDoc + */ + public function offsetSet($offset, $value): void + { + if ($this->contains($value)) { + return; + } + + parent::offsetSet($offset, $value); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/ArrayInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/ArrayInterface.php new file mode 100644 index 00000000..27af6102 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/ArrayInterface.php @@ -0,0 +1,51 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +use ArrayAccess; +use Countable; +use IteratorAggregate; +use Serializable; + +/** + * `ArrayInterface` provides traversable array functionality to data types. + * + * @template T + * @extends ArrayAccess + * @extends IteratorAggregate + */ +interface ArrayInterface extends + ArrayAccess, + Countable, + IteratorAggregate, + Serializable +{ + /** + * Removes all items from this array. + */ + public function clear(): void; + + /** + * Returns a native PHP array representation of this array object. + * + * @return array + */ + public function toArray(): array; + + /** + * Returns `true` if this array is empty. + */ + public function isEmpty(): bool; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Collection.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Collection.php new file mode 100644 index 00000000..1299c12c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Collection.php @@ -0,0 +1,106 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +/** + * A collection represents a group of objects. + * + * Each object in the collection is of a specific, defined type. + * + * This is a direct implementation of `CollectionInterface`, provided for + * the sake of convenience. + * + * Example usage: + * + * ``` php + * $collection = new \Ramsey\Collection\Collection('My\\Foo'); + * $collection->add(new \My\Foo()); + * $collection->add(new \My\Foo()); + * + * foreach ($collection as $foo) { + * // Do something with $foo + * } + * ``` + * + * It is preferable to subclass `AbstractCollection` to create your own typed + * collections. For example: + * + * ``` php + * namespace My\Foo; + * + * class FooCollection extends \Ramsey\Collection\AbstractCollection + * { + * public function getType() + * { + * return 'My\\Foo'; + * } + * } + * ``` + * + * And then use it similarly to the earlier example: + * + * ``` php + * $fooCollection = new \My\Foo\FooCollection(); + * $fooCollection->add(new \My\Foo()); + * $fooCollection->add(new \My\Foo()); + * + * foreach ($fooCollection as $foo) { + * // Do something with $foo + * } + * ``` + * + * The benefit with this approach is that you may do type-checking on the + * collection object: + * + * ``` php + * if ($collection instanceof \My\Foo\FooCollection) { + * // the collection is a collection of My\Foo objects + * } + * ``` + * + * @template T + * @extends AbstractCollection + */ +class Collection extends AbstractCollection +{ + /** + * The type of elements stored in this collection. + * + * A collection's type is immutable once it is set. For this reason, this + * property is set private. + * + * @var string + */ + private $collectionType; + + /** + * Constructs a collection object of the specified type, optionally with the + * specified data. + * + * @param string $collectionType The type (FQCN) associated with this + * collection. + * @param array $data The initial items to store in the collection. + */ + public function __construct(string $collectionType, array $data = []) + { + $this->collectionType = $collectionType; + parent::__construct($data); + } + + public function getType(): string + { + return $this->collectionType; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/CollectionInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/CollectionInterface.php new file mode 100644 index 00000000..aa86feb0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/CollectionInterface.php @@ -0,0 +1,205 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +/** + * A collection represents a group of objects, known as its elements. + * + * Some collections allow duplicate elements and others do not. Some are ordered + * and others unordered. + * + * @template T + * @extends ArrayInterface + */ +interface CollectionInterface extends ArrayInterface +{ + /** + * Ascending sort type. + */ + public const SORT_ASC = 'asc'; + + /** + * Descending sort type. + */ + public const SORT_DESC = 'desc'; + + /** + * Ensures that this collection contains the specified element (optional + * operation). + * + * Returns `true` if this collection changed as a result of the call. + * (Returns `false` if this collection does not permit duplicates and + * already contains the specified element.) + * + * Collections that support this operation may place limitations on what + * elements may be added to this collection. In particular, some + * collections will refuse to add `null` elements, and others will impose + * restrictions on the type of elements that may be added. Collection + * classes should clearly specify in their documentation any restrictions + * on what elements may be added. + * + * If a collection refuses to add a particular element for any reason other + * than that it already contains the element, it must throw an exception + * (rather than returning `false`). This preserves the invariant that a + * collection always contains the specified element after this call returns. + * + * @param T $element The element to add to the collection. + * + * @return bool `true` if this collection changed as a result of the call. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function add($element): bool; + + /** + * Returns `true` if this collection contains the specified element. + * + * @param T $element The element to check whether the collection contains. + * @param bool $strict Whether to perform a strict type check on the value. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function contains($element, bool $strict = true): bool; + + /** + * Returns the type associated with this collection. + */ + public function getType(): string; + + /** + * Removes a single instance of the specified element from this collection, + * if it is present. + * + * @param T $element The element to remove from the collection. + * + * @return bool `true` if an element was removed as a result of this call. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function remove($element): bool; + + /** + * Returns the values from the given property or method. + * + * @param string $propertyOrMethod The property or method name to filter by. + * + * @return list + */ + public function column(string $propertyOrMethod): array; + + /** + * Returns the first item of the collection. + * + * @return T + */ + public function first(); + + /** + * Returns the last item of the collection. + * + * @return T + */ + public function last(); + + /** + * Sort the collection by a property or method with the given sort order. + * + * This will always leave the original collection untouched and will return + * a new one. + * + * @param string $propertyOrMethod The property or method to sort by. + * @param string $order The sort order for the resulting collection (one of + * this interface's `SORT_*` constants). + * + * @return CollectionInterface + */ + public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): self; + + /** + * Filter out items of the collection which don't match the criteria of + * given callback. + * + * This will always leave the original collection untouched and will return + * a new one. + * + * See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation} + * for examples of how the `$callback` parameter works. + * + * @param callable(T):bool $callback A callable to use for filtering elements. + * + * @return CollectionInterface + */ + public function filter(callable $callback): self; + + /** + * Create a new collection where items match the criteria of given callback. + * + * This will always leave the original collection untouched and will return + * a new one. + * + * @param string $propertyOrMethod The property or method to evaluate. + * @param mixed $value The value to match. + * + * @return CollectionInterface + */ + public function where(string $propertyOrMethod, $value): self; + + /** + * Apply a given callback method on each item of the collection. + * + * This will always leave the original collection untouched. The new + * collection is created by mapping the callback to each item of the + * original collection. + * + * See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation} + * for examples of how the `$callback` parameter works. + * + * @param callable(T):TCallbackReturn $callback A callable to apply to each + * item of the collection. + * + * @return CollectionInterface + * + * @template TCallbackReturn + */ + public function map(callable $callback): self; + + /** + * Create a new collection with divergent items between current and given + * collection. + * + * @param CollectionInterface $other The collection to check for divergent + * items. + * + * @return CollectionInterface + */ + public function diff(CollectionInterface $other): self; + + /** + * Create a new collection with intersecting item between current and given + * collection. + * + * @param CollectionInterface $other The collection to check for + * intersecting items. + * + * @return CollectionInterface + */ + public function intersect(CollectionInterface $other): self; + + /** + * Merge current items and items of given collections into a new one. + * + * @param CollectionInterface ...$collections The collections to merge. + * + * @return CollectionInterface + */ + public function merge(CollectionInterface ...$collections): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueue.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueue.php new file mode 100644 index 00000000..c9c59502 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueue.php @@ -0,0 +1,187 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +use Ramsey\Collection\Exception\InvalidArgumentException; +use Ramsey\Collection\Exception\NoSuchElementException; + +/** + * This class provides a basic implementation of `DoubleEndedQueueInterface`, to + * minimize the effort required to implement this interface. + * + * @template T + * @extends Queue + * @implements DoubleEndedQueueInterface + */ +class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface +{ + /** + * Index of the last element in the queue. + * + * @var int + */ + private $tail = -1; + + /** + * @inheritDoc + */ + public function offsetSet($offset, $value): void + { + if ($this->checkType($this->getType(), $value) === false) { + throw new InvalidArgumentException( + 'Value must be of type ' . $this->getType() . '; value is ' + . $this->toolValueToString($value) + ); + } + + $this->tail++; + + $this->data[$this->tail] = $value; + } + + /** + * @inheritDoc + */ + public function addFirst($element): bool + { + if ($this->checkType($this->getType(), $element) === false) { + throw new InvalidArgumentException( + 'Value must be of type ' . $this->getType() . '; value is ' + . $this->toolValueToString($element) + ); + } + + $this->index--; + + $this->data[$this->index] = $element; + + return true; + } + + /** + * @inheritDoc + */ + public function addLast($element): bool + { + return $this->add($element); + } + + /** + * @inheritDoc + */ + public function offerFirst($element): bool + { + try { + return $this->addFirst($element); + } catch (InvalidArgumentException $e) { + return false; + } + } + + /** + * @inheritDoc + */ + public function offerLast($element): bool + { + return $this->offer($element); + } + + /** + * @inheritDoc + */ + public function removeFirst() + { + return $this->remove(); + } + + /** + * @inheritDoc + */ + public function removeLast() + { + $tail = $this->pollLast(); + + if ($tail === null) { + throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.'); + } + + return $tail; + } + + /** + * @inheritDoc + */ + public function pollFirst() + { + return $this->poll(); + } + + /** + * @inheritDoc + */ + public function pollLast() + { + if ($this->count() === 0) { + return null; + } + + $tail = $this[$this->tail]; + + unset($this[$this->tail]); + $this->tail--; + + return $tail; + } + + /** + * @inheritDoc + */ + public function firstElement() + { + return $this->element(); + } + + /** + * @inheritDoc + */ + public function lastElement() + { + if ($this->count() === 0) { + throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.'); + } + + return $this->data[$this->tail]; + } + + /** + * @inheritDoc + */ + public function peekFirst() + { + return $this->peek(); + } + + /** + * @inheritDoc + */ + public function peekLast() + { + if ($this->count() === 0) { + return null; + } + + return $this->data[$this->tail]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php new file mode 100644 index 00000000..d7df5346 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php @@ -0,0 +1,316 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +use Ramsey\Collection\Exception\NoSuchElementException; + +/** + * A linear collection that supports element insertion and removal at both ends. + * + * Most `DoubleEndedQueueInterface` implementations place no fixed limits on the + * number of elements they may contain, but this interface supports + * capacity-restricted double-ended queues as well as those with no fixed size + * limit. + * + * This interface defines methods to access the elements at both ends of the + * double-ended queue. Methods are provided to insert, remove, and examine the + * element. Each of these methods exists in two forms: one throws an exception + * if the operation fails, the other returns a special value (either `null` or + * `false`, depending on the operation). The latter form of the insert operation + * is designed specifically for use with capacity-restricted implementations; in + * most implementations, insert operations cannot fail. + * + * The twelve methods described above are summarized in the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Summary of DoubleEndedQueueInterface methods
First Element (Head)Last Element (Tail)
Throws exceptionSpecial valueThrows exceptionSpecial value
InsertaddFirst()offerFirst()addLast()offerLast()
RemoveremoveFirst()pollFirst()removeLast()pollLast()
ExaminefirstElement()peekFirst()lastElement()peekLast()
+ * + * This interface extends the `QueueInterface`. When a double-ended queue is + * used as a queue, FIFO (first-in-first-out) behavior results. Elements are + * added at the end of the double-ended queue and removed from the beginning. + * The methods inherited from the `QueueInterface` are precisely equivalent to + * `DoubleEndedQueueInterface` methods as indicated in the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Comparison of QueueInterface and DoubleEndedQueueInterface methods
QueueInterface MethodDoubleEndedQueueInterface Method
add()addLast()
offer()offerLast()
remove()removeFirst()
poll()pollFirst()
element()firstElement()
peek()peekFirst()
+ * + * Double-ended queues can also be used as LIFO (last-in-first-out) stacks. When + * a double-ended queue is used as a stack, elements are pushed and popped from + * the beginning of the double-ended queue. Stack concepts are precisely + * equivalent to `DoubleEndedQueueInterface` methods as indicated in the table + * below: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Comparison of stack concepts and DoubleEndedQueueInterface methods
Stack conceptDoubleEndedQueueInterface Method
pushaddFirst()
popremoveFirst()
peekpeekFirst()
+ * + * Note that the `peek()` method works equally well when a double-ended queue is + * used as a queue or a stack; in either case, elements are drawn from the + * beginning of the double-ended queue. + * + * While `DoubleEndedQueueInterface` implementations are not strictly required + * to prohibit the insertion of `null` elements, they are strongly encouraged to + * do so. Users of any `DoubleEndedQueueInterface` implementations that do allow + * `null` elements are strongly encouraged *not* to take advantage of the + * ability to insert nulls. This is so because `null` is used as a special + * return value by various methods to indicated that the double-ended queue is + * empty. + * + * @template T + * @extends QueueInterface + */ +interface DoubleEndedQueueInterface extends QueueInterface +{ + /** + * Inserts the specified element at the front of this queue if it is + * possible to do so immediately without violating capacity restrictions. + * + * When using a capacity-restricted double-ended queue, it is generally + * preferable to use the `offerFirst()` method. + * + * @param T $element The element to add to the front of this queue. + * + * @return bool `true` if this queue changed as a result of the call. + * + * @throws \RuntimeException if a queue refuses to add a particular element + * for any reason other than that it already contains the element. + * Implementations should use a more-specific exception that extends + * `\RuntimeException`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function addFirst($element): bool; + + /** + * Inserts the specified element at the end of this queue if it is possible + * to do so immediately without violating capacity restrictions. + * + * When using a capacity-restricted double-ended queue, it is generally + * preferable to use the `offerLast()` method. + * + * This method is equivalent to `add()`. + * + * @param T $element The element to add to the end of this queue. + * + * @return bool `true` if this queue changed as a result of the call. + * + * @throws \RuntimeException if a queue refuses to add a particular element + * for any reason other than that it already contains the element. + * Implementations should use a more-specific exception that extends + * `\RuntimeException`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function addLast($element): bool; + + /** + * Inserts the specified element at the front of this queue if it is + * possible to do so immediately without violating capacity restrictions. + * + * When using a capacity-restricted queue, this method is generally + * preferable to `addFirst()`, which can fail to insert an element only by + * throwing an exception. + * + * @param T $element The element to add to the front of this queue. + * + * @return bool `true` if the element was added to this queue, else `false`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function offerFirst($element): bool; + + /** + * Inserts the specified element at the end of this queue if it is possible + * to do so immediately without violating capacity restrictions. + * + * When using a capacity-restricted queue, this method is generally + * preferable to `addLast()` which can fail to insert an element only by + * throwing an exception. + * + * @param T $element The element to add to the end of this queue. + * + * @return bool `true` if the element was added to this queue, else `false`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function offerLast($element): bool; + + /** + * Retrieves and removes the head of this queue. + * + * This method differs from `pollFirst()` only in that it throws an + * exception if this queue is empty. + * + * @return T the first element in this queue. + * + * @throws NoSuchElementException if this queue is empty. + */ + public function removeFirst(); + + /** + * Retrieves and removes the tail of this queue. + * + * This method differs from `pollLast()` only in that it throws an exception + * if this queue is empty. + * + * @return T the last element in this queue. + * + * @throws NoSuchElementException if this queue is empty. + */ + public function removeLast(); + + /** + * Retrieves and removes the head of this queue, or returns `null` if this + * queue is empty. + * + * @return T|null the head of this queue, or `null` if this queue is empty. + */ + public function pollFirst(); + + /** + * Retrieves and removes the tail of this queue, or returns `null` if this + * queue is empty. + * + * @return T|null the tail of this queue, or `null` if this queue is empty. + */ + public function pollLast(); + + /** + * Retrieves, but does not remove, the head of this queue. + * + * This method differs from `peekFirst()` only in that it throws an + * exception if this queue is empty. + * + * @return T the head of this queue. + * + * @throws NoSuchElementException if this queue is empty. + */ + public function firstElement(); + + /** + * Retrieves, but does not remove, the tail of this queue. + * + * This method differs from `peekLast()` only in that it throws an exception + * if this queue is empty. + * + * @return T the tail of this queue. + * + * @throws NoSuchElementException if this queue is empty. + */ + public function lastElement(); + + /** + * Retrieves, but does not remove, the head of this queue, or returns `null` + * if this queue is empty. + * + * @return T|null the head of this queue, or `null` if this queue is empty. + */ + public function peekFirst(); + + /** + * Retrieves, but does not remove, the tail of this queue, or returns `null` + * if this queue is empty. + * + * @return T|null the tail of this queue, or `null` if this queue is empty. + */ + public function peekLast(); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php new file mode 100644 index 00000000..d4b335f4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php @@ -0,0 +1,22 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Exception; + +/** + * Thrown when attempting to operate on collections of differing types. + */ +class CollectionMismatchException extends \RuntimeException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..dcc3eac6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php @@ -0,0 +1,22 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Exception; + +/** + * Thrown to indicate an argument is not of the expected type. + */ +class InvalidArgumentException extends \InvalidArgumentException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php new file mode 100644 index 00000000..9337ccc6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php @@ -0,0 +1,22 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Exception; + +/** + * Thrown when attempting to use a sort order that is not recognized. + */ +class InvalidSortOrderException extends \RuntimeException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/NoSuchElementException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/NoSuchElementException.php new file mode 100644 index 00000000..9debe8f6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/NoSuchElementException.php @@ -0,0 +1,22 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Exception; + +/** + * Thrown when attempting to access an element that does not exist. + */ +class NoSuchElementException extends \RuntimeException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php new file mode 100644 index 00000000..4e9d16fa --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php @@ -0,0 +1,22 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Exception; + +/** + * Thrown when attempting to access an element out of the range of the collection. + */ +class OutOfBoundsException extends \OutOfBoundsException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php new file mode 100644 index 00000000..8f45e583 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php @@ -0,0 +1,22 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Exception; + +/** + * Thrown to indicate that the requested operation is not supported. + */ +class UnsupportedOperationException extends \RuntimeException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/ValueExtractionException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/ValueExtractionException.php new file mode 100644 index 00000000..f6c6cb4e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Exception/ValueExtractionException.php @@ -0,0 +1,22 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Exception; + +/** + * Thrown when attempting to extract a value for a method or property that does not exist. + */ +class ValueExtractionException extends \RuntimeException +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/GenericArray.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/GenericArray.php new file mode 100644 index 00000000..2b079aa5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/GenericArray.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +/** + * `GenericArray` represents a standard array object. + * + * @extends AbstractArray + */ +class GenericArray extends AbstractArray +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractMap.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractMap.php new file mode 100644 index 00000000..ae9f2fe6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractMap.php @@ -0,0 +1,162 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Map; + +use Ramsey\Collection\AbstractArray; +use Ramsey\Collection\Exception\InvalidArgumentException; + +use function array_key_exists; +use function array_keys; +use function in_array; + +/** + * This class provides a basic implementation of `MapInterface`, to minimize the + * effort required to implement this interface. + * + * @template T + * @extends AbstractArray + * @implements MapInterface + */ +abstract class AbstractMap extends AbstractArray implements MapInterface +{ + /** + * @inheritDoc + */ + public function offsetSet($offset, $value): void + { + if ($offset === null) { + throw new InvalidArgumentException( + 'Map elements are key/value pairs; a key must be provided for ' + . 'value ' . var_export($value, true) + ); + } + + $this->data[$offset] = $value; + } + + /** + * @inheritDoc + */ + public function containsKey($key): bool + { + return array_key_exists($key, $this->data); + } + + /** + * @inheritDoc + */ + public function containsValue($value): bool + { + return in_array($value, $this->data, true); + } + + /** + * @inheritDoc + */ + public function keys(): array + { + return array_keys($this->data); + } + + /** + * @inheritDoc + */ + public function get($key, $defaultValue = null) + { + if (!$this->containsKey($key)) { + return $defaultValue; + } + + return $this[$key]; + } + + /** + * @inheritDoc + */ + public function put($key, $value) + { + $previousValue = $this->get($key); + $this[$key] = $value; + + return $previousValue; + } + + /** + * @inheritDoc + */ + public function putIfAbsent($key, $value) + { + $currentValue = $this->get($key); + + if ($currentValue === null) { + $this[$key] = $value; + } + + return $currentValue; + } + + /** + * @inheritDoc + */ + public function remove($key) + { + $previousValue = $this->get($key); + unset($this[$key]); + + return $previousValue; + } + + /** + * @inheritDoc + */ + public function removeIf($key, $value): bool + { + if ($this->get($key) === $value) { + unset($this[$key]); + + return true; + } + + return false; + } + + /** + * @inheritDoc + */ + public function replace($key, $value) + { + $currentValue = $this->get($key); + + if ($this->containsKey($key)) { + $this[$key] = $value; + } + + return $currentValue; + } + + /** + * @inheritDoc + */ + public function replaceIf($key, $oldValue, $newValue): bool + { + if ($this->get($key) === $oldValue) { + $this[$key] = $newValue; + + return true; + } + + return false; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractTypedMap.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractTypedMap.php new file mode 100644 index 00000000..551d2e6c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AbstractTypedMap.php @@ -0,0 +1,69 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Map; + +use Ramsey\Collection\Exception\InvalidArgumentException; +use Ramsey\Collection\Tool\TypeTrait; +use Ramsey\Collection\Tool\ValueToStringTrait; + +/** + * This class provides a basic implementation of `TypedMapInterface`, to + * minimize the effort required to implement this interface. + * + * @template K + * @template T + * @extends AbstractMap + * @implements TypedMapInterface + */ +abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface +{ + use TypeTrait; + use ValueToStringTrait; + + /** + * @param K|null $offset + * @param T $value + * + * @inheritDoc + * + * @psalm-suppress MoreSpecificImplementedParamType + */ + public function offsetSet($offset, $value): void + { + if ($offset === null) { + throw new InvalidArgumentException( + 'Map elements are key/value pairs; a key must be provided for ' + . 'value ' . var_export($value, true) + ); + } + + if ($this->checkType($this->getKeyType(), $offset) === false) { + throw new InvalidArgumentException( + 'Key must be of type ' . $this->getKeyType() . '; key is ' + . $this->toolValueToString($offset) + ); + } + + if ($this->checkType($this->getValueType(), $value) === false) { + throw new InvalidArgumentException( + 'Value must be of type ' . $this->getValueType() . '; value is ' + . $this->toolValueToString($value) + ); + } + + /** @psalm-suppress MixedArgumentTypeCoercion */ + parent::offsetSet($offset, $value); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php new file mode 100644 index 00000000..79a314d9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Map; + +/** + * `AssociativeArrayMap` represents a standard associative array object. + * + * @template T + * @extends AbstractMap + */ +class AssociativeArrayMap extends AbstractMap +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/MapInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/MapInterface.php new file mode 100644 index 00000000..6ed0b296 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/MapInterface.php @@ -0,0 +1,149 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Map; + +use Ramsey\Collection\ArrayInterface; + +/** + * An object that maps keys to values. + * + * A map cannot contain duplicate keys; each key can map to at most one value. + * + * @template T + * @extends ArrayInterface + */ +interface MapInterface extends ArrayInterface +{ + /** + * Returns `true` if this map contains a mapping for the specified key. + * + * @param array-key $key The key to check in the map. + */ + public function containsKey($key): bool; + + /** + * Returns `true` if this map maps one or more keys to the specified value. + * + * This performs a strict type check on the value. + * + * @param T $value The value to check in the map. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function containsValue($value): bool; + + /** + * Return an array of the keys contained in this map. + * + * @return list + */ + public function keys(): array; + + /** + * Returns the value to which the specified key is mapped, `null` if this + * map contains no mapping for the key, or (optionally) `$defaultValue` if + * this map contains no mapping for the key. + * + * @param array-key $key The key to return from the map. + * @param T|null $defaultValue The default value to use if `$key` is not found. + * + * @return T|null the value or `null` if the key could not be found. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function get($key, $defaultValue = null); + + /** + * Associates the specified value with the specified key in this map. + * + * If the map previously contained a mapping for the key, the old value is + * replaced by the specified value. + * + * @param array-key $key The key to put or replace in the map. + * @param T $value The value to store at `$key`. + * + * @return T|null the previous value associated with key, or `null` if + * there was no mapping for `$key`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function put($key, $value); + + /** + * Associates the specified value with the specified key in this map only if + * it is not already set. + * + * If there is already a value associated with `$key`, this returns that + * value without replacing it. + * + * @param array-key $key The key to put in the map. + * @param T $value The value to store at `$key`. + * + * @return T|null the previous value associated with key, or `null` if + * there was no mapping for `$key`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function putIfAbsent($key, $value); + + /** + * Removes the mapping for a key from this map if it is present. + * + * @param array-key $key The key to remove from the map. + * + * @return T|null the previous value associated with key, or `null` if + * there was no mapping for `$key`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function remove($key); + + /** + * Removes the entry for the specified key only if it is currently mapped to + * the specified value. + * + * This performs a strict type check on the value. + * + * @param array-key $key The key to remove from the map. + * @param T $value The value to match. + * + * @return bool true if the value was removed. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function removeIf($key, $value): bool; + + /** + * Replaces the entry for the specified key only if it is currently mapped + * to some value. + * + * @param array-key $key The key to replace. + * @param T $value The value to set at `$key`. + * + * @return T|null the previous value associated with key, or `null` if + * there was no mapping for `$key`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function replace($key, $value); + + /** + * Replaces the entry for the specified key only if currently mapped to the + * specified value. + * + * This performs a strict type check on the value. + * + * @param array-key $key The key to remove from the map. + * @param T $oldValue The value to match. + * @param T $newValue The value to use as a replacement. + * + * @return bool true if the value was replaced. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function replaceIf($key, $oldValue, $newValue): bool; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/NamedParameterMap.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/NamedParameterMap.php new file mode 100644 index 00000000..9926ddd8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/NamedParameterMap.php @@ -0,0 +1,120 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Map; + +use Ramsey\Collection\Exception\InvalidArgumentException; +use Ramsey\Collection\Tool\TypeTrait; +use Ramsey\Collection\Tool\ValueToStringTrait; + +use function array_combine; +use function array_key_exists; +use function is_int; + +/** + * `NamedParameterMap` represents a mapping of values to a set of named keys + * that may optionally be typed + * + * @extends AbstractMap + */ +class NamedParameterMap extends AbstractMap +{ + use TypeTrait; + use ValueToStringTrait; + + /** + * Named parameters defined for this map. + * + * @var array + */ + protected $namedParameters; + + /** + * Constructs a new `NamedParameterMap`. + * + * @param array $namedParameters The named parameters defined for this map. + * @param array $data An initial set of data to set on this map. + */ + public function __construct(array $namedParameters, array $data = []) + { + $this->namedParameters = $this->filterNamedParameters($namedParameters); + parent::__construct($data); + } + + /** + * Returns named parameters set for this `NamedParameterMap`. + * + * @return array + */ + public function getNamedParameters(): array + { + return $this->namedParameters; + } + + /** + * @inheritDoc + */ + public function offsetSet($offset, $value): void + { + if ($offset === null) { + throw new InvalidArgumentException( + 'Map elements are key/value pairs; a key must be provided for ' + . 'value ' . var_export($value, true) + ); + } + + if (!array_key_exists($offset, $this->namedParameters)) { + throw new InvalidArgumentException( + 'Attempting to set value for unconfigured parameter \'' + . $offset . '\'' + ); + } + + if ($this->checkType($this->namedParameters[$offset], $value) === false) { + throw new InvalidArgumentException( + 'Value for \'' . $offset . '\' must be of type ' + . $this->namedParameters[$offset] . '; value is ' + . $this->toolValueToString($value) + ); + } + + $this->data[$offset] = $value; + } + + /** + * Given an array of named parameters, constructs a proper mapping of + * named parameters to types. + * + * @param array $namedParameters The named parameters to filter. + * + * @return array + */ + protected function filterNamedParameters(array $namedParameters): array + { + $names = []; + $types = []; + + foreach ($namedParameters as $key => $value) { + if (is_int($key)) { + $names[] = $value; + $types[] = 'mixed'; + } else { + $names[] = $key; + $types[] = $value; + } + } + + return array_combine($names, $types) ?: []; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMap.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMap.php new file mode 100644 index 00000000..2e796377 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMap.php @@ -0,0 +1,137 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Map; + +use Ramsey\Collection\Tool\TypeTrait; + +/** + * A `TypedMap` represents a map of elements where key and value are typed. + * + * Each element is identified by a key with defined type and a value of defined + * type. The keys of the map must be unique. The values on the map can be= + * repeated but each with its own different key. + * + * The most common case is to use a string type key, but it's not limited to + * this type of keys. + * + * This is a direct implementation of `TypedMapInterface`, provided for the sake + * of convenience. + * + * Example usage: + * + * ```php + * $map = new TypedMap('string', Foo::class); + * $map['x'] = new Foo(); + * foreach ($map as $key => $value) { + * // do something with $key, it will be a Foo::class + * } + * + * // this will throw an exception since key must be string + * $map[10] = new Foo(); + * + * // this will throw an exception since value must be a Foo + * $map['bar'] = 'bar'; + * + * // initialize map with contents + * $map = new TypedMap('string', Foo::class, [ + * new Foo(), new Foo(), new Foo() + * ]); + * ``` + * + * It is preferable to subclass `AbstractTypedMap` to create your own typed map + * implementation: + * + * ```php + * class FooTypedMap extends AbstractTypedMap + * { + * public function getKeyType() + * { + * return 'int'; + * } + * + * public function getValueType() + * { + * return Foo::class; + * } + * } + * ``` + * + * … but you also may use the `TypedMap` class: + * + * ```php + * class FooTypedMap extends TypedMap + * { + * public function __constructor(array $data = []) + * { + * parent::__construct('int', Foo::class, $data); + * } + * } + * ``` + * + * @template K + * @template T + * @extends AbstractTypedMap + */ +class TypedMap extends AbstractTypedMap +{ + use TypeTrait; + + /** + * The data type of keys stored in this collection. + * + * A map key's type is immutable once it is set. For this reason, this + * property is set private. + * + * @var string data type of the map key. + */ + private $keyType; + + /** + * The data type of values stored in this collection. + * + * A map value's type is immutable once it is set. For this reason, this + * property is set private. + * + * @var string data type of the map value. + */ + private $valueType; + + /** + * Constructs a map object of the specified key and value types, + * optionally with the specified data. + * + * @param string $keyType The data type of the map's keys. + * @param string $valueType The data type of the map's values. + * @param array $data The initial data to set for this map. + */ + public function __construct(string $keyType, string $valueType, array $data = []) + { + $this->keyType = $keyType; + $this->valueType = $valueType; + + /** @psalm-suppress MixedArgumentTypeCoercion */ + parent::__construct($data); + } + + public function getKeyType(): string + { + return $this->keyType; + } + + public function getValueType(): string + { + return $this->valueType; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMapInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMapInterface.php new file mode 100644 index 00000000..0308109c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Map/TypedMapInterface.php @@ -0,0 +1,35 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Map; + +/** + * A `TypedMapInterface` represents a map of elements where key and value are + * typed. + * + * @template T + * @extends MapInterface + */ +interface TypedMapInterface extends MapInterface +{ + /** + * Return the type used on the key. + */ + public function getKeyType(): string; + + /** + * Return the type forced on the values. + */ + public function getValueType(): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Queue.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Queue.php new file mode 100644 index 00000000..93e032b4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Queue.php @@ -0,0 +1,169 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +use Ramsey\Collection\Exception\InvalidArgumentException; +use Ramsey\Collection\Exception\NoSuchElementException; +use Ramsey\Collection\Tool\TypeTrait; +use Ramsey\Collection\Tool\ValueToStringTrait; + +/** + * This class provides a basic implementation of `QueueInterface`, to minimize + * the effort required to implement this interface. + * + * @template T + * @extends AbstractArray + * @implements QueueInterface + */ +class Queue extends AbstractArray implements QueueInterface +{ + use TypeTrait; + use ValueToStringTrait; + + /** + * The type of elements stored in this queue. + * + * A queue's type is immutable once it is set. For this reason, this + * property is set private. + * + * @var string + */ + private $queueType; + + /** + * The index of the head of the queue. + * + * @var int + */ + protected $index = 0; + + /** + * Constructs a queue object of the specified type, optionally with the + * specified data. + * + * @param string $queueType The type (FQCN) associated with this queue. + * @param array $data The initial items to store in the collection. + */ + public function __construct(string $queueType, array $data = []) + { + $this->queueType = $queueType; + parent::__construct($data); + } + + /** + * {@inheritDoc} + * + * Since arbitrary offsets may not be manipulated in a queue, this method + * serves only to fulfill the `ArrayAccess` interface requirements. It is + * invoked by other operations when adding values to the queue. + */ + public function offsetSet($offset, $value): void + { + if ($this->checkType($this->getType(), $value) === false) { + throw new InvalidArgumentException( + 'Value must be of type ' . $this->getType() . '; value is ' + . $this->toolValueToString($value) + ); + } + + $this->data[] = $value; + } + + /** + * @inheritDoc + */ + public function add($element): bool + { + $this[] = $element; + + return true; + } + + /** + * @inheritDoc + */ + public function element() + { + $element = $this->peek(); + + if ($element === null) { + throw new NoSuchElementException( + 'Can\'t return element from Queue. Queue is empty.' + ); + } + + return $element; + } + + /** + * @inheritDoc + */ + public function offer($element): bool + { + try { + return $this->add($element); + } catch (InvalidArgumentException $e) { + return false; + } + } + + /** + * @inheritDoc + */ + public function peek() + { + if ($this->count() === 0) { + return null; + } + + return $this[$this->index]; + } + + /** + * @inheritDoc + */ + public function poll() + { + if ($this->count() === 0) { + return null; + } + + $head = $this[$this->index]; + + unset($this[$this->index]); + $this->index++; + + return $head; + } + + /** + * @inheritDoc + */ + public function remove() + { + $head = $this->poll(); + + if ($head === null) { + throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.'); + } + + return $head; + } + + public function getType(): string + { + return $this->queueType; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/QueueInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/QueueInterface.php new file mode 100644 index 00000000..8c7383df --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/QueueInterface.php @@ -0,0 +1,203 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +use Ramsey\Collection\Exception\NoSuchElementException; + +/** + * A queue is a collection in which the entities in the collection are kept in + * order. + * + * The principal operations on the queue are the addition of entities to the end + * (tail), also known as *enqueue*, and removal of entities from the front + * (head), also known as *dequeue*. This makes the queue a first-in-first-out + * (FIFO) data structure. + * + * Besides basic array operations, queues provide additional insertion, + * extraction, and inspection operations. Each of these methods exists in two + * forms: one throws an exception if the operation fails, the other returns a + * special value (either `null` or `false`, depending on the operation). The + * latter form of the insert operation is designed specifically for use with + * capacity-restricted `QueueInterface` implementations; in most + * implementations, insert operations cannot fail. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Summary of QueueInterface methods
Throws exceptionReturns special value
Insertadd()offer()
Removeremove()poll()
Examineelement()peek()
+ * + * Queues typically, but do not necessarily, order elements in a FIFO + * (first-in-first-out) manner. Among the exceptions are priority queues, which + * order elements according to a supplied comparator, or the elements' natural + * ordering, and LIFO queues (or stacks) which order the elements LIFO + * (last-in-first-out). Whatever the ordering used, the head of the queue is + * that element which would be removed by a call to remove() or poll(). In a + * FIFO queue, all new elements are inserted at the tail of the queue. Other + * kinds of queues may use different placement rules. Every `QueueInterface` + * implementation must specify its ordering properties. + * + * The `offer()` method inserts an element if possible, otherwise returning + * `false`. This differs from the `add()` method, which can fail to add an + * element only by throwing an unchecked exception. The `offer()` method is + * designed for use when failure is a normal, rather than exceptional + * occurrence, for example, in fixed-capacity (or "bounded") queues. + * + * The `remove()` and `poll()` methods remove and return the head of the queue. + * Exactly which element is removed from the queue is a function of the queue's + * ordering policy, which differs from implementation to implementation. The + * `remove()` and `poll()` methods differ only in their behavior when the queue + * is empty: the `remove()` method throws an exception, while the `poll()` + * method returns `null`. + * + * The `element()` and `peek()` methods return, but do not remove, the head of + * the queue. + * + * `QueueInterface` implementations generally do not allow insertion of `null` + * elements, although some implementations do not prohibit insertion of `null`. + * Even in the implementations that permit it, `null` should not be inserted + * into a queue, as `null` is also used as a special return value by the + * `poll()` method to indicate that the queue contains no elements. + * + * @template T + * @extends ArrayInterface + */ +interface QueueInterface extends ArrayInterface +{ + /** + * Ensures that this queue contains the specified element (optional + * operation). + * + * Returns `true` if this queue changed as a result of the call. (Returns + * `false` if this queue does not permit duplicates and already contains the + * specified element.) + * + * Queues that support this operation may place limitations on what elements + * may be added to this queue. In particular, some queues will refuse to add + * `null` elements, and others will impose restrictions on the type of + * elements that may be added. Queue classes should clearly specify in their + * documentation any restrictions on what elements may be added. + * + * If a queue refuses to add a particular element for any reason other than + * that it already contains the element, it must throw an exception (rather + * than returning `false`). This preserves the invariant that a queue always + * contains the specified element after this call returns. + * + * @see self::offer() + * + * @param T $element The element to add to this queue. + * + * @return bool `true` if this queue changed as a result of the call. + * + * @throws \RuntimeException if a queue refuses to add a particular element + * for any reason other than that it already contains the element. + * Implementations should use a more-specific exception that extends + * `\RuntimeException`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function add($element): bool; + + /** + * Retrieves, but does not remove, the head of this queue. + * + * This method differs from `peek()` only in that it throws an exception if + * this queue is empty. + * + * @see self::peek() + * + * @return T the head of this queue. + * + * @throws NoSuchElementException if this queue is empty. + */ + public function element(); + + /** + * Inserts the specified element into this queue if it is possible to do so + * immediately without violating capacity restrictions. + * + * When using a capacity-restricted queue, this method is generally + * preferable to `add()`, which can fail to insert an element only by + * throwing an exception. + * + * @see self::add() + * + * @param T $element The element to add to this queue. + * + * @return bool `true` if the element was added to this queue, else `false`. + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function offer($element): bool; + + /** + * Retrieves, but does not remove, the head of this queue, or returns `null` + * if this queue is empty. + * + * @see self::element() + * + * @return T|null the head of this queue, or `null` if this queue is empty. + */ + public function peek(); + + /** + * Retrieves and removes the head of this queue, or returns `null` + * if this queue is empty. + * + * @see self::remove() + * + * @return T|null the head of this queue, or `null` if this queue is empty. + */ + public function poll(); + + /** + * Retrieves and removes the head of this queue. + * + * This method differs from `poll()` only in that it throws an exception if + * this queue is empty. + * + * @see self::poll() + * + * @return T the head of this queue. + * + * @throws NoSuchElementException if this queue is empty. + */ + public function remove(); + + /** + * Returns the type associated with this queue. + */ + public function getType(): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Set.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Set.php new file mode 100644 index 00000000..6932f247 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Set.php @@ -0,0 +1,69 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection; + +/** + * A set is a collection that contains no duplicate elements. + * + * Great care must be exercised if mutable objects are used as set elements. + * The behavior of a set is not specified if the value of an object is changed + * in a manner that affects equals comparisons while the object is an element in + * the set. + * + * Example usage: + * + * ``` php + * $foo = new \My\Foo(); + * $set = new Set(\My\Foo::class); + * + * $set->add($foo); // returns TRUE, the element don't exists + * $set->add($foo); // returns FALSE, the element already exists + * + * $bar = new \My\Foo(); + * $set->add($bar); // returns TRUE, $bar !== $foo + * ``` + * + * @template T + * @extends AbstractSet + */ +class Set extends AbstractSet +{ + /** + * The type of elements stored in this set + * + * A set's type is immutable. For this reason, this property is private. + * + * @var string + */ + private $setType; + + /** + * Constructs a set object of the specified type, optionally with the + * specified data. + * + * @param string $setType The type (FQCN) associated with this set. + * @param array $data The initial items to store in the set. + */ + public function __construct(string $setType, array $data = []) + { + $this->setType = $setType; + parent::__construct($data); + } + + public function getType(): string + { + return $this->setType; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/TypeTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/TypeTrait.php new file mode 100644 index 00000000..8214e965 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/TypeTrait.php @@ -0,0 +1,73 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Tool; + +use function is_array; +use function is_bool; +use function is_callable; +use function is_float; +use function is_int; +use function is_numeric; +use function is_object; +use function is_resource; +use function is_scalar; +use function is_string; + +/** + * Provides functionality to check values for specific types. + */ +trait TypeTrait +{ + /** + * Returns `true` if value is of the specified type. + * + * @param string $type The type to check the value against. + * @param mixed $value The value to check. + */ + protected function checkType(string $type, $value): bool + { + switch ($type) { + case 'array': + return is_array($value); + case 'bool': + case 'boolean': + return is_bool($value); + case 'callable': + return is_callable($value); + case 'float': + case 'double': + return is_float($value); + case 'int': + case 'integer': + return is_int($value); + case 'null': + return $value === null; + case 'numeric': + return is_numeric($value); + case 'object': + return is_object($value); + case 'resource': + return is_resource($value); + case 'scalar': + return is_scalar($value); + case 'string': + return is_string($value); + case 'mixed': + return true; + default: + return $value instanceof $type; + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php new file mode 100644 index 00000000..f9be1be2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php @@ -0,0 +1,58 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Tool; + +use Ramsey\Collection\Exception\ValueExtractionException; + +use function get_class; +use function method_exists; +use function property_exists; +use function sprintf; + +/** + * Provides functionality to extract the value of a property or method from an object. + */ +trait ValueExtractorTrait +{ + /** + * Extracts the value of the given property or method from the object. + * + * @param mixed $object The object to extract the value from. + * @param string $propertyOrMethod The property or method for which the + * value should be extracted. + * + * @return mixed the value extracted from the specified property or method. + * + * @throws ValueExtractionException if the method or property is not defined. + */ + protected function extractValue($object, string $propertyOrMethod) + { + if (!is_object($object)) { + throw new ValueExtractionException('Unable to extract a value from a non-object'); + } + + if (property_exists($object, $propertyOrMethod)) { + return $object->$propertyOrMethod; + } + + if (method_exists($object, $propertyOrMethod)) { + return $object->{$propertyOrMethod}(); + } + + throw new ValueExtractionException( + sprintf('Method or property "%s" not defined in %s', $propertyOrMethod, get_class($object)) + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php new file mode 100644 index 00000000..721ade00 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php @@ -0,0 +1,94 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Collection\Tool; + +use DateTimeInterface; + +use function get_class; +use function get_resource_type; +use function is_array; +use function is_bool; +use function is_callable; +use function is_resource; +use function is_scalar; + +/** + * Provides functionality to express a value as string + */ +trait ValueToStringTrait +{ + /** + * Returns a string representation of the value. + * + * - null value: `'NULL'` + * - boolean: `'TRUE'`, `'FALSE'` + * - array: `'Array'` + * - scalar: converted-value + * - resource: `'(type resource #number)'` + * - object with `__toString()`: result of `__toString()` + * - object DateTime: ISO 8601 date + * - object: `'(className Object)'` + * - anonymous function: same as object + * + * @param mixed $value the value to return as a string. + */ + protected function toolValueToString($value): string + { + // null + if ($value === null) { + return 'NULL'; + } + + // boolean constants + if (is_bool($value)) { + return $value ? 'TRUE' : 'FALSE'; + } + + // array + if (is_array($value)) { + return 'Array'; + } + + // scalar types (integer, float, string) + if (is_scalar($value)) { + return (string) $value; + } + + // resource + if (is_resource($value)) { + return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')'; + } + + // If we don't know what it is, use var_export(). + if (!is_object($value)) { + return '(' . var_export($value, true) . ')'; + } + + // From here, $value should be an object. + + // __toString() is implemented + if (is_callable([$value, '__toString'])) { + return (string) $value->__toString(); + } + + // object of type \DateTime + if ($value instanceof DateTimeInterface) { + return $value->format('c'); + } + + // unknown type + return '(' . get_class($value) . ' Object)'; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/LICENSE b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/LICENSE new file mode 100644 index 00000000..5e06cf43 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012-2021 Ben Ramsey + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/README.md b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/README.md new file mode 100644 index 00000000..97e81a50 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/README.md @@ -0,0 +1,83 @@ +

ramsey/uuid

+ +

+ A PHP library for generating and working with UUIDs. +

+ +

+ Source Code + Download Package + PHP Programming Language + Read License + Build Status + Codecov Code Coverage + Psalm Type Coverage +

+ +ramsey/uuid is a PHP library for generating and working with universally unique +identifiers (UUIDs). + +This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). +By participating in this project and its community, you are expected to +uphold this code. + +Much inspiration for this library came from the [Java][javauuid] and +[Python][pyuuid] UUID libraries. + +## Installation + +The preferred method of installation is via [Composer][]. Run the following +command to install the package and add it as a requirement to your project's +`composer.json`: + +```bash +composer require ramsey/uuid +``` + +## Upgrading to Version 4 + +See the documentation for a thorough upgrade guide: + +* [Upgrading ramsey/uuid Version 3 to 4](https://uuid.ramsey.dev/en/latest/upgrading/3-to-4.html) + +## Documentation + +Please see for documentation, tips, examples, and +frequently asked questions. + +## Contributing + +Contributions are welcome! To contribute, please familiarize yourself with +[CONTRIBUTING.md](CONTRIBUTING.md). + +## Coordinated Disclosure + +Keeping user information safe and secure is a top priority, and we welcome the +contribution of external security researchers. If you believe you've found a +security issue in software that is maintained in this repository, please read +[SECURITY.md][] for instructions on submitting a vulnerability report. + +## ramsey/uuid for Enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of ramsey/uuid and thousands of other packages are working with +Tidelift to deliver commercial support and maintenance for the open source +packages you use to build your applications. Save time, reduce risk, and improve +code health, while paying the maintainers of the exact packages you use. +[Learn more.](https://tidelift.com/subscription/pkg/packagist-ramsey-uuid?utm_source=undefined&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +## Copyright and License + +The ramsey/uuid library is copyright © [Ben Ramsey](https://benramsey.com/) and +licensed for use under the MIT License (MIT). Please see [LICENSE][] for more +information. + +[rfc4122]: http://tools.ietf.org/html/rfc4122 +[conduct]: https://github.com/ramsey/uuid/blob/main/CODE_OF_CONDUCT.md +[javauuid]: http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html +[pyuuid]: http://docs.python.org/3/library/uuid.html +[composer]: http://getcomposer.org/ +[contributing.md]: https://github.com/ramsey/uuid/blob/main/CONTRIBUTING.md +[security.md]: https://github.com/ramsey/uuid/blob/main/SECURITY.md +[license]: https://github.com/ramsey/uuid/blob/main/LICENSE diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/composer.json b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/composer.json new file mode 100644 index 00000000..3f3b5ac4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/composer.json @@ -0,0 +1,107 @@ +{ + "name": "ramsey/uuid", + "type": "library", + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "uuid", + "identifier", + "guid" + ], + "license": "MIT", + "require": { + "php": "^7.2 || ^8.0", + "ext-json": "*", + "brick/math": "^0.8 || ^0.9", + "ramsey/collection": "^1.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php80": "^1.14" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "moontoast/math": "^1.1", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5 || ^9", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-ctype": "Enables faster processing of character classification using ctype functions.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "config": { + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-main": "4.x-dev" + }, + "captainhook": { + "force-install": true + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Uuid\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "autoload-dev": { + "psr-4": { + "Ramsey\\Uuid\\Benchmark\\": "tests/benchmark/", + "Ramsey\\Uuid\\StaticAnalysis\\": "tests/static-analysis/", + "Ramsey\\Uuid\\Test\\": "tests/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "scripts": { + "analyze": [ + "@phpstan", + "@psalm" + ], + "build:clean": "git clean -fX build/", + "lint": "parallel-lint src tests", + "lint:paths": "parallel-lint", + "phpbench": "phpbench run", + "phpcbf": "phpcbf -vpw --cache=build/cache/phpcs.cache", + "phpcs": "phpcs --cache=build/cache/phpcs.cache", + "phpstan": [ + "phpstan analyse --no-progress", + "phpstan analyse -c phpstan-tests.neon --no-progress" + ], + "phpunit": "phpunit --verbose --colors=always", + "phpunit-coverage": "phpunit --verbose --colors=always --coverage-html build/coverage", + "psalm": "psalm --show-info=false --config=psalm.xml", + "test": [ + "@lint", + "@phpbench", + "@phpcs", + "@phpstan", + "@psalm", + "@phpunit" + ] + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/BinaryUtils.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/BinaryUtils.php new file mode 100644 index 00000000..fb8ba9ad --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/BinaryUtils.php @@ -0,0 +1,63 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +/** + * Provides binary math utilities + */ +class BinaryUtils +{ + /** + * Applies the RFC 4122 variant field to the 16-bit clock sequence + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant + * + * @param int $clockSeq The 16-bit clock sequence value before the RFC 4122 + * variant is applied + * + * @return int The 16-bit clock sequence multiplexed with the UUID variant + * + * @psalm-pure + */ + public static function applyVariant(int $clockSeq): int + { + $clockSeq = $clockSeq & 0x3fff; + $clockSeq |= 0x8000; + + return $clockSeq; + } + + /** + * Applies the RFC 4122 version number to the 16-bit `time_hi_and_version` field + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version + * + * @param int $timeHi The value of the 16-bit `time_hi_and_version` field + * before the RFC 4122 version is applied + * @param int $version The RFC 4122 version to apply to the `time_hi` field + * + * @return int The 16-bit time_hi field of the timestamp multiplexed with + * the UUID version number + * + * @psalm-pure + */ + public static function applyVersion(int $timeHi, int $version): int + { + $timeHi = $timeHi & 0x0fff; + $timeHi |= $version << 12; + + return $timeHi; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/BuilderCollection.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/BuilderCollection.php new file mode 100644 index 00000000..89fa1e3c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/BuilderCollection.php @@ -0,0 +1,80 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Builder; + +use Ramsey\Collection\AbstractCollection; +use Ramsey\Uuid\Converter\Number\GenericNumberConverter; +use Ramsey\Uuid\Converter\Time\GenericTimeConverter; +use Ramsey\Uuid\Converter\Time\PhpTimeConverter; +use Ramsey\Uuid\Guid\GuidBuilder; +use Ramsey\Uuid\Math\BrickMathCalculator; +use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder; +use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder; +use Traversable; + +/** + * A collection of UuidBuilderInterface objects + * + * @extends AbstractCollection + */ +class BuilderCollection extends AbstractCollection +{ + public function getType(): string + { + return UuidBuilderInterface::class; + } + + /** + * @psalm-mutation-free + * @psalm-suppress ImpureMethodCall + * @psalm-suppress InvalidTemplateParam + */ + public function getIterator(): Traversable + { + return parent::getIterator(); + } + + /** + * Re-constructs the object from its serialized form + * + * @param string $serialized The serialized PHP string to unserialize into + * a UuidInterface instance + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @psalm-suppress RedundantConditionGivenDocblockType + */ + public function unserialize($serialized): void + { + /** @var array $data */ + $data = unserialize($serialized, [ + 'allowed_classes' => [ + BrickMathCalculator::class, + GenericNumberConverter::class, + GenericTimeConverter::class, + GuidBuilder::class, + NonstandardUuidBuilder::class, + PhpTimeConverter::class, + Rfc4122UuidBuilder::class, + ], + ]); + + $this->data = array_filter( + $data, + function ($unserialized): bool { + return $unserialized instanceof UuidBuilderInterface; + } + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php new file mode 100644 index 00000000..7c4a6f83 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php @@ -0,0 +1,26 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Builder; + +use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder; + +/** + * @deprecated Transition to {@see Rfc4122UuidBuilder}. + * + * @psalm-immutable + */ +class DefaultUuidBuilder extends Rfc4122UuidBuilder +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php new file mode 100644 index 00000000..23931e41 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php @@ -0,0 +1,76 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Builder; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\Time\DegradedTimeConverter; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\DegradedUuid; +use Ramsey\Uuid\Rfc4122\Fields as Rfc4122Fields; +use Ramsey\Uuid\UuidInterface; + +/** + * @deprecated DegradedUuid instances are no longer necessary to support 32-bit + * systems. Transition to {@see DefaultUuidBuilder}. + * + * @psalm-immutable + */ +class DegradedUuidBuilder implements UuidBuilderInterface +{ + /** + * @var NumberConverterInterface + */ + private $numberConverter; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * @param NumberConverterInterface $numberConverter The number converter to + * use when constructing the DegradedUuid + * @param TimeConverterInterface|null $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to Unix timestamps + */ + public function __construct( + NumberConverterInterface $numberConverter, + ?TimeConverterInterface $timeConverter = null + ) { + $this->numberConverter = $numberConverter; + $this->timeConverter = $timeConverter ?: new DegradedTimeConverter(); + } + + /** + * Builds and returns a DegradedUuid + * + * @param CodecInterface $codec The codec to use for building this DegradedUuid instance + * @param string $bytes The byte string from which to construct a UUID + * + * @return DegradedUuid The DegradedUuidBuild returns an instance of Ramsey\Uuid\DegradedUuid + * + * @psalm-pure + */ + public function build(CodecInterface $codec, string $bytes): UuidInterface + { + return new DegradedUuid( + new Rfc4122Fields($bytes), + $this->numberConverter, + $codec, + $this->timeConverter + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php new file mode 100644 index 00000000..470d2f75 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php @@ -0,0 +1,74 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Builder; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Exception\BuilderNotFoundException; +use Ramsey\Uuid\Exception\UnableToBuildUuidException; +use Ramsey\Uuid\UuidInterface; + +/** + * FallbackBuilder builds a UUID by stepping through a list of UUID builders + * until a UUID can be constructed without exceptions + * + * @psalm-immutable + */ +class FallbackBuilder implements UuidBuilderInterface +{ + /** + * @var BuilderCollection + */ + private $builders; + + /** + * @param BuilderCollection $builders An array of UUID builders + */ + public function __construct(BuilderCollection $builders) + { + $this->builders = $builders; + } + + /** + * Builds and returns a UuidInterface instance using the first builder that + * succeeds + * + * @param CodecInterface $codec The codec to use for building this instance + * @param string $bytes The byte string from which to construct a UUID + * + * @return UuidInterface an instance of a UUID object + * + * @psalm-pure + */ + public function build(CodecInterface $codec, string $bytes): UuidInterface + { + $lastBuilderException = null; + + foreach ($this->builders as $builder) { + try { + return $builder->build($codec, $bytes); + } catch (UnableToBuildUuidException $exception) { + $lastBuilderException = $exception; + + continue; + } + } + + throw new BuilderNotFoundException( + 'Could not find a suitable builder for the provided codec and fields', + 0, + $lastBuilderException + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php new file mode 100644 index 00000000..8e58b2b4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php @@ -0,0 +1,39 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Builder; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\UuidInterface; + +/** + * A UUID builder builds instances of UuidInterface + * + * @psalm-immutable + */ +interface UuidBuilderInterface +{ + /** + * Builds and returns a UuidInterface + * + * @param CodecInterface $codec The codec to use for building this UuidInterface instance + * @param string $bytes The byte string from which to construct a UUID + * + * @return UuidInterface Implementations may choose to return more specific + * instances of UUIDs that implement UuidInterface + * + * @psalm-pure + */ + public function build(CodecInterface $codec, string $bytes): UuidInterface; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/CodecInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/CodecInterface.php new file mode 100644 index 00000000..85f8a7e9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/CodecInterface.php @@ -0,0 +1,71 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Codec; + +use Ramsey\Uuid\UuidInterface; + +/** + * A codec encodes and decodes a UUID according to defined rules + * + * @psalm-immutable + */ +interface CodecInterface +{ + /** + * Returns a hexadecimal string representation of a UuidInterface + * + * @param UuidInterface $uuid The UUID for which to create a hexadecimal + * string representation + * + * @return string Hexadecimal string representation of a UUID + * + * @psalm-return non-empty-string + */ + public function encode(UuidInterface $uuid): string; + + /** + * Returns a binary string representation of a UuidInterface + * + * @param UuidInterface $uuid The UUID for which to create a binary string + * representation + * + * @return string Binary string representation of a UUID + * + * @psalm-return non-empty-string + */ + public function encodeBinary(UuidInterface $uuid): string; + + /** + * Returns a UuidInterface derived from a hexadecimal string representation + * + * @param string $encodedUuid The hexadecimal string representation to + * convert into a UuidInterface instance + * + * @return UuidInterface An instance of a UUID decoded from a hexadecimal + * string representation + */ + public function decode(string $encodedUuid): UuidInterface; + + /** + * Returns a UuidInterface derived from a binary string representation + * + * @param string $bytes The binary string representation to convert into a + * UuidInterface instance + * + * @return UuidInterface An instance of a UUID decoded from a binary string + * representation + */ + public function decodeBytes(string $bytes): UuidInterface; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php new file mode 100644 index 00000000..f11e9d50 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php @@ -0,0 +1,55 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Codec; + +use Ramsey\Uuid\Guid\Guid; +use Ramsey\Uuid\UuidInterface; + +use function bin2hex; +use function substr; + +/** + * GuidStringCodec encodes and decodes globally unique identifiers (GUID) + * + * @see Guid + * + * @psalm-immutable + */ +class GuidStringCodec extends StringCodec +{ + public function decode(string $encodedUuid): UuidInterface + { + $bytes = $this->getBytes($encodedUuid); + + return $this->getBuilder()->build($this, $this->swapBytes($bytes)); + } + + public function decodeBytes(string $bytes): UuidInterface + { + // Specifically call parent::decode to preserve correct byte order + return parent::decode(bin2hex($bytes)); + } + + /** + * Swaps bytes according to the GUID rules + */ + private function swapBytes(string $bytes): string + { + return $bytes[3] . $bytes[2] . $bytes[1] . $bytes[0] + . $bytes[5] . $bytes[4] + . $bytes[7] . $bytes[6] + . substr($bytes, 8); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php new file mode 100644 index 00000000..0798ebc4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php @@ -0,0 +1,113 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Codec; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Exception\UnsupportedOperationException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +use function strlen; +use function substr; + +/** + * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for + * more efficient storage + * + * For binary representations of version 1 UUID, this codec may be used to + * reorganize the time fields, making the UUID closer to sequential when storing + * the bytes. According to Percona, this optimization can improve database + * INSERTs and SELECTs using the UUID column as a key. + * + * The string representation of the UUID will remain unchanged. Only the binary + * representation is reordered. + * + * **PLEASE NOTE:** Binary representations of UUIDs encoded with this codec must + * be decoded with this codec. Decoding using another codec can result in + * malformed UUIDs. + * + * @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ Storing UUID Values in MySQL + * + * @psalm-immutable + */ +class OrderedTimeCodec extends StringCodec +{ + /** + * Returns a binary string representation of a UUID, with the timestamp + * fields rearranged for optimized storage + * + * @inheritDoc + * @psalm-return non-empty-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function encodeBinary(UuidInterface $uuid): string + { + if ( + !($uuid->getFields() instanceof Rfc4122FieldsInterface) + || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME + ) { + throw new InvalidArgumentException( + 'Expected RFC 4122 version 1 (time-based) UUID' + ); + } + + $bytes = $uuid->getFields()->getBytes(); + + /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */ + return $bytes[6] . $bytes[7] + . $bytes[4] . $bytes[5] + . $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3] + . substr($bytes, 8); + } + + /** + * Returns a UuidInterface derived from an ordered-time binary string + * representation + * + * @throws InvalidArgumentException if $bytes is an invalid length + * + * @inheritDoc + */ + public function decodeBytes(string $bytes): UuidInterface + { + if (strlen($bytes) !== 16) { + throw new InvalidArgumentException( + '$bytes string should contain 16 characters.' + ); + } + + // Rearrange the bytes to their original order. + $rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7] + . $bytes[2] . $bytes[3] + . $bytes[0] . $bytes[1] + . substr($bytes, 8); + + $uuid = parent::decodeBytes($rearrangedBytes); + + if ( + !($uuid->getFields() instanceof Rfc4122FieldsInterface) + || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME + ) { + throw new UnsupportedOperationException( + 'Attempting to decode a non-time-based UUID using ' + . 'OrderedTimeCodec' + ); + } + + return $uuid; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/StringCodec.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/StringCodec.php new file mode 100644 index 00000000..58c9f580 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/StringCodec.php @@ -0,0 +1,138 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Codec; + +use Ramsey\Uuid\Builder\UuidBuilderInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Exception\InvalidUuidStringException; +use Ramsey\Uuid\Rfc4122\FieldsInterface; +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +use function hex2bin; +use function implode; +use function str_replace; +use function strlen; +use function substr; + +/** + * StringCodec encodes and decodes RFC 4122 UUIDs + * + * @link http://tools.ietf.org/html/rfc4122 + * + * @psalm-immutable + */ +class StringCodec implements CodecInterface +{ + /** + * @var UuidBuilderInterface + */ + private $builder; + + /** + * Constructs a StringCodec + * + * @param UuidBuilderInterface $builder The builder to use when encoding UUIDs + */ + public function __construct(UuidBuilderInterface $builder) + { + $this->builder = $builder; + } + + public function encode(UuidInterface $uuid): string + { + /** @var FieldsInterface $fields */ + $fields = $uuid->getFields(); + + return $fields->getTimeLow()->toString() + . '-' + . $fields->getTimeMid()->toString() + . '-' + . $fields->getTimeHiAndVersion()->toString() + . '-' + . $fields->getClockSeqHiAndReserved()->toString() + . $fields->getClockSeqLow()->toString() + . '-' + . $fields->getNode()->toString(); + } + + /** + * @psalm-return non-empty-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function encodeBinary(UuidInterface $uuid): string + { + /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */ + return $uuid->getFields()->getBytes(); + } + + /** + * @throws InvalidUuidStringException + * + * @inheritDoc + */ + public function decode(string $encodedUuid): UuidInterface + { + return $this->builder->build($this, $this->getBytes($encodedUuid)); + } + + public function decodeBytes(string $bytes): UuidInterface + { + if (strlen($bytes) !== 16) { + throw new InvalidArgumentException( + '$bytes string should contain 16 characters.' + ); + } + + return $this->builder->build($this, $bytes); + } + + /** + * Returns the UUID builder + */ + protected function getBuilder(): UuidBuilderInterface + { + return $this->builder; + } + + /** + * Returns a byte string of the UUID + */ + protected function getBytes(string $encodedUuid): string + { + $parsedUuid = str_replace( + ['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'], + '', + $encodedUuid + ); + + $components = [ + substr($parsedUuid, 0, 8), + substr($parsedUuid, 8, 4), + substr($parsedUuid, 12, 4), + substr($parsedUuid, 16, 4), + substr($parsedUuid, 20), + ]; + + if (!Uuid::isValid(implode('-', $components))) { + throw new InvalidUuidStringException( + 'Invalid UUID string: ' . $encodedUuid + ); + } + + return (string) hex2bin($parsedUuid); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php new file mode 100644 index 00000000..0e0042d0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php @@ -0,0 +1,113 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Codec; + +use Ramsey\Uuid\Exception\InvalidUuidStringException; +use Ramsey\Uuid\UuidInterface; + +use function bin2hex; +use function sprintf; +use function substr; +use function substr_replace; + +/** + * TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the + * first 48 bits + * + * In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec + * adds the timestamp to the first 48 bits of the COMB. To generate a + * timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along + * with the CombGenerator as the random generator. + * + * ``` php + * $factory = new UuidFactory(); + * + * $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder())); + * + * $factory->setRandomGenerator(new CombGenerator( + * $factory->getRandomGenerator(), + * $factory->getNumberConverter() + * )); + * + * $timestampFirstComb = $factory->uuid4(); + * ``` + * + * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys + * + * @psalm-immutable + */ +class TimestampFirstCombCodec extends StringCodec +{ + /** + * @psalm-return non-empty-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function encode(UuidInterface $uuid): string + { + $bytes = $this->swapBytes($uuid->getFields()->getBytes()); + + return sprintf( + '%08s-%04s-%04s-%04s-%012s', + bin2hex(substr($bytes, 0, 4)), + bin2hex(substr($bytes, 4, 2)), + bin2hex(substr($bytes, 6, 2)), + bin2hex(substr($bytes, 8, 2)), + bin2hex(substr($bytes, 10)) + ); + } + + /** + * @psalm-return non-empty-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function encodeBinary(UuidInterface $uuid): string + { + /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */ + return $this->swapBytes($uuid->getFields()->getBytes()); + } + + /** + * @throws InvalidUuidStringException + * + * @inheritDoc + */ + public function decode(string $encodedUuid): UuidInterface + { + $bytes = $this->getBytes($encodedUuid); + + return $this->getBuilder()->build($this, $this->swapBytes($bytes)); + } + + public function decodeBytes(string $bytes): UuidInterface + { + return $this->getBuilder()->build($this, $this->swapBytes($bytes)); + } + + /** + * Swaps bytes according to the timestamp-first COMB rules + */ + private function swapBytes(string $bytes): string + { + $first48Bits = substr($bytes, 0, 6); + $last48Bits = substr($bytes, -6); + + $bytes = substr_replace($bytes, $last48Bits, 0, 6); + $bytes = substr_replace($bytes, $first48Bits, -6); + + return $bytes; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php new file mode 100644 index 00000000..4856deae --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php @@ -0,0 +1,51 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Codec; + +/** + * TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the + * last 48 bits + * + * The CombGenerator when used with the StringCodec (and, by proxy, the + * TimestampLastCombCodec) adds the timestamp to the last 48 bits of the COMB. + * The TimestampLastCombCodec is provided for the sake of consistency. In + * practice, it is identical to the standard StringCodec but, it may be used + * with the CombGenerator for additional context when reading code. + * + * Consider the following code. By default, the codec used by UuidFactory is the + * StringCodec, but here, we explicitly set the TimestampLastCombCodec. It is + * redundant, but it is clear that we intend this COMB to be generated with the + * timestamp appearing at the end. + * + * ``` php + * $factory = new UuidFactory(); + * + * $factory->setCodec(new TimestampLastCombCodec($factory->getUuidBuilder())); + * + * $factory->setRandomGenerator(new CombGenerator( + * $factory->getRandomGenerator(), + * $factory->getNumberConverter() + * )); + * + * $timestampLastComb = $factory->uuid4(); + * ``` + * + * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys + * + * @psalm-immutable + */ +class TimestampLastCombCodec extends StringCodec +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php new file mode 100644 index 00000000..fef63fd0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php @@ -0,0 +1,57 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter\Number; + +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Math\BrickMathCalculator; + +/** + * Previously used to integrate moontoast/math as a bignum arithmetic library, + * BigNumberConverter is deprecated in favor of GenericNumberConverter + * + * @deprecated Transition to {@see GenericNumberConverter}. + * + * @psalm-immutable + */ +class BigNumberConverter implements NumberConverterInterface +{ + /** + * @var NumberConverterInterface + */ + private $converter; + + public function __construct() + { + $this->converter = new GenericNumberConverter(new BrickMathCalculator()); + } + + /** + * @inheritDoc + * @psalm-pure + */ + public function fromHex(string $hex): string + { + return $this->converter->fromHex($hex); + } + + /** + * @inheritDoc + * @psalm-pure + */ + public function toHex(string $number): string + { + return $this->converter->toHex($number); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php new file mode 100644 index 00000000..c9cfa686 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter\Number; + +/** + * @deprecated DegradedNumberConverter is no longer necessary for converting + * numbers on 32-bit systems. Transition to {@see GenericNumberConverter}. + * + * @psalm-immutable + */ +class DegradedNumberConverter extends BigNumberConverter +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php new file mode 100644 index 00000000..501eac0f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php @@ -0,0 +1,63 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter\Number; + +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Math\CalculatorInterface; +use Ramsey\Uuid\Type\Integer as IntegerObject; + +/** + * GenericNumberConverter uses the provided calculator to convert decimal + * numbers to and from hexadecimal values + * + * @psalm-immutable + */ +class GenericNumberConverter implements NumberConverterInterface +{ + /** + * @var CalculatorInterface + */ + private $calculator; + + public function __construct(CalculatorInterface $calculator) + { + $this->calculator = $calculator; + } + + /** + * @inheritDoc + * @psalm-pure + * @psalm-return numeric-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function fromHex(string $hex): string + { + return $this->calculator->fromBase($hex, 16)->toString(); + } + + /** + * @inheritDoc + * @psalm-pure + * @psalm-return non-empty-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function toHex(string $number): string + { + /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */ + return $this->calculator->toBase(new IntegerObject($number), 16); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php new file mode 100644 index 00000000..b33ec31f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php @@ -0,0 +1,57 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter; + +/** + * A number converter converts UUIDs from hexadecimal characters into + * representations of integers and vice versa + * + * @psalm-immutable + */ +interface NumberConverterInterface +{ + /** + * Converts a hexadecimal number into an string integer representation of + * the number + * + * The integer representation returned is a string representation of the + * integer, to accommodate unsigned integers greater than PHP_INT_MAX. + * + * @param string $hex The hexadecimal string representation to convert + * + * @return string String representation of an integer + * + * @psalm-return numeric-string + * + * @psalm-pure + */ + public function fromHex(string $hex): string; + + /** + * Converts a string integer representation into a hexadecimal string + * representation of the number + * + * @param string $number A string integer representation to convert; this + * must be a numeric string to accommodate unsigned integers greater + * than PHP_INT_MAX. + * + * @return string Hexadecimal string + * + * @psalm-return non-empty-string + * + * @psalm-pure + */ + public function toHex(string $number): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php new file mode 100644 index 00000000..7390dad8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php @@ -0,0 +1,51 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter\Time; + +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Math\BrickMathCalculator; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Time; + +/** + * Previously used to integrate moontoast/math as a bignum arithmetic library, + * BigNumberTimeConverter is deprecated in favor of GenericTimeConverter + * + * @deprecated Transition to {@see GenericTimeConverter}. + * + * @psalm-immutable + */ +class BigNumberTimeConverter implements TimeConverterInterface +{ + /** + * @var TimeConverterInterface + */ + private $converter; + + public function __construct() + { + $this->converter = new GenericTimeConverter(new BrickMathCalculator()); + } + + public function calculateTime(string $seconds, string $microseconds): Hexadecimal + { + return $this->converter->calculateTime($seconds, $microseconds); + } + + public function convertTime(Hexadecimal $uuidTimestamp): Time + { + return $this->converter->convertTime($uuidTimestamp); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php new file mode 100644 index 00000000..cdc28752 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter\Time; + +/** + * @deprecated DegradedTimeConverter is no longer necessary for converting + * time on 32-bit systems. Transition to {@see GenericTimeConverter}. + * + * @psalm-immutable + */ +class DegradedTimeConverter extends BigNumberTimeConverter +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php new file mode 100644 index 00000000..a8aa64b7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php @@ -0,0 +1,124 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter\Time; + +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Math\CalculatorInterface; +use Ramsey\Uuid\Math\RoundingMode; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Type\Time; + +use function explode; +use function str_pad; + +use const STR_PAD_LEFT; + +/** + * GenericTimeConverter uses the provided calculator to calculate and convert + * time values + * + * @psalm-immutable + */ +class GenericTimeConverter implements TimeConverterInterface +{ + /** + * The number of 100-nanosecond intervals from the Gregorian calendar epoch + * to the Unix epoch. + */ + private const GREGORIAN_TO_UNIX_INTERVALS = '122192928000000000'; + + /** + * The number of 100-nanosecond intervals in one second. + */ + private const SECOND_INTERVALS = '10000000'; + + /** + * The number of 100-nanosecond intervals in one microsecond. + */ + private const MICROSECOND_INTERVALS = '10'; + + /** + * @var CalculatorInterface + */ + private $calculator; + + public function __construct(CalculatorInterface $calculator) + { + $this->calculator = $calculator; + } + + public function calculateTime(string $seconds, string $microseconds): Hexadecimal + { + $timestamp = new Time($seconds, $microseconds); + + // Convert the seconds into a count of 100-nanosecond intervals. + $sec = $this->calculator->multiply( + $timestamp->getSeconds(), + new IntegerObject(self::SECOND_INTERVALS) + ); + + // Convert the microseconds into a count of 100-nanosecond intervals. + $usec = $this->calculator->multiply( + $timestamp->getMicroseconds(), + new IntegerObject(self::MICROSECOND_INTERVALS) + ); + + // Combine the seconds and microseconds intervals and add the count of + // 100-nanosecond intervals from the Gregorian calendar epoch to the + // Unix epoch. This gives us the correct count of 100-nanosecond + // intervals since the Gregorian calendar epoch for the given seconds + // and microseconds. + /** @var IntegerObject $uuidTime */ + $uuidTime = $this->calculator->add( + $sec, + $usec, + new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS) + ); + + $uuidTimeHex = str_pad( + $this->calculator->toHexadecimal($uuidTime)->toString(), + 16, + '0', + STR_PAD_LEFT + ); + + return new Hexadecimal($uuidTimeHex); + } + + public function convertTime(Hexadecimal $uuidTimestamp): Time + { + // From the total, subtract the number of 100-nanosecond intervals from + // the Gregorian calendar epoch to the Unix epoch. This gives us the + // number of 100-nanosecond intervals from the Unix epoch, which also + // includes the microtime. + $epochNanoseconds = $this->calculator->subtract( + $this->calculator->toInteger($uuidTimestamp), + new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS) + ); + + // Convert the 100-nanosecond intervals into seconds and microseconds. + $unixTimestamp = $this->calculator->divide( + RoundingMode::HALF_UP, + 6, + $epochNanoseconds, + new IntegerObject(self::SECOND_INTERVALS) + ); + + $split = explode('.', (string) $unixTimestamp, 2); + + return new Time($split[0], $split[1] ?? 0); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php new file mode 100644 index 00000000..538d2f2f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php @@ -0,0 +1,183 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter\Time; + +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Math\BrickMathCalculator; +use Ramsey\Uuid\Math\CalculatorInterface; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Type\Time; + +use function count; +use function dechex; +use function explode; +use function is_float; +use function is_int; +use function str_pad; +use function strlen; +use function substr; + +use const STR_PAD_LEFT; +use const STR_PAD_RIGHT; + +/** + * PhpTimeConverter uses built-in PHP functions and standard math operations + * available to the PHP programming language to provide facilities for + * converting parts of time into representations that may be used in UUIDs + * + * @psalm-immutable + */ +class PhpTimeConverter implements TimeConverterInterface +{ + /** + * The number of 100-nanosecond intervals from the Gregorian calendar epoch + * to the Unix epoch. + */ + private const GREGORIAN_TO_UNIX_INTERVALS = 0x01b21dd213814000; + + /** + * The number of 100-nanosecond intervals in one second. + */ + private const SECOND_INTERVALS = 10000000; + + /** + * The number of 100-nanosecond intervals in one microsecond. + */ + private const MICROSECOND_INTERVALS = 10; + + /** + * @var CalculatorInterface + */ + private $calculator; + + /** + * @var TimeConverterInterface + */ + private $fallbackConverter; + + /** + * @var int + */ + private $phpPrecision; + + public function __construct( + ?CalculatorInterface $calculator = null, + ?TimeConverterInterface $fallbackConverter = null + ) { + if ($calculator === null) { + $calculator = new BrickMathCalculator(); + } + + if ($fallbackConverter === null) { + $fallbackConverter = new GenericTimeConverter($calculator); + } + + $this->calculator = $calculator; + $this->fallbackConverter = $fallbackConverter; + $this->phpPrecision = (int) ini_get('precision'); + } + + public function calculateTime(string $seconds, string $microseconds): Hexadecimal + { + $seconds = new IntegerObject($seconds); + $microseconds = new IntegerObject($microseconds); + + // Calculate the count of 100-nanosecond intervals since the Gregorian + // calendar epoch for the given seconds and microseconds. + $uuidTime = ((int) $seconds->toString() * self::SECOND_INTERVALS) + + ((int) $microseconds->toString() * self::MICROSECOND_INTERVALS) + + self::GREGORIAN_TO_UNIX_INTERVALS; + + // Check to see whether we've overflowed the max/min integer size. + // If so, we will default to a different time converter. + /** @psalm-suppress RedundantCondition */ + if (!is_int($uuidTime)) { + return $this->fallbackConverter->calculateTime( + $seconds->toString(), + $microseconds->toString() + ); + } + + return new Hexadecimal(str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT)); + } + + public function convertTime(Hexadecimal $uuidTimestamp): Time + { + $timestamp = $this->calculator->toInteger($uuidTimestamp); + + // Convert the 100-nanosecond intervals into seconds and microseconds. + $splitTime = $this->splitTime( + ((int) $timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS) + / self::SECOND_INTERVALS + ); + + if (count($splitTime) === 0) { + return $this->fallbackConverter->convertTime($uuidTimestamp); + } + + return new Time($splitTime['sec'], $splitTime['usec']); + } + + /** + * @param int|float $time The time to split into seconds and microseconds + * + * @return string[] + */ + private function splitTime($time): array + { + $split = explode('.', (string) $time, 2); + + // If the $time value is a float but $split only has 1 element, then the + // float math was rounded up to the next second, so we want to return + // an empty array to allow use of the fallback converter. + if (is_float($time) && count($split) === 1) { + return []; + } + + if (count($split) === 1) { + return [ + 'sec' => $split[0], + 'usec' => '0', + ]; + } + + // If the microseconds are less than six characters AND the length of + // the number is greater than or equal to the PHP precision, then it's + // possible that we lost some precision for the microseconds. Return an + // empty array, so that we can choose to use the fallback converter. + if (strlen($split[1]) < 6 && strlen((string) $time) >= $this->phpPrecision) { + return []; + } + + $microseconds = $split[1]; + + // Ensure the microseconds are no longer than 6 digits. If they are, + // truncate the number to the first 6 digits and round up, if needed. + if (strlen($microseconds) > 6) { + $roundingDigit = (int) substr($microseconds, 6, 1); + $microseconds = (int) substr($microseconds, 0, 6); + + if ($roundingDigit >= 5) { + $microseconds++; + } + } + + return [ + 'sec' => $split[0], + 'usec' => str_pad((string) $microseconds, 6, '0', STR_PAD_RIGHT), + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php new file mode 100644 index 00000000..1e848070 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php @@ -0,0 +1,58 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Converter; + +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Time; + +/** + * A time converter converts timestamps into representations that may be used + * in UUIDs + * + * @psalm-immutable + */ +interface TimeConverterInterface +{ + /** + * Uses the provided seconds and micro-seconds to calculate the count of + * 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582, for + * RFC 4122 variant UUIDs + * + * @link http://tools.ietf.org/html/rfc4122#section-4.2.2 RFC 4122, § 4.2.2: Generation Details + * + * @param string $seconds A string representation of the number of seconds + * since the Unix epoch for the time to calculate + * @param string $microseconds A string representation of the micro-seconds + * associated with the time to calculate + * + * @return Hexadecimal The full UUID timestamp as a Hexadecimal value + * + * @psalm-pure + */ + public function calculateTime(string $seconds, string $microseconds): Hexadecimal; + + /** + * Converts a timestamp extracted from a UUID to a Unix timestamp + * + * @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID + * timestamp; a UUID timestamp is a count of 100-nanosecond intervals + * since UTC 00:00:00.00, 15 October 1582. + * + * @return Time An instance of {@see Time} + * + * @psalm-pure + */ + public function convertTime(Hexadecimal $uuidTimestamp): Time; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DegradedUuid.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DegradedUuid.php new file mode 100644 index 00000000..9166042c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DegradedUuid.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +/** + * @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit + * systems. Transition typehints to {@see UuidInterface}. + * + * @psalm-immutable + */ +class DegradedUuid extends Uuid +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php new file mode 100644 index 00000000..ed6d9dec --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php @@ -0,0 +1,147 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use DateTimeInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; + +/** + * This interface encapsulates deprecated methods for ramsey/uuid; this + * interface and its methods will be removed in ramsey/uuid 5.0.0. + * + * @psalm-immutable + */ +interface DeprecatedUuidInterface +{ + /** + * @deprecated This method will be removed in 5.0.0. There is no alternative + * recommendation, so plan accordingly. + */ + public function getNumberConverter(): NumberConverterInterface; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. + * + * @return string[] + */ + public function getFieldsHex(): array; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}. + */ + public function getClockSeqHiAndReservedHex(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}. + */ + public function getClockSeqLowHex(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}. + */ + public function getClockSequenceHex(): string; + + /** + * @deprecated In ramsey/uuid version 5.0.0, this will be removed from the + * interface. It is available at {@see UuidV1::getDateTime()}. + */ + public function getDateTime(): DateTimeInterface; + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + */ + public function getLeastSignificantBitsHex(): string; + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + */ + public function getMostSignificantBitsHex(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}. + */ + public function getNodeHex(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}. + */ + public function getTimeHiAndVersionHex(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}. + */ + public function getTimeLowHex(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}. + */ + public function getTimeMidHex(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}. + */ + public function getTimestampHex(): string; + + /** + * @deprecated In ramsey/uuid version 5.0.0, this will be removed from this + * interface. It has moved to {@see \Ramsey\Uuid\Rfc4122\UuidInterface::getUrn()}. + */ + public function getUrn(): string; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}. + */ + public function getVariant(): ?int; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}. + */ + public function getVersion(): ?int; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php new file mode 100644 index 00000000..34282952 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php @@ -0,0 +1,370 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use DateTimeImmutable; +use DateTimeInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\DateTimeException; +use Ramsey\Uuid\Exception\UnsupportedOperationException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Throwable; + +use function str_pad; +use function substr; + +use const STR_PAD_LEFT; + +/** + * This trait encapsulates deprecated methods for ramsey/uuid; this trait and + * its methods will be removed in ramsey/uuid 5.0.0. + * + * @psalm-immutable + */ +trait DeprecatedUuidMethodsTrait +{ + /** + * @var Rfc4122FieldsInterface + */ + protected $fields; + + /** + * @var NumberConverterInterface + */ + protected $numberConverter; + + /** + * @var TimeConverterInterface + */ + protected $timeConverter; + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getClockSeqHiAndReserved(): string + { + return $this->numberConverter->fromHex($this->fields->getClockSeqHiAndReserved()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}. + */ + public function getClockSeqHiAndReservedHex(): string + { + return $this->fields->getClockSeqHiAndReserved()->toString(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getClockSeqLow(): string + { + return $this->numberConverter->fromHex($this->fields->getClockSeqLow()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}. + */ + public function getClockSeqLowHex(): string + { + return $this->fields->getClockSeqLow()->toString(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getClockSequence(): string + { + return $this->numberConverter->fromHex($this->fields->getClockSeq()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}. + */ + public function getClockSequenceHex(): string + { + return $this->fields->getClockSeq()->toString(); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no alternative + * recommendation, so plan accordingly. + */ + public function getNumberConverter(): NumberConverterInterface + { + return $this->numberConverter; + } + + /** + * @deprecated In ramsey/uuid version 5.0.0, this will be removed. + * It is available at {@see UuidV1::getDateTime()}. + * + * @return DateTimeImmutable An immutable instance of DateTimeInterface + * + * @throws UnsupportedOperationException if UUID is not time-based + * @throws DateTimeException if DateTime throws an exception/error + */ + public function getDateTime(): DateTimeInterface + { + if ($this->fields->getVersion() !== 1) { + throw new UnsupportedOperationException('Not a time-based UUID'); + } + + $time = $this->timeConverter->convertTime($this->fields->getTimestamp()); + + try { + return new DateTimeImmutable( + '@' + . $time->getSeconds()->toString() + . '.' + . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT) + ); + } catch (Throwable $e) { + throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e); + } + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. + * + * @return string[] + */ + public function getFieldsHex(): array + { + return [ + 'time_low' => $this->fields->getTimeLow()->toString(), + 'time_mid' => $this->fields->getTimeMid()->toString(), + 'time_hi_and_version' => $this->fields->getTimeHiAndVersion()->toString(), + 'clock_seq_hi_and_reserved' => $this->fields->getClockSeqHiAndReserved()->toString(), + 'clock_seq_low' => $this->fields->getClockSeqLow()->toString(), + 'node' => $this->fields->getNode()->toString(), + ]; + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + */ + public function getLeastSignificantBits(): string + { + $leastSignificantHex = substr($this->getHex()->toString(), 16); + + return $this->numberConverter->fromHex($leastSignificantHex); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + */ + public function getLeastSignificantBitsHex(): string + { + return substr($this->getHex()->toString(), 16); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + */ + public function getMostSignificantBits(): string + { + $mostSignificantHex = substr($this->getHex()->toString(), 0, 16); + + return $this->numberConverter->fromHex($mostSignificantHex); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + */ + public function getMostSignificantBitsHex(): string + { + return substr($this->getHex()->toString(), 0, 16); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getNode()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getNode(): string + { + return $this->numberConverter->fromHex($this->fields->getNode()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getNode()}. + */ + public function getNodeHex(): string + { + return $this->fields->getNode()->toString(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getTimeHiAndVersion(): string + { + return $this->numberConverter->fromHex($this->fields->getTimeHiAndVersion()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}. + */ + public function getTimeHiAndVersionHex(): string + { + return $this->fields->getTimeHiAndVersion()->toString(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getTimeLow(): string + { + return $this->numberConverter->fromHex($this->fields->getTimeLow()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}. + */ + public function getTimeLowHex(): string + { + return $this->fields->getTimeLow()->toString(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getTimeMid(): string + { + return $this->numberConverter->fromHex($this->fields->getTimeMid()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}. + */ + public function getTimeMidHex(): string + { + return $this->fields->getTimeMid()->toString(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + */ + public function getTimestamp(): string + { + if ($this->fields->getVersion() !== 1) { + throw new UnsupportedOperationException('Not a time-based UUID'); + } + + return $this->numberConverter->fromHex($this->fields->getTimestamp()->toString()); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}. + */ + public function getTimestampHex(): string + { + if ($this->fields->getVersion() !== 1) { + throw new UnsupportedOperationException('Not a time-based UUID'); + } + + return $this->fields->getTimestamp()->toString(); + } + + /** + * @deprecated This has moved to {@see Rfc4122FieldsInterface::getUrn()} and + * is available on {@see \Ramsey\Uuid\Rfc4122\UuidV1}, + * {@see \Ramsey\Uuid\Rfc4122\UuidV3}, {@see \Ramsey\Uuid\Rfc4122\UuidV4}, + * and {@see \Ramsey\Uuid\Rfc4122\UuidV5}. + */ + public function getUrn(): string + { + return 'urn:uuid:' . $this->toString(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}. + */ + public function getVariant(): ?int + { + return $this->fields->getVariant(); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call + * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}. + */ + public function getVersion(): ?int + { + return $this->fields->getVersion(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/BuilderNotFoundException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/BuilderNotFoundException.php new file mode 100644 index 00000000..220ffedb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/BuilderNotFoundException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate that no suitable builder could be found + */ +class BuilderNotFoundException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DateTimeException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DateTimeException.php new file mode 100644 index 00000000..5f0e658b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DateTimeException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate that the PHP DateTime extension encountered an exception/error + */ +class DateTimeException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DceSecurityException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DceSecurityException.php new file mode 100644 index 00000000..e6d80013 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/DceSecurityException.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate an exception occurred while dealing with DCE Security + * (version 2) UUIDs + */ +class DceSecurityException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidArgumentException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..2a1fa3ac --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidArgumentException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use InvalidArgumentException as PhpInvalidArgumentException; + +/** + * Thrown to indicate that the argument received is not valid + */ +class InvalidArgumentException extends PhpInvalidArgumentException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidBytesException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidBytesException.php new file mode 100644 index 00000000..1c94f659 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidBytesException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate that the bytes being operated on are invalid in some way + */ +class InvalidBytesException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php new file mode 100644 index 00000000..6d975816 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +/** + * Thrown to indicate that the string received is not a valid UUID + * + * The InvalidArgumentException that this extends is the ramsey/uuid version + * of this exception. It exists in the same namespace as this class. + */ +class InvalidUuidStringException extends InvalidArgumentException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NameException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NameException.php new file mode 100644 index 00000000..fd96a1fa --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NameException.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate that an error occurred while attempting to hash a + * namespace and name + */ +class NameException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NodeException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NodeException.php new file mode 100644 index 00000000..0dbdd50b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/NodeException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate that attempting to fetch or create a node ID encountered an error + */ +class NodeException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/RandomSourceException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/RandomSourceException.php new file mode 100644 index 00000000..a44dd34a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/RandomSourceException.php @@ -0,0 +1,27 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate that the source of random data encountered an error + * + * This exception is used mostly to indicate that random_bytes() or random_int() + * threw an exception. However, it may be used for other sources of random data. + */ +class RandomSourceException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/TimeSourceException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/TimeSourceException.php new file mode 100644 index 00000000..fc9cf36b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/TimeSourceException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate that the source of time encountered an error + */ +class TimeSourceException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnableToBuildUuidException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnableToBuildUuidException.php new file mode 100644 index 00000000..5ba26d8d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnableToBuildUuidException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use RuntimeException as PhpRuntimeException; + +/** + * Thrown to indicate a builder is unable to build a UUID + */ +class UnableToBuildUuidException extends PhpRuntimeException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnsupportedOperationException.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnsupportedOperationException.php new file mode 100644 index 00000000..e1b3eda1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UnsupportedOperationException.php @@ -0,0 +1,24 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use LogicException as PhpLogicException; + +/** + * Thrown to indicate that the requested operation is not supported + */ +class UnsupportedOperationException extends PhpLogicException implements UuidExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UuidExceptionInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UuidExceptionInterface.php new file mode 100644 index 00000000..a2f1c103 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Exception/UuidExceptionInterface.php @@ -0,0 +1,21 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Exception; + +use Throwable; + +interface UuidExceptionInterface extends Throwable +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/FeatureSet.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/FeatureSet.php new file mode 100644 index 00000000..a8ab2fdb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/FeatureSet.php @@ -0,0 +1,449 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use Ramsey\Uuid\Builder\BuilderCollection; +use Ramsey\Uuid\Builder\FallbackBuilder; +use Ramsey\Uuid\Builder\UuidBuilderInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Codec\GuidStringCodec; +use Ramsey\Uuid\Codec\StringCodec; +use Ramsey\Uuid\Converter\Number\GenericNumberConverter; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\Time\GenericTimeConverter; +use Ramsey\Uuid\Converter\Time\PhpTimeConverter; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Generator\DceSecurityGenerator; +use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface; +use Ramsey\Uuid\Generator\NameGeneratorFactory; +use Ramsey\Uuid\Generator\NameGeneratorInterface; +use Ramsey\Uuid\Generator\PeclUuidNameGenerator; +use Ramsey\Uuid\Generator\PeclUuidRandomGenerator; +use Ramsey\Uuid\Generator\PeclUuidTimeGenerator; +use Ramsey\Uuid\Generator\RandomGeneratorFactory; +use Ramsey\Uuid\Generator\RandomGeneratorInterface; +use Ramsey\Uuid\Generator\TimeGeneratorFactory; +use Ramsey\Uuid\Generator\TimeGeneratorInterface; +use Ramsey\Uuid\Guid\GuidBuilder; +use Ramsey\Uuid\Math\BrickMathCalculator; +use Ramsey\Uuid\Math\CalculatorInterface; +use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder; +use Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider; +use Ramsey\Uuid\Provider\DceSecurityProviderInterface; +use Ramsey\Uuid\Provider\Node\FallbackNodeProvider; +use Ramsey\Uuid\Provider\Node\NodeProviderCollection; +use Ramsey\Uuid\Provider\Node\RandomNodeProvider; +use Ramsey\Uuid\Provider\Node\SystemNodeProvider; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Provider\Time\SystemTimeProvider; +use Ramsey\Uuid\Provider\TimeProviderInterface; +use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder; +use Ramsey\Uuid\Validator\GenericValidator; +use Ramsey\Uuid\Validator\ValidatorInterface; + +use const PHP_INT_SIZE; + +/** + * FeatureSet detects and exposes available features in the current environment + * + * A feature set is used by UuidFactory to determine the available features and + * capabilities of the environment. + */ +class FeatureSet +{ + /** + * @var bool + */ + private $disableBigNumber = false; + + /** + * @var bool + */ + private $disable64Bit = false; + + /** + * @var bool + */ + private $ignoreSystemNode = false; + + /** + * @var bool + */ + private $enablePecl = false; + + /** + * @var UuidBuilderInterface + */ + private $builder; + + /** + * @var CodecInterface + */ + private $codec; + + /** + * @var DceSecurityGeneratorInterface + */ + private $dceSecurityGenerator; + + /** + * @var NameGeneratorInterface + */ + private $nameGenerator; + + /** + * @var NodeProviderInterface + */ + private $nodeProvider; + + /** + * @var NumberConverterInterface + */ + private $numberConverter; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * @var RandomGeneratorInterface + */ + private $randomGenerator; + + /** + * @var TimeGeneratorInterface + */ + private $timeGenerator; + + /** + * @var TimeProviderInterface + */ + private $timeProvider; + + /** + * @var ValidatorInterface + */ + private $validator; + + /** + * @var CalculatorInterface + */ + private $calculator; + + /** + * @param bool $useGuids True build UUIDs using the GuidStringCodec + * @param bool $force32Bit True to force the use of 32-bit functionality + * (primarily for testing purposes) + * @param bool $forceNoBigNumber True to disable the use of moontoast/math + * (primarily for testing purposes) + * @param bool $ignoreSystemNode True to disable attempts to check for the + * system node ID (primarily for testing purposes) + * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator + * to generate version 1 UUIDs + */ + public function __construct( + bool $useGuids = false, + bool $force32Bit = false, + bool $forceNoBigNumber = false, + bool $ignoreSystemNode = false, + bool $enablePecl = false + ) { + $this->disableBigNumber = $forceNoBigNumber; + $this->disable64Bit = $force32Bit; + $this->ignoreSystemNode = $ignoreSystemNode; + $this->enablePecl = $enablePecl; + + $this->setCalculator(new BrickMathCalculator()); + $this->builder = $this->buildUuidBuilder($useGuids); + $this->codec = $this->buildCodec($useGuids); + $this->nodeProvider = $this->buildNodeProvider(); + $this->nameGenerator = $this->buildNameGenerator(); + $this->randomGenerator = $this->buildRandomGenerator(); + $this->setTimeProvider(new SystemTimeProvider()); + $this->setDceSecurityProvider(new SystemDceSecurityProvider()); + $this->validator = new GenericValidator(); + } + + /** + * Returns the builder configured for this environment + */ + public function getBuilder(): UuidBuilderInterface + { + return $this->builder; + } + + /** + * Returns the calculator configured for this environment + */ + public function getCalculator(): CalculatorInterface + { + return $this->calculator; + } + + /** + * Returns the codec configured for this environment + */ + public function getCodec(): CodecInterface + { + return $this->codec; + } + + /** + * Returns the DCE Security generator configured for this environment + */ + public function getDceSecurityGenerator(): DceSecurityGeneratorInterface + { + return $this->dceSecurityGenerator; + } + + /** + * Returns the name generator configured for this environment + */ + public function getNameGenerator(): NameGeneratorInterface + { + return $this->nameGenerator; + } + + /** + * Returns the node provider configured for this environment + */ + public function getNodeProvider(): NodeProviderInterface + { + return $this->nodeProvider; + } + + /** + * Returns the number converter configured for this environment + */ + public function getNumberConverter(): NumberConverterInterface + { + return $this->numberConverter; + } + + /** + * Returns the random generator configured for this environment + */ + public function getRandomGenerator(): RandomGeneratorInterface + { + return $this->randomGenerator; + } + + /** + * Returns the time converter configured for this environment + */ + public function getTimeConverter(): TimeConverterInterface + { + return $this->timeConverter; + } + + /** + * Returns the time generator configured for this environment + */ + public function getTimeGenerator(): TimeGeneratorInterface + { + return $this->timeGenerator; + } + + /** + * Returns the validator configured for this environment + */ + public function getValidator(): ValidatorInterface + { + return $this->validator; + } + + /** + * Sets the calculator to use in this environment + */ + public function setCalculator(CalculatorInterface $calculator): void + { + $this->calculator = $calculator; + $this->numberConverter = $this->buildNumberConverter($calculator); + $this->timeConverter = $this->buildTimeConverter($calculator); + + /** @psalm-suppress RedundantPropertyInitializationCheck */ + if (isset($this->timeProvider)) { + $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider); + } + } + + /** + * Sets the DCE Security provider to use in this environment + */ + public function setDceSecurityProvider(DceSecurityProviderInterface $dceSecurityProvider): void + { + $this->dceSecurityGenerator = $this->buildDceSecurityGenerator($dceSecurityProvider); + } + + /** + * Sets the node provider to use in this environment + */ + public function setNodeProvider(NodeProviderInterface $nodeProvider): void + { + $this->nodeProvider = $nodeProvider; + $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider); + } + + /** + * Sets the time provider to use in this environment + */ + public function setTimeProvider(TimeProviderInterface $timeProvider): void + { + $this->timeProvider = $timeProvider; + $this->timeGenerator = $this->buildTimeGenerator($timeProvider); + } + + /** + * Set the validator to use in this environment + */ + public function setValidator(ValidatorInterface $validator): void + { + $this->validator = $validator; + } + + /** + * Returns a codec configured for this environment + * + * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec + */ + private function buildCodec(bool $useGuids = false): CodecInterface + { + if ($useGuids) { + return new GuidStringCodec($this->builder); + } + + return new StringCodec($this->builder); + } + + /** + * Returns a DCE Security generator configured for this environment + */ + private function buildDceSecurityGenerator( + DceSecurityProviderInterface $dceSecurityProvider + ): DceSecurityGeneratorInterface { + return new DceSecurityGenerator( + $this->numberConverter, + $this->timeGenerator, + $dceSecurityProvider + ); + } + + /** + * Returns a node provider configured for this environment + */ + private function buildNodeProvider(): NodeProviderInterface + { + if ($this->ignoreSystemNode) { + return new RandomNodeProvider(); + } + + return new FallbackNodeProvider(new NodeProviderCollection([ + new SystemNodeProvider(), + new RandomNodeProvider(), + ])); + } + + /** + * Returns a number converter configured for this environment + */ + private function buildNumberConverter(CalculatorInterface $calculator): NumberConverterInterface + { + return new GenericNumberConverter($calculator); + } + + /** + * Returns a random generator configured for this environment + */ + private function buildRandomGenerator(): RandomGeneratorInterface + { + if ($this->enablePecl) { + return new PeclUuidRandomGenerator(); + } + + return (new RandomGeneratorFactory())->getGenerator(); + } + + /** + * Returns a time generator configured for this environment + * + * @param TimeProviderInterface $timeProvider The time provider to use with + * the time generator + */ + private function buildTimeGenerator(TimeProviderInterface $timeProvider): TimeGeneratorInterface + { + if ($this->enablePecl) { + return new PeclUuidTimeGenerator(); + } + + return (new TimeGeneratorFactory( + $this->nodeProvider, + $this->timeConverter, + $timeProvider + ))->getGenerator(); + } + + /** + * Returns a name generator configured for this environment + */ + private function buildNameGenerator(): NameGeneratorInterface + { + if ($this->enablePecl) { + return new PeclUuidNameGenerator(); + } + + return (new NameGeneratorFactory())->getGenerator(); + } + + /** + * Returns a time converter configured for this environment + */ + private function buildTimeConverter(CalculatorInterface $calculator): TimeConverterInterface + { + $genericConverter = new GenericTimeConverter($calculator); + + if ($this->is64BitSystem()) { + return new PhpTimeConverter($calculator, $genericConverter); + } + + return $genericConverter; + } + + /** + * Returns a UUID builder configured for this environment + * + * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec + */ + private function buildUuidBuilder(bool $useGuids = false): UuidBuilderInterface + { + if ($useGuids) { + return new GuidBuilder($this->numberConverter, $this->timeConverter); + } + + /** @psalm-suppress ImpureArgument */ + return new FallbackBuilder(new BuilderCollection([ + new Rfc4122UuidBuilder($this->numberConverter, $this->timeConverter), + new NonstandardUuidBuilder($this->numberConverter, $this->timeConverter), + ])); + } + + /** + * Returns true if the PHP build is 64-bit + */ + private function is64BitSystem(): bool + { + return PHP_INT_SIZE === 8 && !$this->disable64Bit; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/FieldsInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/FieldsInterface.php new file mode 100644 index 00000000..f1b7a290 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/FieldsInterface.php @@ -0,0 +1,32 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Fields; + +use Serializable; + +/** + * UUIDs are comprised of unsigned integers, the bytes of which are separated + * into fields and arranged in a particular layout defined by the specification + * for the variant + * + * @psalm-immutable + */ +interface FieldsInterface extends Serializable +{ + /** + * Returns the bytes that comprise the fields + */ + public function getBytes(): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php new file mode 100644 index 00000000..16e6525d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php @@ -0,0 +1,86 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Fields; + +use ValueError; + +use function base64_decode; +use function sprintf; +use function strlen; + +/** + * Provides common serialization functionality to fields + * + * @psalm-immutable + */ +trait SerializableFieldsTrait +{ + /** + * @param string $bytes The bytes that comprise the fields + */ + abstract public function __construct(string $bytes); + + /** + * Returns the bytes that comprise the fields + */ + abstract public function getBytes(): string; + + /** + * Returns a string representation of object + */ + public function serialize(): string + { + return $this->getBytes(); + } + + /** + * @return array{bytes: string} + */ + public function __serialize(): array + { + return ['bytes' => $this->getBytes()]; + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @psalm-suppress UnusedMethodCall + */ + public function unserialize($serialized): void + { + if (strlen($serialized) === 16) { + $this->__construct($serialized); + } else { + $this->__construct(base64_decode($serialized)); + } + } + + /** + * @param array{bytes: string} $data + */ + public function __unserialize(array $data): void + { + // @codeCoverageIgnoreStart + if (!isset($data['bytes'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $this->unserialize($data['bytes']); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/CombGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/CombGenerator.php new file mode 100644 index 00000000..49b09381 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/CombGenerator.php @@ -0,0 +1,127 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; + +use function bin2hex; +use function explode; +use function hex2bin; +use function microtime; +use function str_pad; +use function substr; + +use const STR_PAD_LEFT; + +/** + * CombGenerator generates COMBs (combined UUID/timestamp) + * + * The CombGenerator, when used with the StringCodec (and, by proxy, the + * TimestampLastCombCodec) or the TimestampFirstCombCodec, combines the current + * timestamp with a UUID (hence the name "COMB"). The timestamp either appears + * as the first or last 48 bits of the COMB, depending on the codec used. + * + * By default, COMBs will have the timestamp set as the last 48 bits of the + * identifier. + * + * ``` php + * $factory = new UuidFactory(); + * + * $factory->setRandomGenerator(new CombGenerator( + * $factory->getRandomGenerator(), + * $factory->getNumberConverter() + * )); + * + * $comb = $factory->uuid4(); + * ``` + * + * To generate a COMB with the timestamp as the first 48 bits, set the + * TimestampFirstCombCodec as the codec. + * + * ``` php + * $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder())); + * ``` + * + * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys + */ +class CombGenerator implements RandomGeneratorInterface +{ + public const TIMESTAMP_BYTES = 6; + + /** + * @var RandomGeneratorInterface + */ + private $randomGenerator; + + /** + * @var NumberConverterInterface + */ + private $converter; + + public function __construct( + RandomGeneratorInterface $generator, + NumberConverterInterface $numberConverter + ) { + $this->converter = $numberConverter; + $this->randomGenerator = $generator; + } + + /** + * @throws InvalidArgumentException if $length is not a positive integer + * greater than or equal to CombGenerator::TIMESTAMP_BYTES + * + * @inheritDoc + */ + public function generate(int $length): string + { + if ($length < self::TIMESTAMP_BYTES || $length < 0) { + throw new InvalidArgumentException( + 'Length must be a positive integer greater than or equal to ' . self::TIMESTAMP_BYTES + ); + } + + $hash = ''; + if (self::TIMESTAMP_BYTES > 0 && $length > self::TIMESTAMP_BYTES) { + $hash = $this->randomGenerator->generate($length - self::TIMESTAMP_BYTES); + } + + $lsbTime = str_pad( + $this->converter->toHex($this->timestamp()), + self::TIMESTAMP_BYTES * 2, + '0', + STR_PAD_LEFT + ); + + return (string) hex2bin( + str_pad( + bin2hex($hash), + $length - self::TIMESTAMP_BYTES, + '0' + ) + . $lsbTime + ); + } + + /** + * Returns current timestamp a string integer, precise to 0.00001 seconds + */ + private function timestamp(): string + { + $time = explode(' ', microtime(false)); + + return $time[1] . substr($time[0], 2, 5); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php new file mode 100644 index 00000000..aca8c5db --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php @@ -0,0 +1,160 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Exception\DceSecurityException; +use Ramsey\Uuid\Provider\DceSecurityProviderInterface; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Uuid; + +use function hex2bin; +use function in_array; +use function pack; +use function str_pad; +use function strlen; +use function substr_replace; + +use const STR_PAD_LEFT; + +/** + * DceSecurityGenerator generates strings of binary data based on a local + * domain, local identifier, node ID, clock sequence, and the current time + */ +class DceSecurityGenerator implements DceSecurityGeneratorInterface +{ + private const DOMAINS = [ + Uuid::DCE_DOMAIN_PERSON, + Uuid::DCE_DOMAIN_GROUP, + Uuid::DCE_DOMAIN_ORG, + ]; + + /** + * Upper bounds for the clock sequence in DCE Security UUIDs. + */ + private const CLOCK_SEQ_HIGH = 63; + + /** + * Lower bounds for the clock sequence in DCE Security UUIDs. + */ + private const CLOCK_SEQ_LOW = 0; + + /** + * @var NumberConverterInterface + */ + private $numberConverter; + + /** + * @var TimeGeneratorInterface + */ + private $timeGenerator; + + /** + * @var DceSecurityProviderInterface + */ + private $dceSecurityProvider; + + public function __construct( + NumberConverterInterface $numberConverter, + TimeGeneratorInterface $timeGenerator, + DceSecurityProviderInterface $dceSecurityProvider + ) { + $this->numberConverter = $numberConverter; + $this->timeGenerator = $timeGenerator; + $this->dceSecurityProvider = $dceSecurityProvider; + } + + public function generate( + int $localDomain, + ?IntegerObject $localIdentifier = null, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): string { + if (!in_array($localDomain, self::DOMAINS)) { + throw new DceSecurityException( + 'Local domain must be a valid DCE Security domain' + ); + } + + if ($localIdentifier && $localIdentifier->isNegative()) { + throw new DceSecurityException( + 'Local identifier out of bounds; it must be a value between 0 and 4294967295' + ); + } + + if ($clockSeq > self::CLOCK_SEQ_HIGH || $clockSeq < self::CLOCK_SEQ_LOW) { + throw new DceSecurityException( + 'Clock sequence out of bounds; it must be a value between 0 and 63' + ); + } + + switch ($localDomain) { + case Uuid::DCE_DOMAIN_ORG: + if ($localIdentifier === null) { + throw new DceSecurityException( + 'A local identifier must be provided for the org domain' + ); + } + + break; + case Uuid::DCE_DOMAIN_PERSON: + if ($localIdentifier === null) { + $localIdentifier = $this->dceSecurityProvider->getUid(); + } + + break; + case Uuid::DCE_DOMAIN_GROUP: + default: + if ($localIdentifier === null) { + $localIdentifier = $this->dceSecurityProvider->getGid(); + } + + break; + } + + $identifierHex = $this->numberConverter->toHex($localIdentifier->toString()); + + // The maximum value for the local identifier is 0xffffffff, or + // 4294967295. This is 8 hexadecimal digits, so if the length of + // hexadecimal digits is greater than 8, we know the value is greater + // than 0xffffffff. + if (strlen($identifierHex) > 8) { + throw new DceSecurityException( + 'Local identifier out of bounds; it must be a value between 0 and 4294967295' + ); + } + + $domainByte = pack('n', $localDomain)[1]; + $identifierBytes = (string) hex2bin(str_pad($identifierHex, 8, '0', STR_PAD_LEFT)); + + if ($node instanceof Hexadecimal) { + $node = $node->toString(); + } + + // Shift the clock sequence 8 bits to the left, so it matches 0x3f00. + if ($clockSeq !== null) { + $clockSeq = $clockSeq << 8; + } + + $bytes = $this->timeGenerator->generate($node, $clockSeq); + + // Replace bytes in the time-based UUID with DCE Security values. + $bytes = substr_replace($bytes, $identifierBytes, 0, 4); + $bytes = substr_replace($bytes, $domainByte, 9, 1); + + return $bytes; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php new file mode 100644 index 00000000..faa29a53 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php @@ -0,0 +1,53 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Rfc4122\UuidV2; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; + +/** + * A DCE Security generator generates strings of binary data based on a local + * domain, local identifier, node ID, clock sequence, and the current time + * + * @see UuidV2 + */ +interface DceSecurityGeneratorInterface +{ + /** + * Generate a binary string from a local domain, local identifier, node ID, + * clock sequence, and current time + * + * @param int $localDomain The local domain to use when generating bytes, + * according to DCE Security + * @param IntegerObject|null $localIdentifier The local identifier for the + * given domain; this may be a UID or GID on POSIX systems, if the local + * domain is person or group, or it may be a site-defined identifier + * if the local domain is org + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return string A binary string + */ + public function generate( + int $localDomain, + ?IntegerObject $localIdentifier = null, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php new file mode 100644 index 00000000..7303e9fa --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php @@ -0,0 +1,48 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Exception\NameException; +use Ramsey\Uuid\UuidInterface; +use ValueError; + +use function hash; + +/** + * DefaultNameGenerator generates strings of binary data based on a namespace, + * name, and hashing algorithm + */ +class DefaultNameGenerator implements NameGeneratorInterface +{ + /** @psalm-pure */ + public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string + { + try { + /** @var string|bool $bytes */ + $bytes = @hash($hashAlgorithm, $ns->getBytes() . $name, true); + } catch (ValueError $e) { + $bytes = false; // keep same behavior than PHP 7 + } + + if ($bytes === false) { + throw new NameException(sprintf( + 'Unable to hash namespace and name with algorithm \'%s\'', + $hashAlgorithm + )); + } + + return (string) $bytes; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php new file mode 100644 index 00000000..d245c7bc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php @@ -0,0 +1,147 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Exception\RandomSourceException; +use Ramsey\Uuid\Exception\TimeSourceException; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Provider\TimeProviderInterface; +use Ramsey\Uuid\Type\Hexadecimal; +use Throwable; + +use function ctype_xdigit; +use function dechex; +use function hex2bin; +use function is_int; +use function pack; +use function sprintf; +use function str_pad; +use function strlen; + +use const STR_PAD_LEFT; + +/** + * DefaultTimeGenerator generates strings of binary data based on a node ID, + * clock sequence, and the current time + */ +class DefaultTimeGenerator implements TimeGeneratorInterface +{ + /** + * @var NodeProviderInterface + */ + private $nodeProvider; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * @var TimeProviderInterface + */ + private $timeProvider; + + public function __construct( + NodeProviderInterface $nodeProvider, + TimeConverterInterface $timeConverter, + TimeProviderInterface $timeProvider + ) { + $this->nodeProvider = $nodeProvider; + $this->timeConverter = $timeConverter; + $this->timeProvider = $timeProvider; + } + + /** + * @throws InvalidArgumentException if the parameters contain invalid values + * @throws RandomSourceException if random_int() throws an exception/error + * + * @inheritDoc + */ + public function generate($node = null, ?int $clockSeq = null): string + { + if ($node instanceof Hexadecimal) { + $node = $node->toString(); + } + + $node = $this->getValidNode($node); + + if ($clockSeq === null) { + try { + // This does not use "stable storage"; see RFC 4122, Section 4.2.1.1. + $clockSeq = random_int(0, 0x3fff); + } catch (Throwable $exception) { + throw new RandomSourceException( + $exception->getMessage(), + (int) $exception->getCode(), + $exception + ); + } + } + + $time = $this->timeProvider->getTime(); + + $uuidTime = $this->timeConverter->calculateTime( + $time->getSeconds()->toString(), + $time->getMicroseconds()->toString() + ); + + $timeHex = str_pad($uuidTime->toString(), 16, '0', STR_PAD_LEFT); + + if (strlen($timeHex) !== 16) { + throw new TimeSourceException(sprintf( + 'The generated time of \'%s\' is larger than expected', + $timeHex + )); + } + + $timeBytes = (string) hex2bin($timeHex); + + return $timeBytes[4] . $timeBytes[5] . $timeBytes[6] . $timeBytes[7] + . $timeBytes[2] . $timeBytes[3] + . $timeBytes[0] . $timeBytes[1] + . pack('n*', $clockSeq) + . $node; + } + + /** + * Uses the node provider given when constructing this instance to get + * the node ID (usually a MAC address) + * + * @param string|int|null $node A node value that may be used to override the node provider + * + * @return string 6-byte binary string representation of the node + * + * @throws InvalidArgumentException + */ + private function getValidNode($node): string + { + if ($node === null) { + $node = $this->nodeProvider->getNode(); + } + + // Convert the node to hex, if it is still an integer. + if (is_int($node)) { + $node = dechex($node); + } + + if (!ctype_xdigit((string) $node) || strlen((string) $node) > 12) { + throw new InvalidArgumentException('Invalid node value'); + } + + return (string) hex2bin(str_pad((string) $node, 12, '0', STR_PAD_LEFT)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php new file mode 100644 index 00000000..6f08e291 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php @@ -0,0 +1,30 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +/** + * NameGeneratorFactory retrieves a default name generator, based on the + * environment + */ +class NameGeneratorFactory +{ + /** + * Returns a default name generator, based on the current environment + */ + public function getGenerator(): NameGeneratorInterface + { + return new DefaultNameGenerator(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php new file mode 100644 index 00000000..cc43dd02 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\UuidInterface; + +/** + * A name generator generates strings of binary data created by hashing together + * a namespace with a name, according to a hashing algorithm + */ +interface NameGeneratorInterface +{ + /** + * Generate a binary string from a namespace and name hashed together with + * the specified hashing algorithm + * + * @param UuidInterface $ns The namespace + * @param string $name The name to use for creating a UUID + * @param string $hashAlgorithm The hashing algorithm to use + * + * @return string A binary string + * + * @psalm-pure + */ + public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php new file mode 100644 index 00000000..3780c5c6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php @@ -0,0 +1,54 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Exception\NameException; +use Ramsey\Uuid\UuidInterface; + +use function sprintf; +use function uuid_generate_md5; +use function uuid_generate_sha1; +use function uuid_parse; + +/** + * PeclUuidNameGenerator generates strings of binary data from a namespace and a + * name, using ext-uuid + * + * @link https://pecl.php.net/package/uuid ext-uuid + */ +class PeclUuidNameGenerator implements NameGeneratorInterface +{ + /** @psalm-pure */ + public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string + { + switch ($hashAlgorithm) { + case 'md5': + $uuid = uuid_generate_md5($ns->toString(), $name); + + break; + case 'sha1': + $uuid = uuid_generate_sha1($ns->toString(), $name); + + break; + default: + throw new NameException(sprintf( + 'Unable to hash namespace and name with algorithm \'%s\'', + $hashAlgorithm + )); + } + + return uuid_parse($uuid); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php new file mode 100644 index 00000000..07c47d26 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php @@ -0,0 +1,35 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use function uuid_create; +use function uuid_parse; + +use const UUID_TYPE_RANDOM; + +/** + * PeclUuidRandomGenerator generates strings of random binary data using ext-uuid + * + * @link https://pecl.php.net/package/uuid ext-uuid + */ +class PeclUuidRandomGenerator implements RandomGeneratorInterface +{ + public function generate(int $length): string + { + $uuid = uuid_create(UUID_TYPE_RANDOM); + + return uuid_parse($uuid); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php new file mode 100644 index 00000000..e01f44e5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php @@ -0,0 +1,39 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use function uuid_create; +use function uuid_parse; + +use const UUID_TYPE_TIME; + +/** + * PeclUuidTimeGenerator generates strings of binary data for time-base UUIDs, + * using ext-uuid + * + * @link https://pecl.php.net/package/uuid ext-uuid + */ +class PeclUuidTimeGenerator implements TimeGeneratorInterface +{ + /** + * @inheritDoc + */ + public function generate($node = null, ?int $clockSeq = null): string + { + $uuid = uuid_create(UUID_TYPE_TIME); + + return uuid_parse($uuid); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php new file mode 100644 index 00000000..12edb96a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php @@ -0,0 +1,45 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Exception\RandomSourceException; +use Throwable; + +/** + * RandomBytesGenerator generates strings of random binary data using the + * built-in `random_bytes()` PHP function + * + * @link http://php.net/random_bytes random_bytes() + */ +class RandomBytesGenerator implements RandomGeneratorInterface +{ + /** + * @throws RandomSourceException if random_bytes() throws an exception/error + * + * @inheritDoc + */ + public function generate(int $length): string + { + try { + return random_bytes($length); + } catch (Throwable $exception) { + throw new RandomSourceException( + $exception->getMessage(), + (int) $exception->getCode(), + $exception + ); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php new file mode 100644 index 00000000..b723ac29 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php @@ -0,0 +1,30 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +/** + * RandomGeneratorFactory retrieves a default random generator, based on the + * environment + */ +class RandomGeneratorFactory +{ + /** + * Returns a default random generator, based on the current environment + */ + public function getGenerator(): RandomGeneratorInterface + { + return new RandomBytesGenerator(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php new file mode 100644 index 00000000..5c83cb4d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php @@ -0,0 +1,30 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +/** + * A random generator generates strings of random binary data + */ +interface RandomGeneratorInterface +{ + /** + * Generates a string of randomized binary data + * + * @param int $length The number of bytes of random binary data to generate + * + * @return string A binary string + */ + public function generate(int $length): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php new file mode 100644 index 00000000..24ed5692 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php @@ -0,0 +1,55 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use RandomLib\Factory; +use RandomLib\Generator; + +/** + * RandomLibAdapter generates strings of random binary data using the + * paragonie/random-lib library + * + * @link https://packagist.org/packages/paragonie/random-lib paragonie/random-lib + */ +class RandomLibAdapter implements RandomGeneratorInterface +{ + /** + * @var Generator + */ + private $generator; + + /** + * Constructs a RandomLibAdapter + * + * By default, if no Generator is passed in, this creates a high-strength + * generator to use when generating random binary data. + * + * @param Generator|null $generator The generator to use when generating binary data + */ + public function __construct(?Generator $generator = null) + { + if ($generator === null) { + $factory = new Factory(); + $generator = $factory->getHighStrengthGenerator(); + } + + $this->generator = $generator; + } + + public function generate(int $length): string + { + return $this->generator->generate($length); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php new file mode 100644 index 00000000..3d55fc4d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php @@ -0,0 +1,63 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Provider\TimeProviderInterface; + +/** + * TimeGeneratorFactory retrieves a default time generator, based on the + * environment + */ +class TimeGeneratorFactory +{ + /** + * @var NodeProviderInterface + */ + private $nodeProvider; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * @var TimeProviderInterface + */ + private $timeProvider; + + public function __construct( + NodeProviderInterface $nodeProvider, + TimeConverterInterface $timeConverter, + TimeProviderInterface $timeProvider + ) { + $this->nodeProvider = $nodeProvider; + $this->timeConverter = $timeConverter; + $this->timeProvider = $timeProvider; + } + + /** + * Returns a default time generator, based on the current environment + */ + public function getGenerator(): TimeGeneratorInterface + { + return new DefaultTimeGenerator( + $this->nodeProvider, + $this->timeConverter, + $this->timeProvider + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php new file mode 100644 index 00000000..18f21c4b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Generator; + +use Ramsey\Uuid\Type\Hexadecimal; + +/** + * A time generator generates strings of binary data based on a node ID, + * clock sequence, and the current time + */ +interface TimeGeneratorInterface +{ + /** + * Generate a binary string from a node ID, clock sequence, and current time + * + * @param Hexadecimal|int|string|null $node A 48-bit number representing the + * hardware address; this number may be represented as an integer or a + * hexadecimal string + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return string A binary string + */ + public function generate($node = null, ?int $clockSeq = null): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Fields.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Fields.php new file mode 100644 index 00000000..d8a1a2b1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Fields.php @@ -0,0 +1,194 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Guid; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Fields\SerializableFieldsTrait; +use Ramsey\Uuid\Rfc4122\FieldsInterface; +use Ramsey\Uuid\Rfc4122\NilTrait; +use Ramsey\Uuid\Rfc4122\VariantTrait; +use Ramsey\Uuid\Rfc4122\VersionTrait; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Uuid; + +use function bin2hex; +use function dechex; +use function hexdec; +use function pack; +use function sprintf; +use function str_pad; +use function strlen; +use function substr; +use function unpack; + +use const STR_PAD_LEFT; + +/** + * GUIDs are comprised of a set of named fields, according to RFC 4122 + * + * @see Guid + * + * @psalm-immutable + */ +final class Fields implements FieldsInterface +{ + use NilTrait; + use SerializableFieldsTrait; + use VariantTrait; + use VersionTrait; + + /** + * @var string + */ + private $bytes; + + /** + * @param string $bytes A 16-byte binary string representation of a UUID + * + * @throws InvalidArgumentException if the byte string is not exactly 16 bytes + * @throws InvalidArgumentException if the byte string does not represent a GUID + * @throws InvalidArgumentException if the byte string does not contain a valid version + */ + public function __construct(string $bytes) + { + if (strlen($bytes) !== 16) { + throw new InvalidArgumentException( + 'The byte string must be 16 bytes long; ' + . 'received ' . strlen($bytes) . ' bytes' + ); + } + + $this->bytes = $bytes; + + if (!$this->isCorrectVariant()) { + throw new InvalidArgumentException( + 'The byte string received does not conform to the RFC ' + . '4122 or Microsoft Corporation variants' + ); + } + + if (!$this->isCorrectVersion()) { + throw new InvalidArgumentException( + 'The byte string received does not contain a valid version' + ); + } + } + + public function getBytes(): string + { + return $this->bytes; + } + + public function getTimeLow(): Hexadecimal + { + // Swap the bytes from little endian to network byte order. + /** @var array $hex */ + $hex = unpack( + 'H*', + pack( + 'v*', + hexdec(bin2hex(substr($this->bytes, 2, 2))), + hexdec(bin2hex(substr($this->bytes, 0, 2))) + ) + ); + + return new Hexadecimal((string) ($hex[1] ?? '')); + } + + public function getTimeMid(): Hexadecimal + { + // Swap the bytes from little endian to network byte order. + /** @var array $hex */ + $hex = unpack( + 'H*', + pack( + 'v', + hexdec(bin2hex(substr($this->bytes, 4, 2))) + ) + ); + + return new Hexadecimal((string) ($hex[1] ?? '')); + } + + public function getTimeHiAndVersion(): Hexadecimal + { + // Swap the bytes from little endian to network byte order. + /** @var array $hex */ + $hex = unpack( + 'H*', + pack( + 'v', + hexdec(bin2hex(substr($this->bytes, 6, 2))) + ) + ); + + return new Hexadecimal((string) ($hex[1] ?? '')); + } + + public function getTimestamp(): Hexadecimal + { + return new Hexadecimal(sprintf( + '%03x%04s%08s', + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff, + $this->getTimeMid()->toString(), + $this->getTimeLow()->toString() + )); + } + + public function getClockSeq(): Hexadecimal + { + $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff; + + return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT)); + } + + public function getClockSeqHiAndReserved(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1))); + } + + public function getClockSeqLow(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1))); + } + + public function getNode(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 10))); + } + + public function getVersion(): ?int + { + if ($this->isNil()) { + return null; + } + + /** @var array $parts */ + $parts = unpack('n*', $this->bytes); + + return ((int) $parts[4] >> 4) & 0x00f; + } + + private function isCorrectVariant(): bool + { + if ($this->isNil()) { + return true; + } + + $variant = $this->getVariant(); + + return $variant === Uuid::RFC_4122 || $variant === Uuid::RESERVED_MICROSOFT; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Guid.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Guid.php new file mode 100644 index 00000000..b3ed096a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/Guid.php @@ -0,0 +1,61 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Guid; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Uuid; + +/** + * Guid represents a UUID with "native" (little-endian) byte order + * + * From Wikipedia: + * + * > The first three fields are unsigned 32- and 16-bit integers and are subject + * > to swapping, while the last two fields consist of uninterpreted bytes, not + * > subject to swapping. This byte swapping applies even for versions 3, 4, and + * > 5, where the canonical fields do not correspond to the content of the UUID. + * + * The first three fields of a GUID are encoded in little-endian byte order, + * while the last three fields are in network (big-endian) byte order. This is + * according to the history of the Microsoft definition of a GUID. + * + * According to the .NET Guid.ToByteArray method documentation: + * + * > Note that the order of bytes in the returned byte array is different from + * > the string representation of a Guid value. The order of the beginning + * > four-byte group and the next two two-byte groups is reversed, whereas the + * > order of the last two-byte group and the closing six-byte group is the + * > same. + * + * @link https://en.wikipedia.org/wiki/Universally_unique_identifier#Variants UUID Variants on Wikipedia + * @link https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid Windows GUID structure + * @link https://docs.microsoft.com/en-us/dotnet/api/system.guid .NET Guid Struct + * @link https://docs.microsoft.com/en-us/dotnet/api/system.guid.tobytearray .NET Guid.ToByteArray Method + * + * @psalm-immutable + */ +final class Guid extends Uuid +{ + public function __construct( + Fields $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/GuidBuilder.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/GuidBuilder.php new file mode 100644 index 00000000..758dd6b7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Guid/GuidBuilder.php @@ -0,0 +1,89 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Guid; + +use Ramsey\Uuid\Builder\UuidBuilderInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\UnableToBuildUuidException; +use Ramsey\Uuid\UuidInterface; +use Throwable; + +/** + * GuidBuilder builds instances of Guid + * + * @see Guid + * + * @psalm-immutable + */ +class GuidBuilder implements UuidBuilderInterface +{ + /** + * @var NumberConverterInterface + */ + private $numberConverter; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * @param NumberConverterInterface $numberConverter The number converter to + * use when constructing the Guid + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to Unix timestamps + */ + public function __construct( + NumberConverterInterface $numberConverter, + TimeConverterInterface $timeConverter + ) { + $this->numberConverter = $numberConverter; + $this->timeConverter = $timeConverter; + } + + /** + * Builds and returns a Guid + * + * @param CodecInterface $codec The codec to use for building this Guid instance + * @param string $bytes The byte string from which to construct a UUID + * + * @return Guid The GuidBuilder returns an instance of Ramsey\Uuid\Guid\Guid + * + * @psalm-pure + */ + public function build(CodecInterface $codec, string $bytes): UuidInterface + { + try { + return new Guid( + $this->buildFields($bytes), + $this->numberConverter, + $codec, + $this->timeConverter + ); + } catch (Throwable $e) { + throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e); + } + } + + /** + * Proxy method to allow injecting a mock, for testing + */ + protected function buildFields(string $bytes): Fields + { + return new Fields($bytes); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php new file mode 100644 index 00000000..8ba75796 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php @@ -0,0 +1,575 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Lazy; + +use DateTimeInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Exception\UnsupportedOperationException; +use Ramsey\Uuid\Fields\FieldsInterface; +use Ramsey\Uuid\Nonstandard\UuidV6; +use Ramsey\Uuid\Rfc4122\UuidV1; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\UuidFactory; +use Ramsey\Uuid\UuidInterface; +use ValueError; + +use function assert; +use function bin2hex; +use function hex2bin; +use function sprintf; +use function str_replace; +use function substr; + +/** + * Lazy version of a UUID: its format has not been determined yet, so it is mostly only usable for string/bytes + * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of + * increased overhead for more advanced UUID operations. + * + * @internal this type is used internally for performance reasons, and is not supposed to be directly referenced + * in consumer libraries. + * + * @psalm-immutable + * + * Note: the {@see FieldsInterface} does not declare methods that deprecated API + * relies upon: the API has been ported from the {@see \Ramsey\Uuid\Uuid} definition, + * and is deprecated anyway. + * Note: the deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed + * once the deprecated API is gone from this class too. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + */ +final class LazyUuidFromString implements UuidInterface +{ + public const VALID_REGEX = '/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/ms'; + /** + * @var string + * @psalm-var non-empty-string + */ + private $uuid; + /** @var UuidInterface|null */ + private $unwrapped; + + /** @psalm-param non-empty-string $uuid */ + public function __construct(string $uuid) + { + $this->uuid = $uuid; + } + + /** @psalm-pure */ + public static function fromBytes(string $bytes): self + { + $base16Uuid = bin2hex($bytes); + + return new self( + substr($base16Uuid, 0, 8) + . '-' + . substr($base16Uuid, 8, 4) + . '-' + . substr($base16Uuid, 12, 4) + . '-' + . substr($base16Uuid, 16, 4) + . '-' + . substr($base16Uuid, 20, 12) + ); + } + + public function serialize(): string + { + return $this->uuid; + } + + /** + * @return array{string: string} + * + * @psalm-return array{string: non-empty-string} + */ + public function __serialize(): array + { + return ['string' => $this->uuid]; + } + + /** + * {@inheritDoc} + * + * @param string $serialized + * + * @psalm-param non-empty-string $serialized + */ + public function unserialize($serialized): void + { + $this->uuid = $serialized; + } + + /** + * @param array{string: string} $data + * + * @psalm-param array{string: non-empty-string} $data + */ + public function __unserialize(array $data): void + { + // @codeCoverageIgnoreStart + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $this->unserialize($data['string']); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getNumberConverter(): NumberConverterInterface + { + return ($this->unwrapped ?? $this->unwrap()) + ->getNumberConverter(); + } + + /** + * {@inheritDoc} + * + * @psalm-suppress DeprecatedMethod + */ + public function getFieldsHex(): array + { + return ($this->unwrapped ?? $this->unwrap()) + ->getFieldsHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getClockSeqHiAndReservedHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getClockSeqHiAndReservedHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getClockSeqLowHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getClockSeqLowHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getClockSequenceHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getClockSequenceHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getDateTime(): DateTimeInterface + { + return ($this->unwrapped ?? $this->unwrap()) + ->getDateTime(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getLeastSignificantBitsHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getLeastSignificantBitsHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getMostSignificantBitsHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getMostSignificantBitsHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getNodeHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getNodeHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimeHiAndVersionHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimeHiAndVersionHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimeLowHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimeLowHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimeMidHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimeMidHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getTimestampHex(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getTimestampHex(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getUrn(): string + { + return ($this->unwrapped ?? $this->unwrap()) + ->getUrn(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getVariant(): ?int + { + return ($this->unwrapped ?? $this->unwrap()) + ->getVariant(); + } + + /** @psalm-suppress DeprecatedMethod */ + public function getVersion(): ?int + { + return ($this->unwrapped ?? $this->unwrap()) + ->getVersion(); + } + + public function compareTo(UuidInterface $other): int + { + return ($this->unwrapped ?? $this->unwrap()) + ->compareTo($other); + } + + public function equals(?object $other): bool + { + if (! $other instanceof UuidInterface) { + return false; + } + + return $this->uuid === $other->toString(); + } + + /** + * {@inheritDoc} + * + * @psalm-suppress MoreSpecificReturnType + * @psalm-suppress LessSpecificReturnStatement we know that {@see self::$uuid} is a non-empty string, so + * we know that {@see hex2bin} will retrieve a non-empty string too. + */ + public function getBytes(): string + { + /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */ + return (string) hex2bin(str_replace('-', '', $this->uuid)); + } + + public function getFields(): FieldsInterface + { + return ($this->unwrapped ?? $this->unwrap()) + ->getFields(); + } + + public function getHex(): Hexadecimal + { + return ($this->unwrapped ?? $this->unwrap()) + ->getHex(); + } + + public function getInteger(): IntegerObject + { + return ($this->unwrapped ?? $this->unwrap()) + ->getInteger(); + } + + public function toString(): string + { + return $this->uuid; + } + + public function __toString(): string + { + return $this->uuid; + } + + public function jsonSerialize(): string + { + return $this->uuid; + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getClockSeqHiAndReserved(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getClockSeqHiAndReserved() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getClockSeqLow(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getClockSeqLow() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getClockSequence(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getClockSeq() + ->toString() + ); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getLeastSignificantBits(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex(substr($instance->getHex()->toString(), 16)); + } + + /** + * @deprecated This method will be removed in 5.0.0. There is no direct + * alternative, but the same information may be obtained by splitting + * in half the value returned by {@see UuidInterface::getHex()}. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getMostSignificantBits(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex(substr($instance->getHex()->toString(), 0, 16)); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getNode()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getNode(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getNode() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimeHiAndVersion(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getTimeHiAndVersion() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimeLow(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getTimeLow() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimeMid(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + return $instance->getNumberConverter() + ->fromHex( + $instance->getFields() + ->getTimeMid() + ->toString() + ); + } + + /** + * @deprecated Use {@see UuidInterface::getFields()} to get a + * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface} + * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()} + * and use the arbitrary-precision math library of your choice to + * convert it to a string integer. + * + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress DeprecatedMethod + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function getTimestamp(): string + { + $instance = ($this->unwrapped ?? $this->unwrap()); + $fields = $instance->getFields(); + + if ($fields->getVersion() !== 1) { + throw new UnsupportedOperationException('Not a time-based UUID'); + } + + return $instance->getNumberConverter() + ->fromHex($fields->getTimestamp()->toString()); + } + + public function toUuidV1(): UuidV1 + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + if ($instance instanceof UuidV1) { + return $instance; + } + + assert($instance instanceof UuidV6); + + return $instance->toUuidV1(); + } + + public function toUuidV6(): UuidV6 + { + $instance = ($this->unwrapped ?? $this->unwrap()); + + assert($instance instanceof UuidV6); + + return $instance; + } + + /** + * @psalm-suppress ImpureMethodCall the retrieval of the factory is a clear violation of purity here: this is a + * known pitfall of the design of this library, where a value object contains + * a mutable reference to a factory. We use a fixed factory here, so the violation + * will not have real-world effects, as this object is only instantiated with the + * default factory settings/features. + * @psalm-suppress InaccessibleProperty property {@see $unwrapped} is used as a cache: we don't expose it to the + * outside world, so we should be fine here. + */ + private function unwrap(): UuidInterface + { + return $this->unwrapped = (new UuidFactory()) + ->fromString($this->uuid); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php new file mode 100644 index 00000000..f2d86788 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php @@ -0,0 +1,144 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Math; + +use Brick\Math\BigDecimal; +use Brick\Math\BigInteger; +use Brick\Math\Exception\MathException; +use Brick\Math\RoundingMode as BrickMathRounding; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Type\Decimal; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Type\NumberInterface; + +/** + * A calculator using the brick/math library for arbitrary-precision arithmetic + * + * @psalm-immutable + */ +final class BrickMathCalculator implements CalculatorInterface +{ + private const ROUNDING_MODE_MAP = [ + RoundingMode::UNNECESSARY => BrickMathRounding::UNNECESSARY, + RoundingMode::UP => BrickMathRounding::UP, + RoundingMode::DOWN => BrickMathRounding::DOWN, + RoundingMode::CEILING => BrickMathRounding::CEILING, + RoundingMode::FLOOR => BrickMathRounding::FLOOR, + RoundingMode::HALF_UP => BrickMathRounding::HALF_UP, + RoundingMode::HALF_DOWN => BrickMathRounding::HALF_DOWN, + RoundingMode::HALF_CEILING => BrickMathRounding::HALF_CEILING, + RoundingMode::HALF_FLOOR => BrickMathRounding::HALF_FLOOR, + RoundingMode::HALF_EVEN => BrickMathRounding::HALF_EVEN, + ]; + + public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface + { + $sum = BigInteger::of($augend->toString()); + + foreach ($addends as $addend) { + $sum = $sum->plus($addend->toString()); + } + + return new IntegerObject((string) $sum); + } + + public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface + { + $difference = BigInteger::of($minuend->toString()); + + foreach ($subtrahends as $subtrahend) { + $difference = $difference->minus($subtrahend->toString()); + } + + return new IntegerObject((string) $difference); + } + + public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface + { + $product = BigInteger::of($multiplicand->toString()); + + foreach ($multipliers as $multiplier) { + $product = $product->multipliedBy($multiplier->toString()); + } + + return new IntegerObject((string) $product); + } + + public function divide( + int $roundingMode, + int $scale, + NumberInterface $dividend, + NumberInterface ...$divisors + ): NumberInterface { + $brickRounding = $this->getBrickRoundingMode($roundingMode); + + $quotient = BigDecimal::of($dividend->toString()); + + foreach ($divisors as $divisor) { + $quotient = $quotient->dividedBy($divisor->toString(), $scale, $brickRounding); + } + + if ($scale === 0) { + return new IntegerObject((string) $quotient->toBigInteger()); + } + + return new Decimal((string) $quotient); + } + + public function fromBase(string $value, int $base): IntegerObject + { + try { + return new IntegerObject((string) BigInteger::fromBase($value, $base)); + } catch (MathException | \InvalidArgumentException $exception) { + throw new InvalidArgumentException( + $exception->getMessage(), + (int) $exception->getCode(), + $exception + ); + } + } + + public function toBase(IntegerObject $value, int $base): string + { + try { + return BigInteger::of($value->toString())->toBase($base); + } catch (MathException | \InvalidArgumentException $exception) { + throw new InvalidArgumentException( + $exception->getMessage(), + (int) $exception->getCode(), + $exception + ); + } + } + + public function toHexadecimal(IntegerObject $value): Hexadecimal + { + return new Hexadecimal($this->toBase($value, 16)); + } + + public function toInteger(Hexadecimal $value): IntegerObject + { + return $this->fromBase($value->toString(), 16); + } + + /** + * Maps ramsey/uuid rounding modes to those used by brick/math + */ + private function getBrickRoundingMode(int $roundingMode): int + { + return self::ROUNDING_MODE_MAP[$roundingMode] ?? 0; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/CalculatorInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/CalculatorInterface.php new file mode 100644 index 00000000..f03645d0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/CalculatorInterface.php @@ -0,0 +1,106 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Math; + +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Type\NumberInterface; + +/** + * A calculator performs arithmetic operations on numbers + * + * @psalm-immutable + */ +interface CalculatorInterface +{ + /** + * Returns the sum of all the provided parameters + * + * @param NumberInterface $augend The first addend (the integer being added to) + * @param NumberInterface ...$addends The additional integers to a add to the augend + * + * @return NumberInterface The sum of all the parameters + */ + public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface; + + /** + * Returns the difference of all the provided parameters + * + * @param NumberInterface $minuend The integer being subtracted from + * @param NumberInterface ...$subtrahends The integers to subtract from the minuend + * + * @return NumberInterface The difference after subtracting all parameters + */ + public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface; + + /** + * Returns the product of all the provided parameters + * + * @param NumberInterface $multiplicand The integer to be multiplied + * @param NumberInterface ...$multipliers The factors by which to multiply the multiplicand + * + * @return NumberInterface The product of multiplying all the provided parameters + */ + public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface; + + /** + * Returns the quotient of the provided parameters divided left-to-right + * + * @param int $roundingMode The RoundingMode constant to use for this operation + * @param int $scale The scale to use for this operation + * @param NumberInterface $dividend The integer to be divided + * @param NumberInterface ...$divisors The integers to divide $dividend by, in + * the order in which the division operations should take place + * (left-to-right) + * + * @return NumberInterface The quotient of dividing the provided parameters left-to-right + */ + public function divide( + int $roundingMode, + int $scale, + NumberInterface $dividend, + NumberInterface ...$divisors + ): NumberInterface; + + /** + * Converts a value from an arbitrary base to a base-10 integer value + * + * @param string $value The value to convert + * @param int $base The base to convert from (i.e., 2, 16, 32, etc.) + * + * @return IntegerObject The base-10 integer value of the converted value + */ + public function fromBase(string $value, int $base): IntegerObject; + + /** + * Converts a base-10 integer value to an arbitrary base + * + * @param IntegerObject $value The integer value to convert + * @param int $base The base to convert to (i.e., 2, 16, 32, etc.) + * + * @return string The value represented in the specified base + */ + public function toBase(IntegerObject $value, int $base): string; + + /** + * Converts an Integer instance to a Hexadecimal instance + */ + public function toHexadecimal(IntegerObject $value): Hexadecimal; + + /** + * Converts a Hexadecimal instance to an Integer instance + */ + public function toInteger(Hexadecimal $value): IntegerObject; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/RoundingMode.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/RoundingMode.php new file mode 100644 index 00000000..e710270d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Math/RoundingMode.php @@ -0,0 +1,146 @@ += 0.5; otherwise, behaves + * as for DOWN. Note that this is the rounding mode commonly taught at + * school. + */ + public const HALF_UP = 5; + + /** + * Rounds towards "nearest neighbor" unless both neighbors are equidistant, + * in which case round down. + * + * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves + * as for DOWN. + */ + public const HALF_DOWN = 6; + + /** + * Rounds towards "nearest neighbor" unless both neighbors are equidistant, + * in which case round towards positive infinity. + * + * If the result is positive, behaves as for HALF_UP; if negative, behaves + * as for HALF_DOWN. + */ + public const HALF_CEILING = 7; + + /** + * Rounds towards "nearest neighbor" unless both neighbors are equidistant, + * in which case round towards negative infinity. + * + * If the result is positive, behaves as for HALF_DOWN; if negative, behaves + * as for HALF_UP. + */ + public const HALF_FLOOR = 8; + + /** + * Rounds towards the "nearest neighbor" unless both neighbors are + * equidistant, in which case rounds towards the even neighbor. + * + * Behaves as for HALF_UP if the digit to the left of the discarded fraction + * is odd; behaves as for HALF_DOWN if it's even. + * + * Note that this is the rounding mode that statistically minimizes + * cumulative error when applied repeatedly over a sequence of calculations. + * It is sometimes known as "Banker's rounding", and is chiefly used in the + * USA. + */ + public const HALF_EVEN = 9; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Fields.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Fields.php new file mode 100644 index 00000000..927bc6a2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Fields.php @@ -0,0 +1,133 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Nonstandard; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Fields\SerializableFieldsTrait; +use Ramsey\Uuid\Rfc4122\FieldsInterface; +use Ramsey\Uuid\Rfc4122\VariantTrait; +use Ramsey\Uuid\Type\Hexadecimal; + +use function bin2hex; +use function dechex; +use function hexdec; +use function sprintf; +use function str_pad; +use function strlen; +use function substr; + +use const STR_PAD_LEFT; + +/** + * Nonstandard UUID fields do not conform to the RFC 4122 standard + * + * Since some systems may create nonstandard UUIDs, this implements the + * Rfc4122\FieldsInterface, so that functionality of a nonstandard UUID is not + * degraded, in the event these UUIDs are expected to contain RFC 4122 fields. + * + * Internally, this class represents the fields together as a 16-byte binary + * string. + * + * @psalm-immutable + */ +final class Fields implements FieldsInterface +{ + use SerializableFieldsTrait; + use VariantTrait; + + /** + * @var string + */ + private $bytes; + + /** + * @param string $bytes A 16-byte binary string representation of a UUID + * + * @throws InvalidArgumentException if the byte string is not exactly 16 bytes + */ + public function __construct(string $bytes) + { + if (strlen($bytes) !== 16) { + throw new InvalidArgumentException( + 'The byte string must be 16 bytes long; ' + . 'received ' . strlen($bytes) . ' bytes' + ); + } + + $this->bytes = $bytes; + } + + public function getBytes(): string + { + return $this->bytes; + } + + public function getClockSeq(): Hexadecimal + { + $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff; + + return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT)); + } + + public function getClockSeqHiAndReserved(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1))); + } + + public function getClockSeqLow(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1))); + } + + public function getNode(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 10))); + } + + public function getTimeHiAndVersion(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 6, 2))); + } + + public function getTimeLow(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 0, 4))); + } + + public function getTimeMid(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 4, 2))); + } + + public function getTimestamp(): Hexadecimal + { + return new Hexadecimal(sprintf( + '%03x%04s%08s', + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff, + $this->getTimeMid()->toString(), + $this->getTimeLow()->toString() + )); + } + + public function getVersion(): ?int + { + return null; + } + + public function isNil(): bool + { + return false; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Uuid.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Uuid.php new file mode 100644 index 00000000..715f8255 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/Uuid.php @@ -0,0 +1,37 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Nonstandard; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Uuid as BaseUuid; + +/** + * Nonstandard\Uuid is a UUID that doesn't conform to RFC 4122 + * + * @psalm-immutable + */ +final class Uuid extends BaseUuid +{ + public function __construct( + Fields $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php new file mode 100644 index 00000000..0c892773 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php @@ -0,0 +1,88 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Nonstandard; + +use Ramsey\Uuid\Builder\UuidBuilderInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\UnableToBuildUuidException; +use Ramsey\Uuid\UuidInterface; +use Throwable; + +/** + * Nonstandard\UuidBuilder builds instances of Nonstandard\Uuid + * + * @psalm-immutable + */ +class UuidBuilder implements UuidBuilderInterface +{ + /** + * @var NumberConverterInterface + */ + private $numberConverter; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * @param NumberConverterInterface $numberConverter The number converter to + * use when constructing the Nonstandard\Uuid + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to Unix timestamps + */ + public function __construct( + NumberConverterInterface $numberConverter, + TimeConverterInterface $timeConverter + ) { + $this->numberConverter = $numberConverter; + $this->timeConverter = $timeConverter; + } + + /** + * Builds and returns a Nonstandard\Uuid + * + * @param CodecInterface $codec The codec to use for building this instance + * @param string $bytes The byte string from which to construct a UUID + * + * @return Uuid The Nonstandard\UuidBuilder returns an instance of + * Nonstandard\Uuid + * + * @psalm-pure + */ + public function build(CodecInterface $codec, string $bytes): UuidInterface + { + try { + return new Uuid( + $this->buildFields($bytes), + $this->numberConverter, + $codec, + $this->timeConverter + ); + } catch (Throwable $e) { + throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e); + } + } + + /** + * Proxy method to allow injecting a mock, for testing + */ + protected function buildFields(string $bytes): Fields + { + return new Fields($bytes); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php new file mode 100644 index 00000000..05586b3e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php @@ -0,0 +1,133 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Nonstandard; + +use DateTimeImmutable; +use DateTimeInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\DateTimeException; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Lazy\LazyUuidFromString; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Rfc4122\UuidInterface; +use Ramsey\Uuid\Rfc4122\UuidV1; +use Ramsey\Uuid\Uuid; +use Throwable; + +use function hex2bin; +use function str_pad; +use function substr; + +use const STR_PAD_LEFT; + +/** + * Ordered-time, or version 6, UUIDs include timestamp, clock sequence, and node + * values that are combined into a 128-bit unsigned integer + * + * @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft + * @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs + * + * @psalm-immutable + */ +final class UuidV6 extends Uuid implements UuidInterface +{ + /** + * Creates a version 6 (time-based) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_PEABODY) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV6 must represent a ' + . 'version 6 (ordered-time) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * Returns a DateTimeInterface object representing the timestamp associated + * with the UUID + * + * @return DateTimeImmutable A PHP DateTimeImmutable instance representing + * the timestamp of a version 6 UUID + */ + public function getDateTime(): DateTimeInterface + { + $time = $this->timeConverter->convertTime($this->fields->getTimestamp()); + + try { + return new DateTimeImmutable( + '@' + . $time->getSeconds()->toString() + . '.' + . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT) + ); + } catch (Throwable $e) { + throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e); + } + } + + /** + * Converts this UUID into an instance of a version 1 UUID + */ + public function toUuidV1(): UuidV1 + { + $hex = $this->getHex()->toString(); + $hex = substr($hex, 7, 5) + . substr($hex, 13, 3) + . substr($hex, 3, 4) + . '1' . substr($hex, 0, 3) + . substr($hex, 16); + + /** @var LazyUuidFromString $uuid */ + $uuid = Uuid::fromBytes((string) hex2bin($hex)); + + return $uuid->toUuidV1(); + } + + /** + * Converts a version 1 UUID into an instance of a version 6 UUID + */ + public static function fromUuidV1(UuidV1 $uuidV1): UuidV6 + { + $hex = $uuidV1->getHex()->toString(); + $hex = substr($hex, 13, 3) + . substr($hex, 8, 4) + . substr($hex, 0, 5) + . '6' . substr($hex, 5, 3) + . substr($hex, 16); + + /** @var LazyUuidFromString $uuid */ + $uuid = Uuid::fromBytes((string) hex2bin($hex)); + + return $uuid->toUuidV6(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php new file mode 100644 index 00000000..6d6240b7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php @@ -0,0 +1,234 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Dce; + +use Ramsey\Uuid\Exception\DceSecurityException; +use Ramsey\Uuid\Provider\DceSecurityProviderInterface; +use Ramsey\Uuid\Type\Integer as IntegerObject; + +use function escapeshellarg; +use function preg_split; +use function str_getcsv; +use function strpos; +use function strrpos; +use function strtolower; +use function strtoupper; +use function substr; +use function trim; + +use const PREG_SPLIT_NO_EMPTY; + +/** + * SystemDceSecurityProvider retrieves the user or group identifiers from the system + */ +class SystemDceSecurityProvider implements DceSecurityProviderInterface +{ + /** + * @throws DceSecurityException if unable to get a user identifier + * + * @inheritDoc + */ + public function getUid(): IntegerObject + { + static $uid = null; + + if ($uid instanceof IntegerObject) { + return $uid; + } + + if ($uid === null) { + $uid = $this->getSystemUid(); + } + + if ($uid === '') { + throw new DceSecurityException( + 'Unable to get a user identifier using the system DCE ' + . 'Security provider; please provide a custom identifier or ' + . 'use a different provider' + ); + } + + $uid = new IntegerObject($uid); + + return $uid; + } + + /** + * @throws DceSecurityException if unable to get a group identifier + * + * @inheritDoc + */ + public function getGid(): IntegerObject + { + static $gid = null; + + if ($gid instanceof IntegerObject) { + return $gid; + } + + if ($gid === null) { + $gid = $this->getSystemGid(); + } + + if ($gid === '') { + throw new DceSecurityException( + 'Unable to get a group identifier using the system DCE ' + . 'Security provider; please provide a custom identifier or ' + . 'use a different provider' + ); + } + + $gid = new IntegerObject($gid); + + return $gid; + } + + /** + * Returns the UID from the system + */ + private function getSystemUid(): string + { + if (!$this->hasShellExec()) { + return ''; + } + + switch ($this->getOs()) { + case 'WIN': + return $this->getWindowsUid(); + case 'DAR': + case 'FRE': + case 'LIN': + default: + return trim((string) shell_exec('id -u')); + } + } + + /** + * Returns the GID from the system + */ + private function getSystemGid(): string + { + if (!$this->hasShellExec()) { + return ''; + } + + switch ($this->getOs()) { + case 'WIN': + return $this->getWindowsGid(); + case 'DAR': + case 'FRE': + case 'LIN': + default: + return trim((string) shell_exec('id -g')); + } + } + + /** + * Returns true if shell_exec() is available for use + */ + private function hasShellExec(): bool + { + $disabledFunctions = strtolower((string) ini_get('disable_functions')); + + return strpos($disabledFunctions, 'shell_exec') === false; + } + + /** + * Returns the PHP_OS string + */ + private function getOs(): string + { + return strtoupper(substr(constant('PHP_OS'), 0, 3)); + } + + /** + * Returns the user identifier for a user on a Windows system + * + * Windows does not have the same concept as an effective POSIX UID for the + * running script. Instead, each user is uniquely identified by an SID + * (security identifier). The SID includes three 32-bit unsigned integers + * that make up a unique domain identifier, followed by an RID (relative + * identifier) that we will use as the UID. The primary caveat is that this + * UID may not be unique to the system, since it is, instead, unique to the + * domain. + * + * @link https://www.lifewire.com/what-is-an-sid-number-2626005 What Is an SID Number? + * @link https://bit.ly/30vE7NM Well-known SID Structures + * @link https://bit.ly/2FWcYKJ Well-known security identifiers in Windows operating systems + * @link https://www.windows-commandline.com/get-sid-of-user/ Get SID of user + */ + private function getWindowsUid(): string + { + $response = shell_exec('whoami /user /fo csv /nh'); + + if ($response === null) { + return ''; + } + + $sid = str_getcsv(trim((string) $response))[1] ?? ''; + + if (($lastHyphen = strrpos($sid, '-')) === false) { + return ''; + } + + return trim(substr($sid, $lastHyphen + 1)); + } + + /** + * Returns a group identifier for a user on a Windows system + * + * Since Windows does not have the same concept as an effective POSIX GID + * for the running script, we will get the local group memberships for the + * user running the script. Then, we will get the SID (security identifier) + * for the first group that appears in that list. Finally, we will return + * the RID (relative identifier) for the group and use that as the GID. + * + * @link https://www.windows-commandline.com/list-of-user-groups-command-line/ List of user groups command line + */ + private function getWindowsGid(): string + { + $response = shell_exec('net user %username% | findstr /b /i "Local Group Memberships"'); + + if ($response === null) { + return ''; + } + + /** @var string[] $userGroups */ + $userGroups = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY); + + $firstGroup = trim($userGroups[1] ?? '', "* \t\n\r\0\x0B"); + + if ($firstGroup === '') { + return ''; + } + + $response = shell_exec('wmic group get name,sid | findstr /b /i ' . escapeshellarg($firstGroup)); + + if ($response === null) { + return ''; + } + + /** @var string[] $userGroup */ + $userGroup = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY); + + $sid = $userGroup[1] ?? ''; + + if (($lastHyphen = strrpos($sid, '-')) === false) { + return ''; + } + + return trim((string) substr($sid, $lastHyphen + 1)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php new file mode 100644 index 00000000..8325da69 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php @@ -0,0 +1,41 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider; + +use Ramsey\Uuid\Rfc4122\UuidV2; +use Ramsey\Uuid\Type\Integer as IntegerObject; + +/** + * A DCE provider provides access to local domain identifiers for version 2, + * DCE Security, UUIDs + * + * @see UuidV2 + */ +interface DceSecurityProviderInterface +{ + /** + * Returns a user identifier for the system + * + * @link https://en.wikipedia.org/wiki/User_identifier User identifier + */ + public function getUid(): IntegerObject; + + /** + * Returns a group identifier for the system + * + * @link https://en.wikipedia.org/wiki/Group_identifier Group identifier + */ + public function getGid(): IntegerObject; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php new file mode 100644 index 00000000..cad01045 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php @@ -0,0 +1,60 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Node; + +use Ramsey\Uuid\Exception\NodeException; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Type\Hexadecimal; + +/** + * FallbackNodeProvider retrieves the system node ID by stepping through a list + * of providers until a node ID can be obtained + */ +class FallbackNodeProvider implements NodeProviderInterface +{ + /** + * @var NodeProviderCollection + */ + private $nodeProviders; + + /** + * @param NodeProviderCollection $providers Array of node providers + */ + public function __construct(NodeProviderCollection $providers) + { + $this->nodeProviders = $providers; + } + + public function getNode(): Hexadecimal + { + $lastProviderException = null; + + foreach ($this->nodeProviders as $provider) { + try { + return $provider->getNode(); + } catch (NodeException $exception) { + $lastProviderException = $exception; + + continue; + } + } + + throw new NodeException( + 'Unable to find a suitable node provider', + 0, + $lastProviderException + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php new file mode 100644 index 00000000..536cb603 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php @@ -0,0 +1,61 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Node; + +use Ramsey\Collection\AbstractCollection; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Type\Hexadecimal; + +/** + * A collection of NodeProviderInterface objects + * + * @extends AbstractCollection + */ +class NodeProviderCollection extends AbstractCollection +{ + public function getType(): string + { + return NodeProviderInterface::class; + } + + /** + * Re-constructs the object from its serialized form + * + * @param string $serialized The serialized PHP string to unserialize into + * a UuidInterface instance + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @psalm-suppress RedundantConditionGivenDocblockType + */ + public function unserialize($serialized): void + { + /** @var array $data */ + $data = unserialize($serialized, [ + 'allowed_classes' => [ + Hexadecimal::class, + RandomNodeProvider::class, + StaticNodeProvider::class, + SystemNodeProvider::class, + ], + ]); + + $this->data = array_filter( + $data, + function ($unserialized): bool { + return $unserialized instanceof NodeProviderInterface; + } + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php new file mode 100644 index 00000000..76141361 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php @@ -0,0 +1,69 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Node; + +use Ramsey\Uuid\Exception\RandomSourceException; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Type\Hexadecimal; +use Throwable; + +use function bin2hex; +use function dechex; +use function hex2bin; +use function hexdec; +use function str_pad; +use function substr; + +use const STR_PAD_LEFT; + +/** + * RandomNodeProvider generates a random node ID + * + * @link http://tools.ietf.org/html/rfc4122#section-4.5 RFC 4122, § 4.5: Node IDs that Do Not Identify the Host + */ +class RandomNodeProvider implements NodeProviderInterface +{ + public function getNode(): Hexadecimal + { + try { + $nodeBytes = random_bytes(6); + } catch (Throwable $exception) { + throw new RandomSourceException( + $exception->getMessage(), + (int) $exception->getCode(), + $exception + ); + } + + // Split the node bytes for math on 32-bit systems. + $nodeMsb = substr($nodeBytes, 0, 3); + $nodeLsb = substr($nodeBytes, 3); + + // Set the multicast bit; see RFC 4122, section 4.5. + $nodeMsb = hex2bin( + str_pad( + dechex(hexdec(bin2hex($nodeMsb)) | 0x010000), + 6, + '0', + STR_PAD_LEFT + ) + ); + + // Recombine the node bytes. + $node = $nodeMsb . $nodeLsb; + + return new Hexadecimal(str_pad(bin2hex($node), 12, '0', STR_PAD_LEFT)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php new file mode 100644 index 00000000..51f1b02e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php @@ -0,0 +1,76 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Node; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Type\Hexadecimal; + +use function dechex; +use function hexdec; +use function str_pad; +use function substr; + +use const STR_PAD_LEFT; + +/** + * StaticNodeProvider provides a static node value with the multicast bit set + * + * @link http://tools.ietf.org/html/rfc4122#section-4.5 RFC 4122, § 4.5: Node IDs that Do Not Identify the Host + */ +class StaticNodeProvider implements NodeProviderInterface +{ + /** + * @var Hexadecimal + */ + private $node; + + /** + * @param Hexadecimal $node The static node value to use + */ + public function __construct(Hexadecimal $node) + { + if (strlen($node->toString()) > 12) { + throw new InvalidArgumentException( + 'Static node value cannot be greater than 12 hexadecimal characters' + ); + } + + $this->node = $this->setMulticastBit($node); + } + + public function getNode(): Hexadecimal + { + return $this->node; + } + + /** + * Set the multicast bit for the static node value + */ + private function setMulticastBit(Hexadecimal $node): Hexadecimal + { + $nodeHex = str_pad($node->toString(), 12, '0', STR_PAD_LEFT); + $firstOctet = substr($nodeHex, 0, 2); + + $firstOctet = str_pad( + dechex(hexdec($firstOctet) | 0x01), + 2, + '0', + STR_PAD_LEFT + ); + + return new Hexadecimal($firstOctet . substr($nodeHex, 2)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php new file mode 100644 index 00000000..d512f22a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php @@ -0,0 +1,173 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Node; + +use Ramsey\Uuid\Exception\NodeException; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Type\Hexadecimal; + +use function array_filter; +use function array_map; +use function array_walk; +use function count; +use function ob_get_clean; +use function ob_start; +use function preg_match; +use function preg_match_all; +use function reset; +use function str_replace; +use function strpos; +use function strtolower; +use function strtoupper; +use function substr; + +use const GLOB_NOSORT; +use const PREG_PATTERN_ORDER; + +/** + * SystemNodeProvider retrieves the system node ID, if possible + * + * The system node ID, or host ID, is often the same as the MAC address for a + * network interface on the host. + */ +class SystemNodeProvider implements NodeProviderInterface +{ + /** + * Pattern to match nodes in ifconfig and ipconfig output. + */ + private const IFCONFIG_PATTERN = '/[^:]([0-9a-f]{2}([:-])[0-9a-f]{2}(\2[0-9a-f]{2}){4})[^:]/i'; + + /** + * Pattern to match nodes in sysfs stream output. + */ + private const SYSFS_PATTERN = '/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i'; + + public function getNode(): Hexadecimal + { + $node = $this->getNodeFromSystem(); + + if ($node === '') { + throw new NodeException( + 'Unable to fetch a node for this system' + ); + } + + return new Hexadecimal($node); + } + + /** + * Returns the system node, if it can find it + */ + protected function getNodeFromSystem(): string + { + static $node = null; + + if ($node !== null) { + return (string) $node; + } + + // First, try a Linux-specific approach. + $node = $this->getSysfs(); + + if ($node === '') { + // Search ifconfig output for MAC addresses & return the first one. + $node = $this->getIfconfig(); + } + + $node = str_replace([':', '-'], '', $node); + + return $node; + } + + /** + * Returns the network interface configuration for the system + * + * @codeCoverageIgnore + */ + protected function getIfconfig(): string + { + $disabledFunctions = strtolower((string) ini_get('disable_functions')); + + if (strpos($disabledFunctions, 'passthru') !== false) { + return ''; + } + + ob_start(); + switch (strtoupper(substr(constant('PHP_OS'), 0, 3))) { + case 'WIN': + passthru('ipconfig /all 2>&1'); + + break; + case 'DAR': + passthru('ifconfig 2>&1'); + + break; + case 'FRE': + passthru('netstat -i -f link 2>&1'); + + break; + case 'LIN': + default: + passthru('netstat -ie 2>&1'); + + break; + } + + $ifconfig = (string) ob_get_clean(); + + $node = ''; + if (preg_match_all(self::IFCONFIG_PATTERN, $ifconfig, $matches, PREG_PATTERN_ORDER)) { + $node = $matches[1][0] ?? ''; + } + + return $node; + } + + /** + * Returns MAC address from the first system interface via the sysfs interface + */ + protected function getSysfs(): string + { + $mac = ''; + + if (strtoupper(constant('PHP_OS')) === 'LINUX') { + $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT); + + if ($addressPaths === false || count($addressPaths) === 0) { + return ''; + } + + $macs = []; + + array_walk($addressPaths, function (string $addressPath) use (&$macs): void { + if (is_readable($addressPath)) { + $macs[] = file_get_contents($addressPath); + } + }); + + $macs = array_map('trim', $macs); + + // Remove invalid entries. + $macs = array_filter($macs, function (string $address) { + return $address !== '00:00:00:00:00:00' + && preg_match(self::SYSFS_PATTERN, $address); + }); + + $mac = reset($macs); + } + + return (string) $mac; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/NodeProviderInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/NodeProviderInterface.php new file mode 100644 index 00000000..d536b455 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/NodeProviderInterface.php @@ -0,0 +1,30 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider; + +use Ramsey\Uuid\Type\Hexadecimal; + +/** + * A node provider retrieves or generates a node ID + */ +interface NodeProviderInterface +{ + /** + * Returns a node ID + * + * @return Hexadecimal The node ID as a hexadecimal string + */ + public function getNode(): Hexadecimal; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php new file mode 100644 index 00000000..b8bfd721 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php @@ -0,0 +1,63 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Time; + +use Ramsey\Uuid\Provider\TimeProviderInterface; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Type\Time; + +/** + * FixedTimeProvider uses an known time to provide the time + * + * This provider allows the use of a previously-generated, or known, time + * when generating time-based UUIDs. + */ +class FixedTimeProvider implements TimeProviderInterface +{ + /** + * @var Time + */ + private $fixedTime; + + public function __construct(Time $time) + { + $this->fixedTime = $time; + } + + /** + * Sets the `usec` component of the time + * + * @param int|string|IntegerObject $value The `usec` value to set + */ + public function setUsec($value): void + { + $this->fixedTime = new Time($this->fixedTime->getSeconds(), $value); + } + + /** + * Sets the `sec` component of the time + * + * @param int|string|IntegerObject $value The `sec` value to set + */ + public function setSec($value): void + { + $this->fixedTime = new Time($value, $this->fixedTime->getMicroseconds()); + } + + public function getTime(): Time + { + return $this->fixedTime; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php new file mode 100644 index 00000000..3a1e09cb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php @@ -0,0 +1,33 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider\Time; + +use Ramsey\Uuid\Provider\TimeProviderInterface; +use Ramsey\Uuid\Type\Time; + +use function gettimeofday; + +/** + * SystemTimeProvider retrieves the current time using built-in PHP functions + */ +class SystemTimeProvider implements TimeProviderInterface +{ + public function getTime(): Time + { + $time = gettimeofday(); + + return new Time($time['sec'], $time['usec']); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/TimeProviderInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/TimeProviderInterface.php new file mode 100644 index 00000000..43588e0b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Provider/TimeProviderInterface.php @@ -0,0 +1,28 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Provider; + +use Ramsey\Uuid\Type\Time; + +/** + * A time provider retrieves the current time + */ +interface TimeProviderInterface +{ + /** + * Returns a time object + */ + public function getTime(): Time; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Fields.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Fields.php new file mode 100644 index 00000000..2ccc20bb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Fields.php @@ -0,0 +1,194 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Fields\SerializableFieldsTrait; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Uuid; + +use function bin2hex; +use function dechex; +use function hexdec; +use function sprintf; +use function str_pad; +use function strlen; +use function substr; +use function unpack; + +use const STR_PAD_LEFT; + +/** + * RFC 4122 variant UUIDs are comprised of a set of named fields + * + * Internally, this class represents the fields together as a 16-byte binary + * string. + * + * @psalm-immutable + */ +final class Fields implements FieldsInterface +{ + use NilTrait; + use SerializableFieldsTrait; + use VariantTrait; + use VersionTrait; + + /** + * @var string + */ + private $bytes; + + /** + * @param string $bytes A 16-byte binary string representation of a UUID + * + * @throws InvalidArgumentException if the byte string is not exactly 16 bytes + * @throws InvalidArgumentException if the byte string does not represent an RFC 4122 UUID + * @throws InvalidArgumentException if the byte string does not contain a valid version + */ + public function __construct(string $bytes) + { + if (strlen($bytes) !== 16) { + throw new InvalidArgumentException( + 'The byte string must be 16 bytes long; ' + . 'received ' . strlen($bytes) . ' bytes' + ); + } + + $this->bytes = $bytes; + + if (!$this->isCorrectVariant()) { + throw new InvalidArgumentException( + 'The byte string received does not conform to the RFC 4122 variant' + ); + } + + if (!$this->isCorrectVersion()) { + throw new InvalidArgumentException( + 'The byte string received does not contain a valid RFC 4122 version' + ); + } + } + + public function getBytes(): string + { + return $this->bytes; + } + + public function getClockSeq(): Hexadecimal + { + $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff; + + return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT)); + } + + public function getClockSeqHiAndReserved(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1))); + } + + public function getClockSeqLow(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1))); + } + + public function getNode(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 10))); + } + + public function getTimeHiAndVersion(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 6, 2))); + } + + public function getTimeLow(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 0, 4))); + } + + public function getTimeMid(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 4, 2))); + } + + /** + * Returns the full 60-bit timestamp, without the version + * + * For version 2 UUIDs, the time_low field is the local identifier and + * should not be returned as part of the time. For this reason, we set the + * bottom 32 bits of the timestamp to 0's. As a result, there is some loss + * of fidelity of the timestamp, for version 2 UUIDs. The timestamp can be + * off by a range of 0 to 429.4967295 seconds (or 7 minutes, 9 seconds, and + * 496730 microseconds). + * + * For version 6 UUIDs, the timestamp order is reversed from the typical RFC + * 4122 order (the time bits are in the correct bit order, so that it is + * monotonically increasing). In returning the timestamp value, we put the + * bits in the order: time_low + time_mid + time_hi. + */ + public function getTimestamp(): Hexadecimal + { + switch ($this->getVersion()) { + case Uuid::UUID_TYPE_DCE_SECURITY: + $timestamp = sprintf( + '%03x%04s%08s', + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff, + $this->getTimeMid()->toString(), + '' + ); + + break; + case Uuid::UUID_TYPE_PEABODY: + $timestamp = sprintf( + '%08s%04s%03x', + $this->getTimeLow()->toString(), + $this->getTimeMid()->toString(), + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff + ); + + break; + default: + $timestamp = sprintf( + '%03x%04s%08s', + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff, + $this->getTimeMid()->toString(), + $this->getTimeLow()->toString() + ); + } + + return new Hexadecimal($timestamp); + } + + public function getVersion(): ?int + { + if ($this->isNil()) { + return null; + } + + /** @var array $parts */ + $parts = unpack('n*', $this->bytes); + + return (int) $parts[4] >> 12; + } + + private function isCorrectVariant(): bool + { + if ($this->isNil()) { + return true; + } + + return $this->getVariant() === Uuid::RFC_4122; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php new file mode 100644 index 00000000..a303525d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php @@ -0,0 +1,126 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Fields\FieldsInterface as BaseFieldsInterface; +use Ramsey\Uuid\Type\Hexadecimal; + +/** + * RFC 4122 defines fields for a specific variant of UUID + * + * The fields of an RFC 4122 variant UUID are: + * + * * **time_low**: The low field of the timestamp, an unsigned 32-bit integer + * * **time_mid**: The middle field of the timestamp, an unsigned 16-bit integer + * * **time_hi_and_version**: The high field of the timestamp multiplexed with + * the version number, an unsigned 16-bit integer + * * **clock_seq_hi_and_reserved**: The high field of the clock sequence + * multiplexed with the variant, an unsigned 8-bit integer + * * **clock_seq_low**: The low field of the clock sequence, an unsigned + * 8-bit integer + * * **node**: The spatially unique node identifier, an unsigned 48-bit + * integer + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1 RFC 4122, § 4.1: Format + * + * @psalm-immutable + */ +interface FieldsInterface extends BaseFieldsInterface +{ + /** + * Returns the full 16-bit clock sequence, with the variant bits (two most + * significant bits) masked out + */ + public function getClockSeq(): Hexadecimal; + + /** + * Returns the high field of the clock sequence multiplexed with the variant + */ + public function getClockSeqHiAndReserved(): Hexadecimal; + + /** + * Returns the low field of the clock sequence + */ + public function getClockSeqLow(): Hexadecimal; + + /** + * Returns the node field + */ + public function getNode(): Hexadecimal; + + /** + * Returns the high field of the timestamp multiplexed with the version + */ + public function getTimeHiAndVersion(): Hexadecimal; + + /** + * Returns the low field of the timestamp + */ + public function getTimeLow(): Hexadecimal; + + /** + * Returns the middle field of the timestamp + */ + public function getTimeMid(): Hexadecimal; + + /** + * Returns the full 60-bit timestamp, without the version + */ + public function getTimestamp(): Hexadecimal; + + /** + * Returns the variant + * + * The variant number describes the layout of the UUID. The variant + * number has the following meaning: + * + * - 0 - Reserved for NCS backward compatibility + * - 2 - The RFC 4122 variant + * - 6 - Reserved, Microsoft Corporation backward compatibility + * - 7 - Reserved for future definition + * + * For RFC 4122 variant UUIDs, this value should always be the integer `2`. + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant + */ + public function getVariant(): int; + + /** + * Returns the version + * + * The version number describes how the UUID was generated and has the + * following meaning: + * + * 1. Time-based UUID + * 2. DCE security UUID + * 3. Name-based UUID hashed with MD5 + * 4. Randomly generated UUID + * 5. Name-based UUID hashed with SHA-1 + * + * This returns `null` if the UUID is not an RFC 4122 variant, since version + * is only meaningful for this variant. + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version + */ + public function getVersion(): ?int; + + /** + * Returns true if these fields represent a nil UUID + * + * The nil UUID is special form of UUID that is specified to have all 128 + * bits set to zero. + */ + public function isNil(): bool; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php new file mode 100644 index 00000000..9a9774d8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php @@ -0,0 +1,41 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +/** + * Provides common functionality for nil UUIDs + * + * The nil UUID is special form of UUID that is specified to have all 128 bits + * set to zero. + * + * @link https://tools.ietf.org/html/rfc4122#section-4.1.7 RFC 4122, § 4.1.7: Nil UUID + * + * @psalm-immutable + */ +trait NilTrait +{ + /** + * Returns the bytes that comprise the fields + */ + abstract public function getBytes(): string; + + /** + * Returns true if the byte string represents a nil UUID + */ + public function isNil(): bool + { + return $this->getBytes() === "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php new file mode 100644 index 00000000..c49b9945 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php @@ -0,0 +1,27 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Uuid; + +/** + * The nil UUID is special form of UUID that is specified to have all 128 bits + * set to zero + * + * @psalm-immutable + */ +final class NilUuid extends Uuid implements UuidInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php new file mode 100644 index 00000000..736931af --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php @@ -0,0 +1,111 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Builder\UuidBuilderInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\UnableToBuildUuidException; +use Ramsey\Uuid\Exception\UnsupportedOperationException; +use Ramsey\Uuid\Nonstandard\UuidV6; +use Ramsey\Uuid\Rfc4122\UuidInterface as Rfc4122UuidInterface; +use Ramsey\Uuid\UuidInterface; +use Throwable; + +/** + * UuidBuilder builds instances of RFC 4122 UUIDs + * + * @psalm-immutable + */ +class UuidBuilder implements UuidBuilderInterface +{ + /** + * @var NumberConverterInterface + */ + private $numberConverter; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * Constructs the DefaultUuidBuilder + * + * @param NumberConverterInterface $numberConverter The number converter to + * use when constructing the Uuid + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to Unix timestamps + */ + public function __construct( + NumberConverterInterface $numberConverter, + TimeConverterInterface $timeConverter + ) { + $this->numberConverter = $numberConverter; + $this->timeConverter = $timeConverter; + } + + /** + * Builds and returns a Uuid + * + * @param CodecInterface $codec The codec to use for building this Uuid instance + * @param string $bytes The byte string from which to construct a UUID + * + * @return Rfc4122UuidInterface UuidBuilder returns instances of Rfc4122UuidInterface + * + * @psalm-pure + */ + public function build(CodecInterface $codec, string $bytes): UuidInterface + { + try { + $fields = $this->buildFields($bytes); + + if ($fields->isNil()) { + return new NilUuid($fields, $this->numberConverter, $codec, $this->timeConverter); + } + + switch ($fields->getVersion()) { + case 1: + return new UuidV1($fields, $this->numberConverter, $codec, $this->timeConverter); + case 2: + return new UuidV2($fields, $this->numberConverter, $codec, $this->timeConverter); + case 3: + return new UuidV3($fields, $this->numberConverter, $codec, $this->timeConverter); + case 4: + return new UuidV4($fields, $this->numberConverter, $codec, $this->timeConverter); + case 5: + return new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter); + case 6: + return new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter); + } + + throw new UnsupportedOperationException( + 'The UUID version in the given fields is not supported ' + . 'by this UUID builder' + ); + } catch (Throwable $e) { + throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e); + } + } + + /** + * Proxy method to allow injecting a mock, for testing + */ + protected function buildFields(string $bytes): FieldsInterface + { + return new Fields($bytes); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php new file mode 100644 index 00000000..3e4d9fae --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php @@ -0,0 +1,36 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\UuidInterface as BaseUuidInterface; + +/** + * Also known as a Leach-Salz variant UUID, an RFC 4122 variant UUID is a + * universally unique identifier defined by RFC 4122 + * + * @link https://tools.ietf.org/html/rfc4122 RFC 4122 + * + * @psalm-immutable + */ +interface UuidInterface extends BaseUuidInterface +{ + /** + * Returns the string standard representation of the UUID as a URN + * + * @link http://en.wikipedia.org/wiki/Uniform_Resource_Name Uniform Resource Name + * @link https://tools.ietf.org/html/rfc4122#section-3 RFC 4122, § 3: Namespace Registration Template + */ + public function getUrn(): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php new file mode 100644 index 00000000..764e42f8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php @@ -0,0 +1,92 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use DateTimeImmutable; +use DateTimeInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\DateTimeException; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Uuid; +use Throwable; + +use function str_pad; + +use const STR_PAD_LEFT; + +/** + * Time-based, or version 1, UUIDs include timestamp, clock sequence, and node + * values that are combined into a 128-bit unsigned integer + * + * @psalm-immutable + */ +final class UuidV1 extends Uuid implements UuidInterface +{ + /** + * Creates a version 1 (time-based) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_TIME) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV1 must represent a ' + . 'version 1 (time-based) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * Returns a DateTimeInterface object representing the timestamp associated + * with the UUID + * + * The timestamp value is only meaningful in a time-based UUID, which + * has version type 1. + * + * @return DateTimeImmutable A PHP DateTimeImmutable instance representing + * the timestamp of a version 1 UUID + */ + public function getDateTime(): DateTimeInterface + { + $time = $this->timeConverter->convertTime($this->fields->getTimestamp()); + + try { + return new DateTimeImmutable( + '@' + . $time->getSeconds()->toString() + . '.' + . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT) + ); + } catch (Throwable $e) { + throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php new file mode 100644 index 00000000..74906f05 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php @@ -0,0 +1,143 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use DateTimeImmutable; +use DateTimeInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\DateTimeException; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Uuid; +use Throwable; + +use function hexdec; +use function str_pad; + +use const STR_PAD_LEFT; + +/** + * DCE Security version, or version 2, UUIDs include local domain identifier, + * local ID for the specified domain, and node values that are combined into a + * 128-bit unsigned integer + * + * @link https://publications.opengroup.org/c311 DCE 1.1: Authentication and Security Services + * @link https://publications.opengroup.org/c706 DCE 1.1: Remote Procedure Call + * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 DCE 1.1: Auth & Sec, §5.2.1.1 + * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1: Auth & Sec, §11.5.1.1 + * @link https://pubs.opengroup.org/onlinepubs/9629399/apdxa.htm DCE 1.1: RPC, Appendix A + * @link https://github.com/google/uuid Go package for UUIDs (includes DCE implementation) + * + * @psalm-immutable + */ +final class UuidV2 extends Uuid implements UuidInterface +{ + /** + * Creates a version 2 (DCE Security) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_DCE_SECURITY) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV2 must represent a ' + . 'version 2 (DCE Security) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } + + /** + * Returns a DateTimeInterface object representing the timestamp associated + * with the UUID + * + * It is important to note that a version 2 UUID suffers from some loss of + * fidelity of the timestamp, due to replacing the time_low field with the + * local identifier. When constructing the timestamp value for date + * purposes, we replace the local identifier bits with zeros. As a result, + * the timestamp can be off by a range of 0 to 429.4967295 seconds (or 7 + * minutes, 9 seconds, and 496730 microseconds). + * + * Astute observers might note this value directly corresponds to 2^32 - 1, + * or 0xffffffff. The local identifier is 32-bits, and we have set each of + * these bits to 0, so the maximum range of timestamp drift is 0x00000000 + * to 0xffffffff (counted in 100-nanosecond intervals). + * + * @return DateTimeImmutable A PHP DateTimeImmutable instance representing + * the timestamp of a version 2 UUID + */ + public function getDateTime(): DateTimeInterface + { + $time = $this->timeConverter->convertTime($this->fields->getTimestamp()); + + try { + return new DateTimeImmutable( + '@' + . $time->getSeconds()->toString() + . '.' + . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT) + ); + } catch (Throwable $e) { + throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e); + } + } + + /** + * Returns the local domain used to create this version 2 UUID + */ + public function getLocalDomain(): int + { + /** @var Rfc4122FieldsInterface $fields */ + $fields = $this->getFields(); + + return (int) hexdec($fields->getClockSeqLow()->toString()); + } + + /** + * Returns the string name of the local domain + */ + public function getLocalDomainName(): string + { + return Uuid::DCE_DOMAIN_NAMES[$this->getLocalDomain()]; + } + + /** + * Returns the local identifier for the domain used to create this version 2 UUID + */ + public function getLocalIdentifier(): IntegerObject + { + /** @var Rfc4122FieldsInterface $fields */ + $fields = $this->getFields(); + + return new IntegerObject( + $this->numberConverter->fromHex($fields->getTimeLow()->toString()) + ); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php new file mode 100644 index 00000000..deaa54eb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php @@ -0,0 +1,58 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Uuid; + +/** + * Version 3 UUIDs are named-based, using combination of a namespace and name + * that are hashed into a 128-bit unsigned integer using MD5 + * + * @psalm-immutable + */ +final class UuidV3 extends Uuid implements UuidInterface +{ + /** + * Creates a version 3 (name-based, MD5-hashed) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_MD5) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV3 must represent a ' + . 'version 3 (name-based, MD5-hashed) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php new file mode 100644 index 00000000..2e572462 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php @@ -0,0 +1,58 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Uuid; + +/** + * Random, or version 4, UUIDs are randomly or pseudo-randomly generated 128-bit + * integers + * + * @psalm-immutable + */ +final class UuidV4 extends Uuid implements UuidInterface +{ + /** + * Creates a version 4 (random) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_RANDOM) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV4 must represent a ' + . 'version 4 (random) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php new file mode 100644 index 00000000..2ef6ab3f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php @@ -0,0 +1,58 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Uuid; + +/** + * Version 5 UUIDs are named-based, using combination of a namespace and name + * that are hashed into a 128-bit unsigned integer using SHA1 + * + * @psalm-immutable + */ +final class UuidV5 extends Uuid implements UuidInterface +{ + /** + * Creates a version 5 (name-based, SHA1-hashed) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_SHA1) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV5 must represent a ' + . 'version 5 (named-based, SHA1-hashed) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Validator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Validator.php new file mode 100644 index 00000000..ed43c982 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/Validator.php @@ -0,0 +1,49 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\Validator\ValidatorInterface; + +use function preg_match; +use function str_replace; + +/** + * Rfc4122\Validator validates strings as UUIDs of the RFC 4122 variant + * + * @psalm-immutable + */ +final class Validator implements ValidatorInterface +{ + private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-' + . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z'; + + /** + * @psalm-return non-empty-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function getPattern(): string + { + return self::VALID_PATTERN; + } + + public function validate(string $uuid): bool + { + $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid); + + return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php new file mode 100644 index 00000000..4c981658 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php @@ -0,0 +1,90 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Exception\InvalidBytesException; +use Ramsey\Uuid\Uuid; + +use function decbin; +use function str_pad; +use function strlen; +use function strpos; +use function substr; +use function unpack; + +use const STR_PAD_LEFT; + +/** + * Provides common functionality for handling the variant, as defined by RFC 4122 + * + * @psalm-immutable + */ +trait VariantTrait +{ + /** + * Returns the bytes that comprise the fields + */ + abstract public function getBytes(): string; + + /** + * Returns the variant identifier, according to RFC 4122, for the given bytes + * + * The following values may be returned: + * + * - `0` -- Reserved, NCS backward compatibility. + * - `2` -- The variant specified in RFC 4122. + * - `6` -- Reserved, Microsoft Corporation backward compatibility. + * - `7` -- Reserved for future definition. + * + * @link https://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant + * + * @return int The variant identifier, according to RFC 4122 + */ + public function getVariant(): int + { + if (strlen($this->getBytes()) !== 16) { + throw new InvalidBytesException('Invalid number of bytes'); + } + + /** @var array $parts */ + $parts = unpack('n*', $this->getBytes()); + + // $parts[5] is a 16-bit, unsigned integer containing the variant bits + // of the UUID. We convert this integer into a string containing a + // binary representation, padded to 16 characters. We analyze the first + // three characters (three most-significant bits) to determine the + // variant. + $binary = str_pad( + decbin((int) $parts[5]), + 16, + '0', + STR_PAD_LEFT + ); + + $msb = substr($binary, 0, 3); + + if ($msb === '111') { + $variant = Uuid::RESERVED_FUTURE; + } elseif ($msb === '110') { + $variant = Uuid::RESERVED_MICROSOFT; + } elseif (strpos($msb, '10') === 0) { + $variant = Uuid::RFC_4122; + } else { + $variant = Uuid::RESERVED_NCS; + } + + return $variant; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php new file mode 100644 index 00000000..cee55fbe --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php @@ -0,0 +1,57 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +/** + * Provides common functionality for handling the version, as defined by RFC 4122 + * + * @psalm-immutable + */ +trait VersionTrait +{ + /** + * Returns the version + */ + abstract public function getVersion(): ?int; + + /** + * Returns true if these fields represent a nil UUID + */ + abstract public function isNil(): bool; + + /** + * Returns true if the version matches one of those defined by RFC 4122 + * + * @return bool True if the UUID version is valid, false otherwise + */ + private function isCorrectVersion(): bool + { + if ($this->isNil()) { + return true; + } + + switch ($this->getVersion()) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + return true; + } + + return false; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Decimal.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Decimal.php new file mode 100644 index 00000000..10f93845 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Decimal.php @@ -0,0 +1,137 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Type; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use ValueError; + +use function is_numeric; +use function sprintf; + +/** + * A value object representing a decimal + * + * This class exists for type-safety purposes, to ensure that decimals + * returned from ramsey/uuid methods as strings are truly decimals and not some + * other kind of string. + * + * To support values as true decimals and not as floats or doubles, we store the + * decimals as strings. + * + * @psalm-immutable + */ +final class Decimal implements NumberInterface +{ + /** + * @var string + */ + private $value; + + /** + * @var bool + */ + private $isNegative = false; + + /** + * @param mixed $value The decimal value to store + */ + public function __construct($value) + { + $value = (string) $value; + + if (!is_numeric($value)) { + throw new InvalidArgumentException( + 'Value must be a signed decimal or a string containing only ' + . 'digits 0-9 and, optionally, a decimal point or sign (+ or -)' + ); + } + + // Remove the leading +-symbol. + if (strpos($value, '+') === 0) { + $value = substr($value, 1); + } + + // For cases like `-0` or `-0.0000`, convert the value to `0`. + if (abs((float) $value) === 0.0) { + $value = '0'; + } + + if (strpos($value, '-') === 0) { + $this->isNegative = true; + } + + $this->value = $value; + } + + public function isNegative(): bool + { + return $this->isNegative; + } + + public function toString(): string + { + return $this->value; + } + + public function __toString(): string + { + return $this->toString(); + } + + public function jsonSerialize(): string + { + return $this->toString(); + } + + public function serialize(): string + { + return $this->toString(); + } + + /** + * @return array{string: string} + */ + public function __serialize(): array + { + return ['string' => $this->toString()]; + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @psalm-suppress UnusedMethodCall + */ + public function unserialize($serialized): void + { + $this->__construct($serialized); + } + + /** + * @param array{string: string} $data + */ + public function __unserialize(array $data): void + { + // @codeCoverageIgnoreStart + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $this->unserialize($data['string']); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Hexadecimal.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Hexadecimal.php new file mode 100644 index 00000000..88adc2e7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Hexadecimal.php @@ -0,0 +1,116 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Type; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use ValueError; + +use function ctype_xdigit; +use function sprintf; +use function strpos; +use function strtolower; +use function substr; + +/** + * A value object representing a hexadecimal number + * + * This class exists for type-safety purposes, to ensure that hexadecimal numbers + * returned from ramsey/uuid methods as strings are truly hexadecimal and not some + * other kind of string. + * + * @psalm-immutable + */ +final class Hexadecimal implements TypeInterface +{ + /** + * @var string + */ + private $value; + + /** + * @param string $value The hexadecimal value to store + */ + public function __construct(string $value) + { + $value = strtolower($value); + + if (strpos($value, '0x') === 0) { + $value = substr($value, 2); + } + + if (!ctype_xdigit($value)) { + throw new InvalidArgumentException( + 'Value must be a hexadecimal number' + ); + } + + $this->value = $value; + } + + public function toString(): string + { + return $this->value; + } + + public function __toString(): string + { + return $this->toString(); + } + + public function jsonSerialize(): string + { + return $this->toString(); + } + + public function serialize(): string + { + return $this->toString(); + } + + /** + * @return array{string: string} + */ + public function __serialize(): array + { + return ['string' => $this->toString()]; + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @psalm-suppress UnusedMethodCall + */ + public function unserialize($serialized): void + { + $this->__construct($serialized); + } + + /** + * @param array{string: string} $data + */ + public function __unserialize(array $data): void + { + // @codeCoverageIgnoreStart + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $this->unserialize($data['string']); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Integer.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Integer.php new file mode 100644 index 00000000..7690f6cd --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Integer.php @@ -0,0 +1,153 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Type; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use ValueError; + +use function ctype_digit; +use function ltrim; +use function sprintf; +use function strpos; +use function substr; + +/** + * A value object representing an integer + * + * This class exists for type-safety purposes, to ensure that integers + * returned from ramsey/uuid methods as strings are truly integers and not some + * other kind of string. + * + * To support large integers beyond PHP_INT_MAX and PHP_INT_MIN on both 64-bit + * and 32-bit systems, we store the integers as strings. + * + * @psalm-immutable + */ +final class Integer implements NumberInterface +{ + /** + * @psalm-var numeric-string + */ + private $value; + + /** + * @var bool + */ + private $isNegative = false; + + /** + * @param mixed $value The integer value to store + */ + public function __construct($value) + { + $value = (string) $value; + $sign = '+'; + + // If the value contains a sign, remove it for ctype_digit() check. + if (strpos($value, '-') === 0 || strpos($value, '+') === 0) { + $sign = substr($value, 0, 1); + $value = substr($value, 1); + } + + if (!ctype_digit($value)) { + throw new InvalidArgumentException( + 'Value must be a signed integer or a string containing only ' + . 'digits 0-9 and, optionally, a sign (+ or -)' + ); + } + + // Trim any leading zeros. + $value = ltrim($value, '0'); + + // Set to zero if the string is empty after trimming zeros. + if ($value === '') { + $value = '0'; + } + + // Add the negative sign back to the value. + if ($sign === '-' && $value !== '0') { + $value = $sign . $value; + $this->isNegative = true; + } + + /** @psalm-var numeric-string $numericValue */ + $numericValue = $value; + + $this->value = $numericValue; + } + + public function isNegative(): bool + { + return $this->isNegative; + } + + /** + * @psalm-return numeric-string + */ + public function toString(): string + { + return $this->value; + } + + public function __toString(): string + { + return $this->toString(); + } + + public function jsonSerialize(): string + { + return $this->toString(); + } + + public function serialize(): string + { + return $this->toString(); + } + + /** + * @return array{string: string} + */ + public function __serialize(): array + { + return ['string' => $this->toString()]; + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @psalm-suppress UnusedMethodCall + */ + public function unserialize($serialized): void + { + $this->__construct($serialized); + } + + /** + * @param array{string: string} $data + */ + public function __unserialize(array $data): void + { + // @codeCoverageIgnoreStart + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $this->unserialize($data['string']); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/NumberInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/NumberInterface.php new file mode 100644 index 00000000..bf4ae9db --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/NumberInterface.php @@ -0,0 +1,28 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Type; + +/** + * NumberInterface ensures consistency in numeric values returned by ramsey/uuid + * + * @psalm-immutable + */ +interface NumberInterface extends TypeInterface +{ + /** + * Returns true if this number is less than zero + */ + public function isNegative(): bool; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Time.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Time.php new file mode 100644 index 00000000..dd1b8bc2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/Time.php @@ -0,0 +1,139 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Type; + +use Ramsey\Uuid\Exception\UnsupportedOperationException; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use ValueError; +use stdClass; + +use function json_decode; +use function json_encode; +use function sprintf; + +/** + * A value object representing a timestamp + * + * This class exists for type-safety purposes, to ensure that timestamps used + * by ramsey/uuid are truly timestamp integers and not some other kind of string + * or integer. + * + * @psalm-immutable + */ +final class Time implements TypeInterface +{ + /** + * @var IntegerObject + */ + private $seconds; + + /** + * @var IntegerObject + */ + private $microseconds; + + /** + * @param mixed $seconds + * @param mixed $microseconds + */ + public function __construct($seconds, $microseconds = 0) + { + $this->seconds = new IntegerObject($seconds); + $this->microseconds = new IntegerObject($microseconds); + } + + public function getSeconds(): IntegerObject + { + return $this->seconds; + } + + public function getMicroseconds(): IntegerObject + { + return $this->microseconds; + } + + public function toString(): string + { + return $this->seconds->toString() . '.' . $this->microseconds->toString(); + } + + public function __toString(): string + { + return $this->toString(); + } + + /** + * @return string[] + */ + public function jsonSerialize(): array + { + return [ + 'seconds' => $this->getSeconds()->toString(), + 'microseconds' => $this->getMicroseconds()->toString(), + ]; + } + + public function serialize(): string + { + return (string) json_encode($this); + } + + /** + * @return array{seconds: string, microseconds: string} + */ + public function __serialize(): array + { + return [ + 'seconds' => $this->getSeconds()->toString(), + 'microseconds' => $this->getMicroseconds()->toString(), + ]; + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @psalm-suppress UnusedMethodCall + */ + public function unserialize($serialized): void + { + /** @var stdClass $time */ + $time = json_decode($serialized); + + if (!isset($time->seconds) || !isset($time->microseconds)) { + throw new UnsupportedOperationException( + 'Attempted to unserialize an invalid value' + ); + } + + $this->__construct($time->seconds, $time->microseconds); + } + + /** + * @param array{seconds: string, microseconds: string} $data + */ + public function __unserialize(array $data): void + { + // @codeCoverageIgnoreStart + if (!isset($data['seconds']) || !isset($data['microseconds'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $this->__construct($data['seconds'], $data['microseconds']); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/TypeInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/TypeInterface.php new file mode 100644 index 00000000..da2d8b20 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Type/TypeInterface.php @@ -0,0 +1,30 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Type; + +use JsonSerializable; +use Serializable; + +/** + * TypeInterface ensures consistency in typed values returned by ramsey/uuid + * + * @psalm-immutable + */ +interface TypeInterface extends JsonSerializable, Serializable +{ + public function toString(): string; + + public function __toString(): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Uuid.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Uuid.php new file mode 100644 index 00000000..945480ba --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Uuid.php @@ -0,0 +1,664 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use DateTimeInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Fields\FieldsInterface; +use Ramsey\Uuid\Lazy\LazyUuidFromString; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use ValueError; + +use function assert; +use function bin2hex; +use function preg_match; +use function sprintf; +use function str_replace; +use function strcmp; +use function strlen; +use function strtolower; +use function substr; + +/** + * Uuid provides constants and static methods for working with and generating UUIDs + * + * @psalm-immutable + */ +class Uuid implements UuidInterface +{ + use DeprecatedUuidMethodsTrait; + + /** + * When this namespace is specified, the name string is a fully-qualified + * domain name + * + * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs + */ + public const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; + + /** + * When this namespace is specified, the name string is a URL + * + * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs + */ + public const NAMESPACE_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; + + /** + * When this namespace is specified, the name string is an ISO OID + * + * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs + */ + public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8'; + + /** + * When this namespace is specified, the name string is an X.500 DN in DER + * or a text output format + * + * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs + */ + public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8'; + + /** + * The nil UUID is a special form of UUID that is specified to have all 128 + * bits set to zero + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.7 RFC 4122, § 4.1.7: Nil UUID + */ + public const NIL = '00000000-0000-0000-0000-000000000000'; + + /** + * Variant: reserved, NCS backward compatibility + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant + */ + public const RESERVED_NCS = 0; + + /** + * Variant: the UUID layout specified in RFC 4122 + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant + */ + public const RFC_4122 = 2; + + /** + * Variant: reserved, Microsoft Corporation backward compatibility + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant + */ + public const RESERVED_MICROSOFT = 6; + + /** + * Variant: reserved for future definition + * + * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant + */ + public const RESERVED_FUTURE = 7; + + /** + * @deprecated Use {@see ValidatorInterface::getPattern()} instead. + */ + public const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$'; + + /** + * Version 1 (time-based) UUID + * + * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version + */ + public const UUID_TYPE_TIME = 1; + + /** + * Version 2 (DCE Security) UUID + * + * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version + */ + public const UUID_TYPE_DCE_SECURITY = 2; + + /** + * @deprecated Use {@see Uuid::UUID_TYPE_DCE_SECURITY} instead. + */ + public const UUID_TYPE_IDENTIFIER = 2; + + /** + * Version 3 (name-based and hashed with MD5) UUID + * + * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version + */ + public const UUID_TYPE_HASH_MD5 = 3; + + /** + * Version 4 (random) UUID + * + * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version + */ + public const UUID_TYPE_RANDOM = 4; + + /** + * Version 5 (name-based and hashed with SHA1) UUID + * + * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version + */ + public const UUID_TYPE_HASH_SHA1 = 5; + + /** + * Version 6 (ordered-time) UUID + * + * This is named `UUID_TYPE_PEABODY`, since the specification is still in + * draft form, and the primary author/editor's name is Brad Peabody. + * + * @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft + * @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs + */ + public const UUID_TYPE_PEABODY = 6; + + /** + * DCE Security principal domain + * + * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1 + */ + public const DCE_DOMAIN_PERSON = 0; + + /** + * DCE Security group domain + * + * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1 + */ + public const DCE_DOMAIN_GROUP = 1; + + /** + * DCE Security organization domain + * + * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1 + */ + public const DCE_DOMAIN_ORG = 2; + + /** + * DCE Security domain string names + * + * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1 + */ + public const DCE_DOMAIN_NAMES = [ + self::DCE_DOMAIN_PERSON => 'person', + self::DCE_DOMAIN_GROUP => 'group', + self::DCE_DOMAIN_ORG => 'org', + ]; + + /** + * @var UuidFactoryInterface|null + */ + private static $factory = null; + + /** + * @var bool flag to detect if the UUID factory was replaced internally, which disables all optimizations + * for the default/happy path internal scenarios + */ + private static $factoryReplaced = false; + + /** + * @var CodecInterface + */ + protected $codec; + + /** + * The fields that make up this UUID + * + * @var Rfc4122FieldsInterface + */ + protected $fields; + + /** + * @var NumberConverterInterface + */ + protected $numberConverter; + + /** + * @var TimeConverterInterface + */ + protected $timeConverter; + + /** + * Creates a universally unique identifier (UUID) from an array of fields + * + * Unless you're making advanced use of this library to generate identifiers + * that deviate from RFC 4122, you probably do not want to instantiate a + * UUID directly. Use the static methods, instead: + * + * ``` + * use Ramsey\Uuid\Uuid; + * + * $timeBasedUuid = Uuid::uuid1(); + * $namespaceMd5Uuid = Uuid::uuid3(Uuid::NAMESPACE_URL, 'http://php.net/'); + * $randomUuid = Uuid::uuid4(); + * $namespaceSha1Uuid = Uuid::uuid5(Uuid::NAMESPACE_URL, 'http://php.net/'); + * ``` + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + $this->fields = $fields; + $this->codec = $codec; + $this->numberConverter = $numberConverter; + $this->timeConverter = $timeConverter; + } + + /** + * @psalm-return non-empty-string + */ + public function __toString(): string + { + return $this->toString(); + } + + /** + * Converts the UUID to a string for JSON serialization + */ + public function jsonSerialize(): string + { + return $this->toString(); + } + + /** + * Converts the UUID to a string for PHP serialization + */ + public function serialize(): string + { + return $this->getFields()->getBytes(); + } + + /** + * @return array{bytes: string} + */ + public function __serialize(): array + { + return ['bytes' => $this->serialize()]; + } + + /** + * Re-constructs the object from its serialized form + * + * @param string $serialized The serialized PHP string to unserialize into + * a UuidInterface instance + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function unserialize($serialized): void + { + if (strlen($serialized) === 16) { + /** @var Uuid $uuid */ + $uuid = self::getFactory()->fromBytes($serialized); + } else { + /** @var Uuid $uuid */ + $uuid = self::getFactory()->fromString($serialized); + } + + $this->codec = $uuid->codec; + $this->numberConverter = $uuid->numberConverter; + $this->fields = $uuid->fields; + $this->timeConverter = $uuid->timeConverter; + } + + /** + * @param array{bytes: string} $data + */ + public function __unserialize(array $data): void + { + // @codeCoverageIgnoreStart + if (!isset($data['bytes'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + // @codeCoverageIgnoreEnd + + $this->unserialize($data['bytes']); + } + + public function compareTo(UuidInterface $other): int + { + $compare = strcmp($this->toString(), $other->toString()); + + if ($compare < 0) { + return -1; + } + + if ($compare > 0) { + return 1; + } + + return 0; + } + + public function equals(?object $other): bool + { + if (!$other instanceof UuidInterface) { + return false; + } + + return $this->compareTo($other) === 0; + } + + /** + * @psalm-return non-empty-string + */ + public function getBytes(): string + { + return $this->codec->encodeBinary($this); + } + + public function getFields(): FieldsInterface + { + return $this->fields; + } + + public function getHex(): Hexadecimal + { + return new Hexadecimal(str_replace('-', '', $this->toString())); + } + + public function getInteger(): IntegerObject + { + return new IntegerObject($this->numberConverter->fromHex($this->getHex()->toString())); + } + + /** + * @psalm-return non-empty-string + */ + public function toString(): string + { + return $this->codec->encode($this); + } + + /** + * Returns the factory used to create UUIDs + */ + public static function getFactory(): UuidFactoryInterface + { + if (self::$factory === null) { + self::$factory = new UuidFactory(); + } + + return self::$factory; + } + + /** + * Sets the factory used to create UUIDs + * + * @param UuidFactoryInterface $factory A factory that will be used by this + * class to create UUIDs + */ + public static function setFactory(UuidFactoryInterface $factory): void + { + // Note: non-strict equality is intentional here. If the factory is configured differently, every assumption + // around purity is broken, and we have to internally decide everything differently. + // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator + self::$factoryReplaced = ($factory != new UuidFactory()); + + self::$factory = $factory; + } + + /** + * Creates a UUID from a byte string + * + * @param string $bytes A binary string + * + * @return UuidInterface A UuidInterface instance created from a binary + * string representation + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + * + * @psalm-suppress ImpureStaticProperty we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. + */ + public static function fromBytes(string $bytes): UuidInterface + { + if (! self::$factoryReplaced && strlen($bytes) === 16) { + $base16Uuid = bin2hex($bytes); + + // Note: we are calling `fromString` internally because we don't know if the given `$bytes` is a valid UUID + return self::fromString( + substr($base16Uuid, 0, 8) + . '-' + . substr($base16Uuid, 8, 4) + . '-' + . substr($base16Uuid, 12, 4) + . '-' + . substr($base16Uuid, 16, 4) + . '-' + . substr($base16Uuid, 20, 12) + ); + } + + return self::getFactory()->fromBytes($bytes); + } + + /** + * Creates a UUID from the string standard representation + * + * @param string $uuid A hexadecimal string + * + * @return UuidInterface A UuidInterface instance created from a hexadecimal + * string representation + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + * + * @psalm-suppress ImpureStaticProperty we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. + */ + public static function fromString(string $uuid): UuidInterface + { + if (! self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) { + assert($uuid !== ''); + + return new LazyUuidFromString(strtolower($uuid)); + } + + return self::getFactory()->fromString($uuid); + } + + /** + * Creates a UUID from a DateTimeInterface instance + * + * @param DateTimeInterface $dateTime The date and time + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return UuidInterface A UuidInterface instance that represents a + * version 1 UUID created from a DateTimeInterface instance + */ + public static function fromDateTime( + DateTimeInterface $dateTime, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): UuidInterface { + return self::getFactory()->fromDateTime($dateTime, $node, $clockSeq); + } + + /** + * Creates a UUID from a 128-bit integer string + * + * @param string $integer String representation of 128-bit integer + * + * @return UuidInterface A UuidInterface instance created from the string + * representation of a 128-bit integer + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + */ + public static function fromInteger(string $integer): UuidInterface + { + return self::getFactory()->fromInteger($integer); + } + + /** + * Returns true if the provided string is a valid UUID + * + * @param string $uuid A string to validate as a UUID + * + * @return bool True if the string is a valid UUID, false otherwise + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + */ + public static function isValid(string $uuid): bool + { + return self::getFactory()->getValidator()->validate($uuid); + } + + /** + * Returns a version 1 (time-based) UUID from a host ID, sequence number, + * and the current time + * + * @param Hexadecimal|int|string|null $node A 48-bit number representing the + * hardware address; this number may be represented as an integer or a + * hexadecimal string + * @param int $clockSeq A 14-bit number used to help avoid duplicates that + * could arise when the clock is set backwards in time or if the node ID + * changes + * + * @return UuidInterface A UuidInterface instance that represents a + * version 1 UUID + */ + public static function uuid1($node = null, ?int $clockSeq = null): UuidInterface + { + return self::getFactory()->uuid1($node, $clockSeq); + } + + /** + * Returns a version 2 (DCE Security) UUID from a local domain, local + * identifier, host ID, clock sequence, and the current time + * + * @param int $localDomain The local domain to use when generating bytes, + * according to DCE Security + * @param IntegerObject|null $localIdentifier The local identifier for the + * given domain; this may be a UID or GID on POSIX systems, if the local + * domain is person or group, or it may be a site-defined identifier + * if the local domain is org + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes (in a version 2 UUID, the lower 8 bits of this number + * are replaced with the domain). + * + * @return UuidInterface A UuidInterface instance that represents a + * version 2 UUID + */ + public static function uuid2( + int $localDomain, + ?IntegerObject $localIdentifier = null, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): UuidInterface { + return self::getFactory()->uuid2($localDomain, $localIdentifier, $node, $clockSeq); + } + + /** + * Returns a version 3 (name-based) UUID based on the MD5 hash of a + * namespace ID and a name + * + * @param string|UuidInterface $ns The namespace (must be a valid UUID) + * @param string $name The name to use for creating a UUID + * + * @return UuidInterface A UuidInterface instance that represents a + * version 3 UUID + * + * @psalm-suppress ImpureMethodCall we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + */ + public static function uuid3($ns, string $name): UuidInterface + { + return self::getFactory()->uuid3($ns, $name); + } + + /** + * Returns a version 4 (random) UUID + * + * @return UuidInterface A UuidInterface instance that represents a + * version 4 UUID + */ + public static function uuid4(): UuidInterface + { + return self::getFactory()->uuid4(); + } + + /** + * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a + * namespace ID and a name + * + * @param string|UuidInterface $ns The namespace (must be a valid UUID) + * @param string $name The name to use for creating a UUID + * + * @return UuidInterface A UuidInterface instance that represents a + * version 5 UUID + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + * + * @psalm-suppress ImpureMethodCall we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. + */ + public static function uuid5($ns, string $name): UuidInterface + { + return self::getFactory()->uuid5($ns, $name); + } + + /** + * Returns a version 6 (ordered-time) UUID from a host ID, sequence number, + * and the current time + * + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int $clockSeq A 14-bit number used to help avoid duplicates that + * could arise when the clock is set backwards in time or if the node ID + * changes + * + * @return UuidInterface A UuidInterface instance that represents a + * version 6 UUID + */ + public static function uuid6( + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): UuidInterface { + return self::getFactory()->uuid6($node, $clockSeq); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactory.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactory.php new file mode 100644 index 00000000..6f2cea06 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactory.php @@ -0,0 +1,493 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use DateTimeInterface; +use Ramsey\Uuid\Builder\UuidBuilderInterface; +use Ramsey\Uuid\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface; +use Ramsey\Uuid\Generator\DefaultTimeGenerator; +use Ramsey\Uuid\Generator\NameGeneratorInterface; +use Ramsey\Uuid\Generator\RandomGeneratorInterface; +use Ramsey\Uuid\Generator\TimeGeneratorInterface; +use Ramsey\Uuid\Lazy\LazyUuidFromString; +use Ramsey\Uuid\Provider\NodeProviderInterface; +use Ramsey\Uuid\Provider\Time\FixedTimeProvider; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Type\Time; +use Ramsey\Uuid\Validator\ValidatorInterface; + +use function bin2hex; +use function hex2bin; +use function pack; +use function str_pad; +use function strtolower; +use function substr; +use function substr_replace; +use function unpack; + +use const STR_PAD_LEFT; + +class UuidFactory implements UuidFactoryInterface +{ + /** + * @var CodecInterface + */ + private $codec; + + /** + * @var DceSecurityGeneratorInterface + */ + private $dceSecurityGenerator; + + /** + * @var NameGeneratorInterface + */ + private $nameGenerator; + + /** + * @var NodeProviderInterface + */ + private $nodeProvider; + + /** + * @var NumberConverterInterface + */ + private $numberConverter; + + /** + * @var RandomGeneratorInterface + */ + private $randomGenerator; + + /** + * @var TimeConverterInterface + */ + private $timeConverter; + + /** + * @var TimeGeneratorInterface + */ + private $timeGenerator; + + /** + * @var UuidBuilderInterface + */ + private $uuidBuilder; + + /** + * @var ValidatorInterface + */ + private $validator; + + /** @var bool whether the feature set was provided from outside, or we can operate under "default" assumptions */ + private $isDefaultFeatureSet; + + /** + * @param FeatureSet $features A set of available features in the current environment + */ + public function __construct(?FeatureSet $features = null) + { + $this->isDefaultFeatureSet = $features === null; + + $features = $features ?: new FeatureSet(); + + $this->codec = $features->getCodec(); + $this->dceSecurityGenerator = $features->getDceSecurityGenerator(); + $this->nameGenerator = $features->getNameGenerator(); + $this->nodeProvider = $features->getNodeProvider(); + $this->numberConverter = $features->getNumberConverter(); + $this->randomGenerator = $features->getRandomGenerator(); + $this->timeConverter = $features->getTimeConverter(); + $this->timeGenerator = $features->getTimeGenerator(); + $this->uuidBuilder = $features->getBuilder(); + $this->validator = $features->getValidator(); + } + + /** + * Returns the codec used by this factory + */ + public function getCodec(): CodecInterface + { + return $this->codec; + } + + /** + * Sets the codec to use for this factory + * + * @param CodecInterface $codec A UUID encoder-decoder + */ + public function setCodec(CodecInterface $codec): void + { + $this->isDefaultFeatureSet = false; + + $this->codec = $codec; + } + + /** + * Returns the name generator used by this factory + */ + public function getNameGenerator(): NameGeneratorInterface + { + return $this->nameGenerator; + } + + /** + * Sets the name generator to use for this factory + * + * @param NameGeneratorInterface $nameGenerator A generator to generate + * binary data, based on a namespace and name + */ + public function setNameGenerator(NameGeneratorInterface $nameGenerator): void + { + $this->isDefaultFeatureSet = false; + + $this->nameGenerator = $nameGenerator; + } + + /** + * Returns the node provider used by this factory + */ + public function getNodeProvider(): NodeProviderInterface + { + return $this->nodeProvider; + } + + /** + * Returns the random generator used by this factory + */ + public function getRandomGenerator(): RandomGeneratorInterface + { + return $this->randomGenerator; + } + + /** + * Returns the time generator used by this factory + */ + public function getTimeGenerator(): TimeGeneratorInterface + { + return $this->timeGenerator; + } + + /** + * Sets the time generator to use for this factory + * + * @param TimeGeneratorInterface $generator A generator to generate binary + * data, based on the time + */ + public function setTimeGenerator(TimeGeneratorInterface $generator): void + { + $this->isDefaultFeatureSet = false; + + $this->timeGenerator = $generator; + } + + /** + * Returns the DCE Security generator used by this factory + */ + public function getDceSecurityGenerator(): DceSecurityGeneratorInterface + { + return $this->dceSecurityGenerator; + } + + /** + * Sets the DCE Security generator to use for this factory + * + * @param DceSecurityGeneratorInterface $generator A generator to generate + * binary data, based on a local domain and local identifier + */ + public function setDceSecurityGenerator(DceSecurityGeneratorInterface $generator): void + { + $this->isDefaultFeatureSet = false; + + $this->dceSecurityGenerator = $generator; + } + + /** + * Returns the number converter used by this factory + */ + public function getNumberConverter(): NumberConverterInterface + { + return $this->numberConverter; + } + + /** + * Sets the random generator to use for this factory + * + * @param RandomGeneratorInterface $generator A generator to generate binary + * data, based on some random input + */ + public function setRandomGenerator(RandomGeneratorInterface $generator): void + { + $this->isDefaultFeatureSet = false; + + $this->randomGenerator = $generator; + } + + /** + * Sets the number converter to use for this factory + * + * @param NumberConverterInterface $converter A converter to use for working + * with large integers (i.e. integers greater than PHP_INT_MAX) + */ + public function setNumberConverter(NumberConverterInterface $converter): void + { + $this->isDefaultFeatureSet = false; + + $this->numberConverter = $converter; + } + + /** + * Returns the UUID builder used by this factory + */ + public function getUuidBuilder(): UuidBuilderInterface + { + return $this->uuidBuilder; + } + + /** + * Sets the UUID builder to use for this factory + * + * @param UuidBuilderInterface $builder A builder for constructing instances + * of UuidInterface + */ + public function setUuidBuilder(UuidBuilderInterface $builder): void + { + $this->isDefaultFeatureSet = false; + + $this->uuidBuilder = $builder; + } + + /** + * @psalm-mutation-free + */ + public function getValidator(): ValidatorInterface + { + return $this->validator; + } + + /** + * Sets the validator to use for this factory + * + * @param ValidatorInterface $validator A validator to use for validating + * whether a string is a valid UUID + */ + public function setValidator(ValidatorInterface $validator): void + { + $this->isDefaultFeatureSet = false; + + $this->validator = $validator; + } + + /** + * @psalm-pure + */ + public function fromBytes(string $bytes): UuidInterface + { + return $this->codec->decodeBytes($bytes); + } + + /** + * @psalm-pure + */ + public function fromString(string $uuid): UuidInterface + { + $uuid = strtolower($uuid); + + return $this->codec->decode($uuid); + } + + /** + * @psalm-pure + */ + public function fromInteger(string $integer): UuidInterface + { + $hex = $this->numberConverter->toHex($integer); + $hex = str_pad($hex, 32, '0', STR_PAD_LEFT); + + return $this->fromString($hex); + } + + public function fromDateTime( + DateTimeInterface $dateTime, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): UuidInterface { + $timeProvider = new FixedTimeProvider( + new Time($dateTime->format('U'), $dateTime->format('u')) + ); + + $timeGenerator = new DefaultTimeGenerator( + $this->nodeProvider, + $this->timeConverter, + $timeProvider + ); + + $nodeHex = $node ? $node->toString() : null; + + $bytes = $timeGenerator->generate($nodeHex, $clockSeq); + + return $this->uuidFromBytesAndVersion($bytes, 1); + } + + /** + * @inheritDoc + */ + public function uuid1($node = null, ?int $clockSeq = null): UuidInterface + { + $bytes = $this->timeGenerator->generate($node, $clockSeq); + + return $this->uuidFromBytesAndVersion($bytes, 1); + } + + public function uuid2( + int $localDomain, + ?IntegerObject $localIdentifier = null, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): UuidInterface { + $bytes = $this->dceSecurityGenerator->generate( + $localDomain, + $localIdentifier, + $node, + $clockSeq + ); + + return $this->uuidFromBytesAndVersion($bytes, 2); + } + + /** + * @inheritDoc + * @psalm-pure + */ + public function uuid3($ns, string $name): UuidInterface + { + return $this->uuidFromNsAndName($ns, $name, 3, 'md5'); + } + + public function uuid4(): UuidInterface + { + $bytes = $this->randomGenerator->generate(16); + + return $this->uuidFromBytesAndVersion($bytes, 4); + } + + /** + * @inheritDoc + * @psalm-pure + */ + public function uuid5($ns, string $name): UuidInterface + { + return $this->uuidFromNsAndName($ns, $name, 5, 'sha1'); + } + + public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface + { + $nodeHex = $node ? $node->toString() : null; + $bytes = $this->timeGenerator->generate($nodeHex, $clockSeq); + + // Rearrange the bytes, according to the UUID version 6 specification. + $v6 = $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5] + . $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3]; + $v6 = bin2hex($v6); + + // Drop the first four bits, while adding an empty four bits for the + // version field. This allows us to reconstruct the correct time from + // the bytes of this UUID. + $v6Bytes = hex2bin(substr($v6, 1, 12) . '0' . substr($v6, -3)); + $v6Bytes .= substr($bytes, 8); + + return $this->uuidFromBytesAndVersion($v6Bytes, 6); + } + + /** + * Returns a Uuid created from the provided byte string + * + * Uses the configured builder and codec and the provided byte string to + * construct a Uuid object. + * + * @param string $bytes The byte string from which to construct a UUID + * + * @return UuidInterface An instance of UuidInterface, created from the + * provided bytes + * + * @psalm-pure + */ + public function uuid(string $bytes): UuidInterface + { + return $this->uuidBuilder->build($this->codec, $bytes); + } + + /** + * Returns a version 3 or 5 namespaced Uuid + * + * @param string|UuidInterface $ns The namespace (must be a valid UUID) + * @param string $name The name to hash together with the namespace + * @param int $version The version of UUID to create (3 or 5) + * @param string $hashAlgorithm The hashing algorithm to use when hashing + * together the namespace and name + * + * @return UuidInterface An instance of UuidInterface, created by hashing + * together the provided namespace and name + * + * @psalm-pure + */ + private function uuidFromNsAndName($ns, string $name, int $version, string $hashAlgorithm): UuidInterface + { + if (!($ns instanceof UuidInterface)) { + $ns = $this->fromString($ns); + } + + $bytes = $this->nameGenerator->generate($ns, $name, $hashAlgorithm); + + return $this->uuidFromBytesAndVersion(substr($bytes, 0, 16), $version); + } + + /** + * Returns an RFC 4122 variant Uuid, created from the provided bytes and version + * + * @param string $bytes The byte string to convert to a UUID + * @param int $version The RFC 4122 version to apply to the UUID + * + * @return UuidInterface An instance of UuidInterface, created from the + * byte string and version + * + * @psalm-pure + */ + private function uuidFromBytesAndVersion(string $bytes, int $version): UuidInterface + { + /** @var array $unpackedTime */ + $unpackedTime = unpack('n*', substr($bytes, 6, 2)); + $timeHi = (int) $unpackedTime[1]; + $timeHiAndVersion = pack('n*', BinaryUtils::applyVersion($timeHi, $version)); + + /** @var array $unpackedClockSeq */ + $unpackedClockSeq = unpack('n*', substr($bytes, 8, 2)); + $clockSeqHi = (int) $unpackedClockSeq[1]; + $clockSeqHiAndReserved = pack('n*', BinaryUtils::applyVariant($clockSeqHi)); + + $bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2); + $bytes = substr_replace($bytes, $clockSeqHiAndReserved, 8, 2); + + if ($this->isDefaultFeatureSet) { + return LazyUuidFromString::fromBytes($bytes); + } + + return $this->uuid($bytes); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactoryInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactoryInterface.php new file mode 100644 index 00000000..468cc637 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidFactoryInterface.php @@ -0,0 +1,182 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use DateTimeInterface; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Ramsey\Uuid\Validator\ValidatorInterface; + +/** + * UuidFactoryInterface defines common functionality all `UuidFactory` instances + * must implement + */ +interface UuidFactoryInterface +{ + /** + * Returns the validator to use for the factory + * + * @psalm-mutation-free + */ + public function getValidator(): ValidatorInterface; + + /** + * Returns a version 1 (time-based) UUID from a host ID, sequence number, + * and the current time + * + * @param Hexadecimal|int|string|null $node A 48-bit number representing the + * hardware address; this number may be represented as an integer or a + * hexadecimal string + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return UuidInterface A UuidInterface instance that represents a + * version 1 UUID + */ + public function uuid1($node = null, ?int $clockSeq = null): UuidInterface; + + /** + * Returns a version 2 (DCE Security) UUID from a local domain, local + * identifier, host ID, clock sequence, and the current time + * + * @param int $localDomain The local domain to use when generating bytes, + * according to DCE Security + * @param IntegerObject|null $localIdentifier The local identifier for the + * given domain; this may be a UID or GID on POSIX systems, if the local + * domain is person or group, or it may be a site-defined identifier + * if the local domain is org + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return UuidInterface A UuidInterface instance that represents a + * version 2 UUID + */ + public function uuid2( + int $localDomain, + ?IntegerObject $localIdentifier = null, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): UuidInterface; + + /** + * Returns a version 3 (name-based) UUID based on the MD5 hash of a + * namespace ID and a name + * + * @param string|UuidInterface $ns The namespace (must be a valid UUID) + * @param string $name The name to use for creating a UUID + * + * @return UuidInterface A UuidInterface instance that represents a + * version 3 UUID + * + * @psalm-pure + */ + public function uuid3($ns, string $name): UuidInterface; + + /** + * Returns a version 4 (random) UUID + * + * @return UuidInterface A UuidInterface instance that represents a + * version 4 UUID + */ + public function uuid4(): UuidInterface; + + /** + * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a + * namespace ID and a name + * + * @param string|UuidInterface $ns The namespace (must be a valid UUID) + * @param string $name The name to use for creating a UUID + * + * @return UuidInterface A UuidInterface instance that represents a + * version 5 UUID + * + * @psalm-pure + */ + public function uuid5($ns, string $name): UuidInterface; + + /** + * Returns a version 6 (ordered-time) UUID from a host ID, sequence number, + * and the current time + * + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return UuidInterface A UuidInterface instance that represents a + * version 6 UUID + */ + public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface; + + /** + * Creates a UUID from a byte string + * + * @param string $bytes A binary string + * + * @return UuidInterface A UuidInterface instance created from a binary + * string representation + * + * @psalm-pure + */ + public function fromBytes(string $bytes): UuidInterface; + + /** + * Creates a UUID from the string standard representation + * + * @param string $uuid A hexadecimal string + * + * @return UuidInterface A UuidInterface instance created from a hexadecimal + * string representation + * + * @psalm-pure + */ + public function fromString(string $uuid): UuidInterface; + + /** + * Creates a UUID from a 128-bit integer string + * + * @param string $integer String representation of 128-bit integer + * + * @return UuidInterface A UuidInterface instance created from the string + * representation of a 128-bit integer + * + * @psalm-pure + */ + public function fromInteger(string $integer): UuidInterface; + + /** + * Creates a UUID from a DateTimeInterface instance + * + * @param DateTimeInterface $dateTime The date and time + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return UuidInterface A UuidInterface instance that represents a + * version 1 UUID created from a DateTimeInterface instance + */ + public function fromDateTime( + DateTimeInterface $dateTime, + ?Hexadecimal $node = null, + ?int $clockSeq = null + ): UuidInterface; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidInterface.php new file mode 100644 index 00000000..f22eb0f9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/UuidInterface.php @@ -0,0 +1,99 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use JsonSerializable; +use Ramsey\Uuid\Fields\FieldsInterface; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; +use Serializable; + +/** + * A UUID is a universally unique identifier adhering to an agreed-upon + * representation format and standard for generation + * + * @psalm-immutable + */ +interface UuidInterface extends + DeprecatedUuidInterface, + JsonSerializable, + Serializable +{ + /** + * Returns -1, 0, or 1 if the UUID is less than, equal to, or greater than + * the other UUID + * + * The first of two UUIDs is greater than the second if the most + * significant field in which the UUIDs differ is greater for the first + * UUID. + * + * * Q. What's the value of being able to sort UUIDs? + * * A. Use them as keys in a B-Tree or similar mapping. + * + * @param UuidInterface $other The UUID to compare + * + * @return int -1, 0, or 1 if the UUID is less than, equal to, or greater than $other + */ + public function compareTo(UuidInterface $other): int; + + /** + * Returns true if the UUID is equal to the provided object + * + * The result is true if and only if the argument is not null, is a UUID + * object, has the same variant, and contains the same value, bit for bit, + * as the UUID. + * + * @param object|null $other An object to test for equality with this UUID + * + * @return bool True if the other object is equal to this UUID + */ + public function equals(?object $other): bool; + + /** + * Returns the binary string representation of the UUID + * + * @psalm-return non-empty-string + */ + public function getBytes(): string; + + /** + * Returns the fields that comprise this UUID + */ + public function getFields(): FieldsInterface; + + /** + * Returns the hexadecimal representation of the UUID + */ + public function getHex(): Hexadecimal; + + /** + * Returns the integer representation of the UUID + */ + public function getInteger(): IntegerObject; + + /** + * Returns the string standard representation of the UUID + * + * @psalm-return non-empty-string + */ + public function toString(): string; + + /** + * Casts the UUID to the string standard representation + * + * @psalm-return non-empty-string + */ + public function __toString(): string; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/GenericValidator.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/GenericValidator.php new file mode 100644 index 00000000..fd609551 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/GenericValidator.php @@ -0,0 +1,50 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Validator; + +use Ramsey\Uuid\Uuid; + +use function preg_match; +use function str_replace; + +/** + * GenericValidator validates strings as UUIDs of any variant + * + * @psalm-immutable + */ +final class GenericValidator implements ValidatorInterface +{ + /** + * Regular expression pattern for matching a UUID of any variant. + */ + private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\z'; + + /** + * @psalm-return non-empty-string + * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty + * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty + */ + public function getPattern(): string + { + return self::VALID_PATTERN; + } + + public function validate(string $uuid): bool + { + $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid); + + return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php new file mode 100644 index 00000000..3d4bd6f2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php @@ -0,0 +1,41 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Validator; + +/** + * A validator validates a string as a proper UUID + * + * @psalm-immutable + */ +interface ValidatorInterface +{ + /** + * Returns the regular expression pattern used by this validator + * + * @return string The regular expression pattern this validator uses + * + * @psalm-return non-empty-string + */ + public function getPattern(): string; + + /** + * Returns true if the provided string represents a UUID + * + * @param string $uuid The string to validate as a UUID + * + * @return bool True if the string is a valid UUID, false otherwise + */ + public function validate(string $uuid): bool; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/functions.php b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/functions.php new file mode 100644 index 00000000..f5df1488 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/ramsey/uuid/src/functions.php @@ -0,0 +1,123 @@ + + * @license http://opensource.org/licenses/MIT MIT + * phpcs:disable Squiz.Functions.GlobalFunction + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid; + +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Type\Integer as IntegerObject; + +/** + * Returns a version 1 (time-based) UUID from a host ID, sequence number, + * and the current time + * + * @param Hexadecimal|int|string|null $node A 48-bit number representing the + * hardware address; this number may be represented as an integer or a + * hexadecimal string + * @param int $clockSeq A 14-bit number used to help avoid duplicates that + * could arise when the clock is set backwards in time or if the node ID + * changes + * + * @return non-empty-string Version 1 UUID as a string + */ +function v1($node = null, ?int $clockSeq = null): string +{ + return Uuid::uuid1($node, $clockSeq)->toString(); +} + +/** + * Returns a version 2 (DCE Security) UUID from a local domain, local + * identifier, host ID, clock sequence, and the current time + * + * @param int $localDomain The local domain to use when generating bytes, + * according to DCE Security + * @param IntegerObject|null $localIdentifier The local identifier for the + * given domain; this may be a UID or GID on POSIX systems, if the local + * domain is person or group, or it may be a site-defined identifier + * if the local domain is org + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates + * that could arise when the clock is set backwards in time or if the + * node ID changes + * + * @return non-empty-string Version 2 UUID as a string + */ +function v2( + int $localDomain, + ?IntegerObject $localIdentifier = null, + ?Hexadecimal $node = null, + ?int $clockSeq = null +): string { + return Uuid::uuid2($localDomain, $localIdentifier, $node, $clockSeq)->toString(); +} + +/** + * Returns a version 3 (name-based) UUID based on the MD5 hash of a + * namespace ID and a name + * + * @param string|UuidInterface $ns The namespace (must be a valid UUID) + * + * @return non-empty-string Version 3 UUID as a string + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + */ +function v3($ns, string $name): string +{ + return Uuid::uuid3($ns, $name)->toString(); +} + +/** + * Returns a version 4 (random) UUID + * + * @return non-empty-string Version 4 UUID as a string + */ +function v4(): string +{ + return Uuid::uuid4()->toString(); +} + +/** + * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a + * namespace ID and a name + * + * @param string|UuidInterface $ns The namespace (must be a valid UUID) + * + * @return non-empty-string Version 5 UUID as a string + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + */ +function v5($ns, string $name): string +{ + return Uuid::uuid5($ns, $name)->toString(); +} + +/** + * Returns a version 6 (ordered-time) UUID from a host ID, sequence number, + * and the current time + * + * @param Hexadecimal|null $node A 48-bit number representing the hardware + * address + * @param int $clockSeq A 14-bit number used to help avoid duplicates that + * could arise when the clock is set backwards in time or if the node ID + * changes + * + * @return non-empty-string Version 6 UUID as a string + */ +function v6(?Hexadecimal $node = null, ?int $clockSeq = null): string +{ + return Uuid::uuid6($node, $clockSeq)->toString(); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/.github/FUNDING.yml b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/.github/FUNDING.yml new file mode 100644 index 00000000..726574c1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: Spomky +patreon: FlorentMorselli diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/LICENSE b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/LICENSE new file mode 100644 index 00000000..506ff485 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014-2018 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/composer.json b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/composer.json new file mode 100644 index 00000000..1f3941b9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/composer.json @@ -0,0 +1,35 @@ +{ + "name": "spomky-labs/base64url", + "description": "Base 64 URL Safe Encoding/Decoding PHP Library", + "type": "library", + "license": "MIT", + "keywords": ["Base64", "URL", "Safe", "RFC4648"], + "homepage": "https://github.com/Spomky-Labs/base64url", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky-Labs/base64url/contributors" + } + ], + "autoload": { + "psr-4": { + "Base64Url\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Base64Url\\Test\\": "tests/" + } + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.11|^0.12", + "phpstan/phpstan-beberlei-assert": "^0.11|^0.12", + "phpstan/phpstan-deprecation-rules": "^0.11|^0.12", + "phpstan/phpstan-phpunit": "^0.11|^0.12", + "phpstan/phpstan-strict-rules": "^0.11|^0.12" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/src/Base64Url.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/src/Base64Url.php new file mode 100644 index 00000000..260215ae --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/base64url/src/Base64Url.php @@ -0,0 +1,56 @@ +=7.3", + "brick/math": "^0.8.15|^0.9.0", + "ext-mbstring": "*" + }, + "require-dev": { + "ext-json": "*", + "ekino/phpstan-banned-code": "^1.0", + "infection/infection": "^0.18|^0.25", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-beberlei-assert": "^1.0", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.12", + "roave/security-advisories": "dev-latest", + "symplify/easy-coding-standard": "^10.0" + }, + "config": { + "sort-packages": true + }, + "suggest": { + "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance", + "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/AbstractCBORObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/AbstractCBORObject.php new file mode 100644 index 00000000..a14d2626 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/AbstractCBORObject.php @@ -0,0 +1,50 @@ +majorType = $majorType; + $this->additionalInformation = $additionalInformation; + } + + public function __toString(): string + { + return chr($this->majorType << 5 | $this->additionalInformation); + } + + public function getMajorType(): int + { + return $this->majorType; + } + + public function getAdditionalInformation(): int + { + return $this->additionalInformation; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringObject.php new file mode 100644 index 00000000..450f7ee2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringObject.php @@ -0,0 +1,76 @@ +length = $length; + $this->value = $data; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->length !== null) { + $result .= $this->length; + } + + return $result . $this->value; + } + + public static function create(string $data): self + { + return new self($data); + } + + public function getValue(): string + { + return $this->value; + } + + public function getLength(): int + { + return mb_strlen($this->value, '8bit'); + } + + public function normalize(): string + { + return $this->value; + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false): string + { + return $this->value; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringWithChunkObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringWithChunkObject.php new file mode 100644 index 00000000..d173e2f7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ByteStringWithChunkObject.php @@ -0,0 +1,21 @@ +tagManager = $tagManager ?? $this->generateTagManager(); + $this->otherObjectManager = $otherTypeManager ?? $this->generateOtherObjectManager(); + } + + public static function create( + ?TagManagerInterface $tagManager = null, + ?OtherObjectManagerInterface $otherObjectManager = null + ): self { + return new self($tagManager, $otherObjectManager); + } + + public function withTagManager(TagManagerInterface $tagManager): self + { + $this->tagManager = $tagManager; + + return $this; + } + + public function withOtherObjectManager(OtherObjectManagerInterface $otherObjectManager): self + { + $this->otherObjectManager = $otherObjectManager; + + return $this; + } + + public function decode(Stream $stream): CBORObject + { + return $this->process($stream, false); + } + + private function process(Stream $stream, bool $breakable): CBORObject + { + $ib = ord($stream->read(1)); + $mt = $ib >> 5; + $ai = $ib & 0b00011111; + $val = null; + switch ($ai) { + case CBORObject::LENGTH_1_BYTE: //24 + case CBORObject::LENGTH_2_BYTES: //25 + case CBORObject::LENGTH_4_BYTES: //26 + case CBORObject::LENGTH_8_BYTES: //27 + $val = $stream->read(2 ** ($ai & 0b00000111)); + break; + case CBORObject::FUTURE_USE_1: //28 + case CBORObject::FUTURE_USE_2: //29 + case CBORObject::FUTURE_USE_3: //30 + throw new InvalidArgumentException(sprintf( + 'Cannot parse the data. Found invalid Additional Information "%s" (%d).', + str_pad(decbin($ai), 8, '0', STR_PAD_LEFT), + $ai + )); + case CBORObject::LENGTH_INDEFINITE: //31 + return $this->processInfinite($stream, $mt, $breakable); + } + + return $this->processFinite($stream, $mt, $ai, $val); + } + + private function processFinite(Stream $stream, int $mt, int $ai, ?string $val): CBORObject + { + switch ($mt) { + case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER: //0 + return UnsignedIntegerObject::createObjectForValue($ai, $val); + case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER: //1 + return NegativeIntegerObject::createObjectForValue($ai, $val); + case CBORObject::MAJOR_TYPE_BYTE_STRING: //2 + $length = $val === null ? $ai : Utils::binToInt($val); + + return ByteStringObject::create($stream->read($length)); + case CBORObject::MAJOR_TYPE_TEXT_STRING: //3 + $length = $val === null ? $ai : Utils::binToInt($val); + + return TextStringObject::create($stream->read($length)); + case CBORObject::MAJOR_TYPE_LIST: //4 + $object = ListObject::create(); + $nbItems = $val === null ? $ai : Utils::binToInt($val); + for ($i = 0; $i < $nbItems; ++$i) { + $object->add($this->process($stream, false)); + } + + return $object; + case CBORObject::MAJOR_TYPE_MAP: //5 + $object = MapObject::create(); + $nbItems = $val === null ? $ai : Utils::binToInt($val); + for ($i = 0; $i < $nbItems; ++$i) { + $object->add($this->process($stream, false), $this->process($stream, false)); + } + + return $object; + case CBORObject::MAJOR_TYPE_TAG: //6 + return $this->tagManager->createObjectForValue($ai, $val, $this->process($stream, false)); + case CBORObject::MAJOR_TYPE_OTHER_TYPE: //7 + return $this->otherObjectManager->createObjectForValue($ai, $val); + default: + throw new RuntimeException(sprintf( + 'Unsupported major type "%s" (%d).', + str_pad(decbin($mt), 5, '0', STR_PAD_LEFT), + $mt + )); // Should never append + } + } + + private function processInfinite(Stream $stream, int $mt, bool $breakable): CBORObject + { + switch ($mt) { + case CBORObject::MAJOR_TYPE_BYTE_STRING: //2 + $object = IndefiniteLengthByteStringObject::create(); + while (! ($it = $this->process($stream, true)) instanceof BreakObject) { + if (! $it instanceof ByteStringObject) { + throw new RuntimeException( + 'Unable to parse the data. Infinite Byte String object can only get Byte String objects.' + ); + } + $object->add($it); + } + + return $object; + case CBORObject::MAJOR_TYPE_TEXT_STRING: //3 + $object = IndefiniteLengthTextStringObject::create(); + while (! ($it = $this->process($stream, true)) instanceof BreakObject) { + if (! $it instanceof TextStringObject) { + throw new RuntimeException( + 'Unable to parse the data. Infinite Text String object can only get Text String objects.' + ); + } + $object->add($it); + } + + return $object; + case CBORObject::MAJOR_TYPE_LIST: //4 + $object = IndefiniteLengthListObject::create(); + $it = $this->process($stream, true); + while (! $it instanceof BreakObject) { + $object->add($it); + $it = $this->process($stream, true); + } + + return $object; + case CBORObject::MAJOR_TYPE_MAP: //5 + $object = IndefiniteLengthMapObject::create(); + while (! ($it = $this->process($stream, true)) instanceof BreakObject) { + $object->add($it, $this->process($stream, false)); + } + + return $object; + case CBORObject::MAJOR_TYPE_OTHER_TYPE: //7 + if (! $breakable) { + throw new InvalidArgumentException('Cannot parse the data. No enclosing indefinite.'); + } + + return BreakObject::create(); + case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER: //0 + case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER: //1 + case CBORObject::MAJOR_TYPE_TAG: //6 + default: + throw new InvalidArgumentException(sprintf( + 'Cannot parse the data. Found infinite length for Major Type "%s" (%d).', + str_pad(decbin($mt), 5, '0', STR_PAD_LEFT), + $mt + )); + } + } + + private function generateTagManager(): TagManagerInterface + { + return TagManager::create() + ->add(DatetimeTag::class) + ->add(TimestampTag::class) + + ->add(UnsignedBigIntegerTag::class) + ->add(NegativeBigIntegerTag::class) + + ->add(DecimalFractionTag::class) + ->add(BigFloatTag::class) + + ->add(Base64UrlEncodingTag::class) + ->add(Base64EncodingTag::class) + ->add(Base16EncodingTag::class) + ->add(CBOREncodingTag::class) + + ->add(UriTag::class) + ->add(Base64UrlTag::class) + ->add(Base64Tag::class) + ->add(MimeTag::class) + + ->add(CBORTag::class) + ; + } + + private function generateOtherObjectManager(): OtherObjectManagerInterface + { + return OtherObjectManager::create() + ->add(BreakObject::class) + ->add(SimpleObject::class) + ->add(FalseObject::class) + ->add(TrueObject::class) + ->add(NullObject::class) + ->add(UndefinedObject::class) + ->add(HalfPrecisionFloatObject::class) + ->add(SinglePrecisionFloatObject::class) + ->add(DoublePrecisionFloatObject::class) + ; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/DecoderInterface.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/DecoderInterface.php new file mode 100644 index 00000000..3d7b1924 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/DecoderInterface.php @@ -0,0 +1,19 @@ +chunks as $chunk) { + $result .= $chunk->__toString(); + } + + return $result . "\xFF"; + } + + public static function create(): self + { + return new self(); + } + + public function add(ByteStringObject $chunk): self + { + $this->chunks[] = $chunk; + + return $this; + } + + public function append(string $chunk): self + { + $this->add(ByteStringObject::create($chunk)); + + return $this; + } + + public function getValue(): string + { + $result = ''; + foreach ($this->chunks as $chunk) { + $result .= $chunk->getValue(); + } + + return $result; + } + + public function getLength(): int + { + $length = 0; + foreach ($this->chunks as $chunk) { + $length += $chunk->getLength(); + } + + return $length; + } + + public function normalize(): string + { + $result = ''; + foreach ($this->chunks as $chunk) { + $result .= $chunk->normalize(); + } + + return $result; + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false): string + { + $result = ''; + foreach ($this->chunks as $chunk) { + $result .= $chunk->getNormalizedData($ignoreTags); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php new file mode 100644 index 00000000..2bf44fb4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php @@ -0,0 +1,167 @@ + + * @phpstan-implements IteratorAggregate + * @final + */ +class IndefiniteLengthListObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess +{ + private const MAJOR_TYPE = self::MAJOR_TYPE_LIST; + + private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE; + + /** + * @var CBORObject[] + */ + private $data = []; + + public function __construct() + { + parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION); + } + + public function __toString(): string + { + $result = parent::__toString(); + foreach ($this->data as $object) { + $result .= (string) $object; + } + + return $result . "\xFF"; + } + + public static function create(): self + { + return new self(); + } + + /** + * @return mixed[] + */ + public function normalize(): array + { + return array_map(static function (CBORObject $object) { + return $object instanceof Normalizable ? $object->normalize() : $object; + }, $this->data); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + * + * @return mixed[] + */ + public function getNormalizedData(bool $ignoreTags = false): array + { + return array_map(static function (CBORObject $object) use ($ignoreTags) { + return $object->getNormalizedData($ignoreTags); + }, $this->data); + } + + public function add(CBORObject $item): self + { + $this->data[] = $item; + + return $this; + } + + public function has(int $index): bool + { + return array_key_exists($index, $this->data); + } + + public function remove(int $index): self + { + if (! $this->has($index)) { + return $this; + } + unset($this->data[$index]); + $this->data = array_values($this->data); + + return $this; + } + + public function get(int $index): CBORObject + { + if (! $this->has($index)) { + throw new InvalidArgumentException('Index not found.'); + } + + return $this->data[$index]; + } + + public function set(int $index, CBORObject $object): self + { + if (! $this->has($index)) { + throw new InvalidArgumentException('Index not found.'); + } + + $this->data[$index] = $object; + + return $this; + } + + /** + * @deprecated The method will be removed on v3.0. No replacement + */ + public function count(): int + { + return count($this->data); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->data); + } + + public function offsetExists($offset): bool + { + return $this->has($offset); + } + + public function offsetGet($offset): CBORObject + { + return $this->get($offset); + } + + public function offsetSet($offset, $value): void + { + if ($offset === null) { + $this->add($value); + + return; + } + + $this->set($offset, $value); + } + + public function offsetUnset($offset): void + { + $this->remove($offset); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php new file mode 100644 index 00000000..7bc7a1c1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php @@ -0,0 +1,201 @@ + + * @phpstan-implements IteratorAggregate + * @final + */ +class IndefiniteLengthMapObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess +{ + private const MAJOR_TYPE = self::MAJOR_TYPE_MAP; + + private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE; + + /** + * @var MapItem[] + */ + private $data = []; + + public function __construct() + { + parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION); + } + + public function __toString(): string + { + $result = parent::__toString(); + foreach ($this->data as $object) { + $result .= (string) $object->getKey(); + $result .= (string) $object->getValue(); + } + + return $result . "\xFF"; + } + + public static function create(): self + { + return new self(); + } + + /** + * @deprecated The method will be removed on v3.0. Please use "add" instead + */ + public function append(CBORObject $key, CBORObject $value): self + { + return $this->add($key, $value); + } + + public function add(CBORObject $key, CBORObject $value): self + { + if (! $key instanceof Normalizable) { + throw new InvalidArgumentException('Invalid key. Shall be normalizable'); + } + $this->data[$key->normalize()] = MapItem::create($key, $value); + + return $this; + } + + /** + * @param int|string $key + */ + public function has($key): bool + { + return array_key_exists($key, $this->data); + } + + /** + * @param int|string $index + */ + public function remove($index): self + { + if (! $this->has($index)) { + return $this; + } + unset($this->data[$index]); + $this->data = array_values($this->data); + + return $this; + } + + /** + * @param int|string $index + */ + public function get($index): CBORObject + { + if (! $this->has($index)) { + throw new InvalidArgumentException('Index not found.'); + } + + return $this->data[$index]->getValue(); + } + + public function set(MapItem $object): self + { + $key = $object->getKey(); + if (! $key instanceof Normalizable) { + throw new InvalidArgumentException('Invalid key. Shall be normalizable'); + } + + $this->data[$key->normalize()] = $object; + + return $this; + } + + /** + * @deprecated The method will be removed on v3.0. No replacement + */ + public function count(): int + { + return count($this->data); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->data); + } + + /** + * @return mixed[] + */ + public function normalize(): array + { + return array_reduce($this->data, static function (array $carry, MapItem $item): array { + $key = $item->getKey(); + if (! $key instanceof Normalizable) { + throw new InvalidArgumentException('Invalid key. Shall be normalizable'); + } + $valueObject = $item->getValue(); + $carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject; + + return $carry; + }, []); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + * + * @return mixed[] + */ + public function getNormalizedData(bool $ignoreTags = false): array + { + return array_reduce($this->data, static function (array $carry, MapItem $item) use ($ignoreTags): array { + $key = $item->getKey(); + $valueObject = $item->getValue(); + $carry[$key->getNormalizedData($ignoreTags)] = $valueObject->getNormalizedData($ignoreTags); + + return $carry; + }, []); + } + + public function offsetExists($offset): bool + { + return $this->has($offset); + } + + public function offsetGet($offset): CBORObject + { + return $this->get($offset); + } + + public function offsetSet($offset, $value): void + { + if (! $offset instanceof CBORObject) { + throw new InvalidArgumentException('Invalid key'); + } + if (! $value instanceof CBORObject) { + throw new InvalidArgumentException('Invalid value'); + } + + $this->set(MapItem::create($offset, $value)); + } + + public function offsetUnset($offset): void + { + $this->remove($offset); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php new file mode 100644 index 00000000..108528e2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php @@ -0,0 +1,106 @@ +data as $object) { + $result .= (string) $object; + } + + return $result . "\xFF"; + } + + public static function create(): self + { + return new self(); + } + + public function add(TextStringObject $chunk): self + { + $this->data[] = $chunk; + + return $this; + } + + public function append(string $chunk): self + { + $this->add(TextStringObject::create($chunk)); + + return $this; + } + + public function getValue(): string + { + $result = ''; + foreach ($this->data as $object) { + $result .= $object->getValue(); + } + + return $result; + } + + public function getLength(): int + { + $length = 0; + foreach ($this->data as $object) { + $length += $object->getLength(); + } + + return $length; + } + + public function normalize(): string + { + $result = ''; + foreach ($this->data as $object) { + $result .= $object->normalize(); + } + + return $result; + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false): string + { + $result = ''; + foreach ($this->data as $object) { + $result .= $object->getNormalizedData($ignoreTags); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/InfiniteListObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/InfiniteListObject.php new file mode 100644 index 00000000..526d74cc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/InfiniteListObject.php @@ -0,0 +1,21 @@ + $data + * + * @return array{int, null|string} + */ + public static function getLengthOfArray(array $data): array + { + $length = count($data); + + return self::computeLength($length); + } + + /** + * @return array{int, null|string} + */ + private static function computeLength(int $length): array + { + switch (true) { + case $length <= 23: + return [$length, null]; + case $length <= 0xFF: + return [CBORObject::LENGTH_1_BYTE, chr($length)]; + case $length <= 0xFFFF: + return [CBORObject::LENGTH_2_BYTES, self::hex2bin(dechex($length))]; + case $length <= 0xFFFFFFFF: + return [CBORObject::LENGTH_4_BYTES, self::hex2bin(dechex($length))]; + case BigInteger::of($length)->isLessThanOrEqualTo(BigInteger::fromBase('FFFFFFFFFFFFFFFF', 16)): + return [CBORObject::LENGTH_8_BYTES, self::hex2bin(dechex($length))]; + default: + return [CBORObject::LENGTH_INDEFINITE, null]; + } + } + + private static function hex2bin(string $data): string + { + $data = str_pad($data, (int) (2 ** ceil(log(mb_strlen($data, '8bit'), 2))), '0', STR_PAD_LEFT); + $result = hex2bin($data); + if ($result === false) { + throw new InvalidArgumentException('Unable to convert the data'); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ListObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ListObject.php new file mode 100644 index 00000000..f3a32133 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/ListObject.php @@ -0,0 +1,187 @@ + + * @phpstan-implements IteratorAggregate + */ +class ListObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess +{ + private const MAJOR_TYPE = self::MAJOR_TYPE_LIST; + + /** + * @var CBORObject[] + */ + private $data; + + /** + * @var string|null + */ + private $length; + + /** + * @param CBORObject[] $data + */ + public function __construct(array $data = []) + { + [$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data); + array_map(static function ($item): void { + if (! $item instanceof CBORObject) { + throw new InvalidArgumentException('The list must contain only CBORObject objects.'); + } + }, $data); + + parent::__construct(self::MAJOR_TYPE, $additionalInformation); + $this->data = array_values($data); + $this->length = $length; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->length !== null) { + $result .= $this->length; + } + foreach ($this->data as $object) { + $result .= (string) $object; + } + + return $result; + } + + /** + * @param CBORObject[] $data + */ + public static function create(array $data = []): self + { + return new self($data); + } + + public function add(CBORObject $object): self + { + $this->data[] = $object; + [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data); + + return $this; + } + + public function has(int $index): bool + { + return array_key_exists($index, $this->data); + } + + public function remove(int $index): self + { + if (! $this->has($index)) { + return $this; + } + unset($this->data[$index]); + $this->data = array_values($this->data); + [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data); + + return $this; + } + + public function get(int $index): CBORObject + { + if (! $this->has($index)) { + throw new InvalidArgumentException('Index not found.'); + } + + return $this->data[$index]; + } + + public function set(int $index, CBORObject $object): self + { + if (! $this->has($index)) { + throw new InvalidArgumentException('Index not found.'); + } + + $this->data[$index] = $object; + [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data); + + return $this; + } + + /** + * @return array + */ + public function normalize(): array + { + return array_map(static function (CBORObject $object) { + return $object instanceof Normalizable ? $object->normalize() : $object; + }, $this->data); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + * + * @return array + */ + public function getNormalizedData(bool $ignoreTags = false): array + { + return array_map(static function (CBORObject $object) use ($ignoreTags) { + return $object->getNormalizedData($ignoreTags); + }, $this->data); + } + + public function count(): int + { + return count($this->data); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->data); + } + + public function offsetExists($offset): bool + { + return $this->has($offset); + } + + public function offsetGet($offset): CBORObject + { + return $this->get($offset); + } + + public function offsetSet($offset, $value): void + { + if ($offset === null) { + $this->add($value); + + return; + } + + $this->set($offset, $value); + } + + public function offsetUnset($offset): void + { + $this->remove($offset); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapItem.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapItem.php new file mode 100644 index 00000000..39578a6e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapItem.php @@ -0,0 +1,48 @@ +key = $key; + $this->value = $value; + } + + public static function create(CBORObject $key, CBORObject $value): self + { + return new self($key, $value); + } + + public function getKey(): CBORObject + { + return $this->key; + } + + public function getValue(): CBORObject + { + return $this->value; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapObject.php new file mode 100644 index 00000000..9c71332e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/MapObject.php @@ -0,0 +1,217 @@ + + * @phpstan-implements IteratorAggregate + */ +final class MapObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess +{ + private const MAJOR_TYPE = self::MAJOR_TYPE_MAP; + + /** + * @var MapItem[] + */ + private $data; + + /** + * @var string|null + */ + private $length; + + /** + * @param MapItem[] $data + */ + public function __construct(array $data = []) + { + [$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data); + array_map(static function ($item): void { + if (! $item instanceof MapItem) { + throw new InvalidArgumentException('The list must contain only MapItem objects.'); + } + }, $data); + + parent::__construct(self::MAJOR_TYPE, $additionalInformation); + $this->data = $data; + $this->length = $length; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->length !== null) { + $result .= $this->length; + } + foreach ($this->data as $object) { + $result .= $object->getKey() + ->__toString() + ; + $result .= $object->getValue() + ->__toString() + ; + } + + return $result; + } + + /** + * @param MapItem[] $data + */ + public static function create(array $data = []): self + { + return new self($data); + } + + public function add(CBORObject $key, CBORObject $value): self + { + if (! $key instanceof Normalizable) { + throw new InvalidArgumentException('Invalid key. Shall be normalizable'); + } + $this->data[$key->normalize()] = MapItem::create($key, $value); + [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data); + + return $this; + } + + /** + * @param int|string $key + */ + public function has($key): bool + { + return array_key_exists($key, $this->data); + } + + /** + * @param int|string $index + */ + public function remove($index): self + { + if (! $this->has($index)) { + return $this; + } + unset($this->data[$index]); + $this->data = array_values($this->data); + [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data); + + return $this; + } + + /** + * @param int|string $index + */ + public function get($index): CBORObject + { + if (! $this->has($index)) { + throw new InvalidArgumentException('Index not found.'); + } + + return $this->data[$index]->getValue(); + } + + public function set(MapItem $object): self + { + $key = $object->getKey(); + if (! $key instanceof Normalizable) { + throw new InvalidArgumentException('Invalid key. Shall be normalizable'); + } + + $this->data[$key->normalize()] = $object; + [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data); + + return $this; + } + + public function count(): int + { + return count($this->data); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->data); + } + + /** + * @return array + */ + public function normalize(): array + { + return array_reduce($this->data, static function (array $carry, MapItem $item): array { + $key = $item->getKey(); + if (! $key instanceof Normalizable) { + throw new InvalidArgumentException('Invalid key. Shall be normalizable'); + } + $valueObject = $item->getValue(); + $carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject; + + return $carry; + }, []); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + * + * @return array + */ + public function getNormalizedData(bool $ignoreTags = false): array + { + return array_reduce($this->data, static function (array $carry, MapItem $item) use ($ignoreTags): array { + $key = $item->getKey(); + $valueObject = $item->getValue(); + $carry[$key->getNormalizedData($ignoreTags)] = $valueObject->getNormalizedData($ignoreTags); + + return $carry; + }, []); + } + + public function offsetExists($offset): bool + { + return $this->has($offset); + } + + public function offsetGet($offset): CBORObject + { + return $this->get($offset); + } + + public function offsetSet($offset, $value): void + { + if (! $offset instanceof CBORObject) { + throw new InvalidArgumentException('Invalid key'); + } + if (! $value instanceof CBORObject) { + throw new InvalidArgumentException('Invalid value'); + } + + $this->set(MapItem::create($offset, $value)); + } + + public function offsetUnset($offset): void + { + $this->remove($offset); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/NegativeIntegerObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/NegativeIntegerObject.php new file mode 100644 index 00000000..ad1bbe1e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/NegativeIntegerObject.php @@ -0,0 +1,136 @@ +data = $data; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->data !== null) { + $result .= $this->data; + } + + return $result; + } + + public static function createObjectForValue(int $additionalInformation, ?string $data): self + { + return new self($additionalInformation, $data); + } + + public static function create(int $value): self + { + return self::createFromString((string) $value); + } + + public static function createFromString(string $value): self + { + $integer = BigInteger::of($value); + + return self::createBigInteger($integer); + } + + public function getValue(): string + { + if ($this->data === null) { + return (string) (-1 - $this->additionalInformation); + } + + $result = Utils::binToBigInteger($this->data); + $minusOne = BigInteger::of(-1); + + return $minusOne->minus($result) + ->toBase(10) + ; + } + + public function normalize(): string + { + return $this->getValue(); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false): string + { + return $this->getValue(); + } + + private static function createBigInteger(BigInteger $integer): self + { + if ($integer->isGreaterThanOrEqualTo(BigInteger::zero())) { + throw new InvalidArgumentException('The value must be a negative integer.'); + } + + $minusOne = BigInteger::of(-1); + $computed_value = $minusOne->minus($integer); + + switch (true) { + case $computed_value->isLessThan(BigInteger::of(24)): + $ai = $computed_value->toInt(); + $data = null; + break; + case $computed_value->isLessThan(BigInteger::fromBase('FF', 16)): + $ai = 24; + $data = self::hex2bin(str_pad($computed_value->toBase(16), 2, '0', STR_PAD_LEFT)); + break; + case $computed_value->isLessThan(BigInteger::fromBase('FFFF', 16)): + $ai = 25; + $data = self::hex2bin(str_pad($computed_value->toBase(16), 4, '0', STR_PAD_LEFT)); + break; + case $computed_value->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)): + $ai = 26; + $data = self::hex2bin(str_pad($computed_value->toBase(16), 8, '0', STR_PAD_LEFT)); + break; + default: + throw new InvalidArgumentException( + 'Out of range. Please use NegativeBigIntegerTag tag with ByteStringObject object instead.' + ); + } + + return new self($ai, $data); + } + + private static function hex2bin(string $data): string + { + $result = hex2bin($data); + if ($result === false) { + throw new InvalidArgumentException('Unable to convert the data'); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Normalizable.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Normalizable.php new file mode 100644 index 00000000..3b776621 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Normalizable.php @@ -0,0 +1,22 @@ +data = $data; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->data !== null) { + $result .= $this->data; + } + + return $result; + } + + public function getContent(): ?string + { + return $this->data; + } + + /** + * @return int[] + */ + abstract public static function supportedAdditionalInformation(): array; + + abstract public static function createFromLoadedData(int $additionalInformation, ?string $data): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/BreakObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/BreakObject.php new file mode 100644 index 00000000..339f11b3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/BreakObject.php @@ -0,0 +1,47 @@ +normalize(); + } + + /** + * @return float|int + */ + public function normalize() + { + $exponent = $this->getExponent(); + $mantissa = $this->getMantissa(); + $sign = $this->getSign(); + + if ($exponent === 0) { + $val = $mantissa * 2 ** (-(1022 + 52)); + } elseif ($exponent !== 0b11111111111) { + $val = ($mantissa + (1 << 52)) * 2 ** ($exponent - (1023 + 52)); + } else { + $val = $mantissa === 0 ? INF : NAN; + } + + return $sign * $val; + } + + public function getExponent(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + + return Utils::binToBigInteger($data)->shiftedRight(52)->and(Utils::hexToBigInteger('7ff'))->toInt(); + } + + public function getMantissa(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + + return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('fffffffffffff'))->toInt(); + } + + public function getSign(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + $sign = Utils::binToBigInteger($data)->shiftedRight(63); + + return $sign->isEqualTo(BigInteger::one()) ? -1 : 1; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/FalseObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/FalseObject.php new file mode 100644 index 00000000..c3ce42ab --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/FalseObject.php @@ -0,0 +1,53 @@ +normalize(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/GenericObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/GenericObject.php new file mode 100644 index 00000000..fb9fccc4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/GenericObject.php @@ -0,0 +1,43 @@ +data; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php new file mode 100644 index 00000000..1f05c5bb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php @@ -0,0 +1,97 @@ +normalize(); + } + + /** + * @return float|int + */ + public function normalize() + { + $exponent = $this->getExponent(); + $mantissa = $this->getMantissa(); + $sign = $this->getSign(); + + if ($exponent === 0) { + $val = $mantissa * 2 ** (-24); + } elseif ($exponent !== 0b11111) { + $val = ($mantissa + (1 << 10)) * 2 ** ($exponent - 25); + } else { + $val = $mantissa === 0 ? INF : NAN; + } + + return $sign * $val; + } + + public function getExponent(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + + return Utils::binToBigInteger($data)->shiftedRight(10)->and(Utils::hexToBigInteger('1f'))->toInt(); + } + + public function getMantissa(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + + return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('3ff'))->toInt(); + } + + public function getSign(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + $sign = Utils::binToBigInteger($data)->shiftedRight(15); + + return $sign->isEqualTo(BigInteger::one()) ? -1 : 1; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/NullObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/NullObject.php new file mode 100644 index 00000000..a960acf4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/NullObject.php @@ -0,0 +1,53 @@ +normalize(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php new file mode 100644 index 00000000..88edcd19 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php @@ -0,0 +1,59 @@ +classes[$ai] = $class; + } + + return $this; + } + + public function getClassForValue(int $value): string + { + return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericObject::class; + } + + public function createObjectForValue(int $value, ?string $data): OtherObject + { + /** @var OtherObject $class */ + $class = $this->getClassForValue($value); + + return $class::createFromLoadedData($value, $data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php new file mode 100644 index 00000000..6c0336de --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php @@ -0,0 +1,21 @@ +data === null) { + return $this->getAdditionalInformation(); + } + + return Utils::binToInt($this->data); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false): int + { + return $this->normalize(); + } + + public static function create(int $value): self + { + switch (true) { + case $value < 32: + return new self($value, null); + case $value < 256: + return new self(24, chr($value)); + default: + throw new InvalidArgumentException('The value is not a valid simple value.'); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php new file mode 100644 index 00000000..3c3af613 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php @@ -0,0 +1,96 @@ +normalize(); + } + + /** + * @return float|int + */ + public function normalize() + { + $exponent = $this->getExponent(); + $mantissa = $this->getMantissa(); + $sign = $this->getSign(); + + if ($exponent === 0) { + $val = $mantissa * 2 ** (-(126 + 23)); + } elseif ($exponent !== 0b11111111) { + $val = ($mantissa + (1 << 23)) * 2 ** ($exponent - (127 + 23)); + } else { + $val = $mantissa === 0 ? INF : NAN; + } + + return $sign * $val; + } + + public function getExponent(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + + return Utils::binToBigInteger($data)->shiftedRight(23)->and(Utils::hexToBigInteger('ff'))->toInt(); + } + + public function getMantissa(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + + return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('7fffff'))->toInt(); + } + + public function getSign(): int + { + $data = $this->data; + Utils::assertString($data, 'Invalid data'); + $sign = Utils::binToBigInteger($data)->shiftedRight(31); + + return $sign->isEqualTo(BigInteger::one()) ? -1 : 1; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/TrueObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/TrueObject.php new file mode 100644 index 00000000..d348a1ba --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/TrueObject.php @@ -0,0 +1,53 @@ +normalize(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php new file mode 100644 index 00000000..0b4bf899 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php @@ -0,0 +1,49 @@ +resource = $resource; + } + + public static function create(string $data): self + { + return new self($data); + } + + public function read(int $length): string + { + if ($length === 0) { + return ''; + } + + $alreadyRead = 0; + $data = ''; + while ($alreadyRead < $length) { + $left = $length - $alreadyRead; + $sizeToRead = $left < 1024 && $left > 0 ? $left : 1024; + $newData = fread($this->resource, $sizeToRead); + $alreadyRead += $sizeToRead; + + if ($newData === false) { + throw new RuntimeException('Unable to read the memory'); + } + if (mb_strlen($newData, '8bit') < $sizeToRead) { + throw new InvalidArgumentException(sprintf( + 'Out of range. Expected: %d, read: %d.', + $length, + mb_strlen($data, '8bit') + )); + } + $data .= $newData; + } + + if (mb_strlen($data, '8bit') !== $length) { + throw new InvalidArgumentException(sprintf( + 'Out of range. Expected: %d, read: %d.', + $length, + mb_strlen($data, '8bit') + )); + } + + return $data; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag.php new file mode 100644 index 00000000..9d7171a9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag.php @@ -0,0 +1,99 @@ +data = $data; + $this->object = $object; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->data !== null) { + $result .= $this->data; + } + + return $result . $this->object; + } + + public function getData(): ?string + { + return $this->data; + } + + abstract public static function getTagId(): int; + + abstract public static function createFromLoadedData( + int $additionalInformation, + ?string $data, + CBORObject $object + ): self; + + public function getValue(): CBORObject + { + return $this->object; + } + + /** + * @return array{int, null|string} + */ + protected static function determineComponents(int $tag): array + { + switch (true) { + case $tag < 0: + throw new InvalidArgumentException('The value must be a positive integer.'); + case $tag < 24: + return [$tag, null]; + case $tag < 0xFF: + return [24, self::hex2bin(dechex($tag))]; + case $tag < 0xFFFF: + return [25, self::hex2bin(dechex($tag))]; + case $tag < 0xFFFFFFFF: + return [26, self::hex2bin(dechex($tag))]; + default: + throw new InvalidArgumentException( + 'Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.' + ); + } + } + + private static function hex2bin(string $data): string + { + $result = hex2bin($data); + if ($result === false) { + throw new InvalidArgumentException('Unable to convert the data'); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php new file mode 100644 index 00000000..1130358d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php @@ -0,0 +1,57 @@ +object->getNormalizedData($ignoreTags); + } + + if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) { + return $this->object->getNormalizedData($ignoreTags); + } + + return bin2hex($this->object->getNormalizedData($ignoreTags)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php new file mode 100644 index 00000000..6f8bb60e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php @@ -0,0 +1,63 @@ +object->getNormalizedData($ignoreTags); + } + + if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) { + return $this->object->getNormalizedData($ignoreTags); + } + + $result = base64_decode($this->object->getNormalizedData($ignoreTags), true); + if ($result === false) { + throw new InvalidArgumentException('Unable to decode the data'); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64Tag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64Tag.php new file mode 100644 index 00000000..b6693270 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64Tag.php @@ -0,0 +1,57 @@ +object->getNormalizedData($ignoreTags); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php new file mode 100644 index 00000000..4dbaaf82 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php @@ -0,0 +1,58 @@ +object->getNormalizedData($ignoreTags); + } + + if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) { + return $this->object->getNormalizedData($ignoreTags); + } + + return Utils::decode($this->object->getNormalizedData($ignoreTags)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php new file mode 100644 index 00000000..1d7d27f6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php @@ -0,0 +1,57 @@ +object->getNormalizedData($ignoreTags); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/BigFloatTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/BigFloatTag.php new file mode 100644 index 00000000..c6a33b24 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/BigFloatTag.php @@ -0,0 +1,108 @@ +get(0); + if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) { + throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.'); + } + $m = $object->get(1); + if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) { + throw new InvalidArgumentException( + 'The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.' + ); + } + + parent::__construct($additionalInformation, $data, $object); + } + + public static function getTagId(): int + { + return self::TAG_BIG_FLOAT; + } + + public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag + { + return new self($additionalInformation, $data, $object); + } + + public static function create(CBORObject $object): Tag + { + [$ai, $data] = self::determineComponents(self::TAG_BIG_FLOAT); + + return new self($ai, $data, $object); + } + + public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag + { + $object = ListObject::create() + ->add($e) + ->add($m) + ; + + return self::create($object); + } + + public function normalize() + { + /** @var ListObject $object */ + $object = $this->object; + /** @var UnsignedIntegerObject|NegativeIntegerObject $e */ + $e = $object->get(0); + /** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */ + $m = $object->get(1); + + return rtrim(bcmul($m->normalize(), bcpow('2', $e->normalize(), 100), 100), '0'); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + if ($ignoreTags) { + return $this->object->getNormalizedData($ignoreTags); + } + + if (! $this->object instanceof ListObject || count($this->object) !== 2) { + return $this->object->getNormalizedData($ignoreTags); + } + + return $this->normalize(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php new file mode 100644 index 00000000..612a6d31 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php @@ -0,0 +1,57 @@ +object->getNormalizedData($ignoreTags); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBORTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBORTag.php new file mode 100644 index 00000000..fbb8581f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/CBORTag.php @@ -0,0 +1,54 @@ +object instanceof Normalizable ? $this->object->normalize() : $this->object; + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + return $this->object->getNormalizedData($ignoreTags); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DatetimeTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DatetimeTag.php new file mode 100644 index 00000000..ac078374 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DatetimeTag.php @@ -0,0 +1,84 @@ +object; + $result = DateTimeImmutable::createFromFormat(DATE_RFC3339, $object->normalize()); + if ($result !== false) { + return $result; + } + + $formatted = DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.uP', $object->normalize()); + if ($formatted === false) { + throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object'); + } + + return $formatted; + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + if ($ignoreTags) { + return $this->object->getNormalizedData($ignoreTags); + } + + return $this->normalize(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php new file mode 100644 index 00000000..76b5c6a7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php @@ -0,0 +1,114 @@ +get(0); + if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) { + throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.'); + } + $m = $object->get(1); + if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) { + throw new InvalidArgumentException( + 'The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.' + ); + } + + parent::__construct(self::TAG_DECIMAL_FRACTION, null, $object); + } + + public static function create(CBORObject $object): self + { + return new self($object); + } + + public static function getTagId(): int + { + return self::TAG_DECIMAL_FRACTION; + } + + public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag + { + return new self($object); + } + + public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag + { + $object = ListObject::create() + ->add($e) + ->add($m) + ; + + return self::create($object); + } + + public function normalize() + { + /** @var ListObject $object */ + $object = $this->object; + /** @var UnsignedIntegerObject|NegativeIntegerObject $e */ + $e = $object->get(0); + /** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */ + $m = $object->get(1); + + return rtrim(bcmul($m->normalize(), bcpow('10', $e->normalize(), 100), 100), '0'); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + if ($ignoreTags) { + return $this->object->getNormalizedData($ignoreTags); + } + + if (! $this->object instanceof ListObject || count($this->object) !== 2) { + return $this->object->getNormalizedData($ignoreTags); + } + $e = $this->object->get(0); + $m = $this->object->get(1); + + if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) { + return $this->object->getNormalizedData($ignoreTags); + } + if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) { + return $this->object->getNormalizedData($ignoreTags); + } + + return $this->normalize(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/EpochTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/EpochTag.php new file mode 100644 index 00000000..aa00c73f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/EpochTag.php @@ -0,0 +1,21 @@ +object; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/MimeTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/MimeTag.php new file mode 100644 index 00000000..bf5d2bb1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/MimeTag.php @@ -0,0 +1,66 @@ +object; + + return $object->normalize(); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + return $this->object->getNormalizedData($ignoreTags); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php new file mode 100644 index 00000000..15726366 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php @@ -0,0 +1,83 @@ +object; + $integer = BigInteger::fromBase(bin2hex($object->getValue()), 16); + $minusOne = BigInteger::of(-1); + + return $minusOne->minus($integer) + ->toBase(10) + ; + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + if ($ignoreTags) { + return $this->object->getNormalizedData($ignoreTags); + } + + if (! $this->object instanceof ByteStringObject) { + return $this->object->getNormalizedData($ignoreTags); + } + $integer = BigInteger::fromBase(bin2hex($this->object->getValue()), 16); + $minusOne = BigInteger::of(-1); + + return $minusOne->minus($integer) + ->toBase(10) + ; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/PositiveBigIntegerTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/PositiveBigIntegerTag.php new file mode 100644 index 00000000..0a35896c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/PositiveBigIntegerTag.php @@ -0,0 +1,21 @@ +classes[$class::getTagId()] = $class; + + return $this; + } + + public function getClassForValue(int $value): string + { + return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericTag::class; + } + + public function createObjectForValue(int $additionalInformation, ?string $data, CBORObject $object): Tag + { + $value = $additionalInformation; + if ($additionalInformation >= 24) { + Utils::assertString($data, 'Invalid data'); + $value = Utils::binToInt($data); + } + /** @var Tag $class */ + $class = $this->getClassForValue($value); + + return $class::createFromLoadedData($additionalInformation, $data, $object); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php new file mode 100644 index 00000000..37e38620 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php @@ -0,0 +1,22 @@ +object; + + switch (true) { + case $object instanceof UnsignedIntegerObject: + case $object instanceof NegativeIntegerObject: + $formatted = DateTimeImmutable::createFromFormat('U', $object->normalize()); + + break; + case $object instanceof HalfPrecisionFloatObject: + case $object instanceof SinglePrecisionFloatObject: + case $object instanceof DoublePrecisionFloatObject: + $value = (string) $object->normalize(); + $parts = explode('.', $value); + if (isset($parts[1])) { + if (mb_strlen($parts[1], '8bit') > 6) { + $parts[1] = mb_substr($parts[1], 0, 6, '8bit'); + } else { + $parts[1] = str_pad($parts[1], 6, '0', STR_PAD_RIGHT); + } + } + $formatted = DateTimeImmutable::createFromFormat('U.u', implode('.', $parts)); + + break; + default: + throw new InvalidArgumentException('Unable to normalize the object'); + } + + if ($formatted === false) { + throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object'); + } + + return $formatted; + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + if ($ignoreTags) { + return $this->object->getNormalizedData($ignoreTags); + } + switch (true) { + case $this->object instanceof UnsignedIntegerObject: + case $this->object instanceof NegativeIntegerObject: + case $this->object instanceof HalfPrecisionFloatObject: + case $this->object instanceof SinglePrecisionFloatObject: + case $this->object instanceof DoublePrecisionFloatObject: + return $this->normalize(); + default: + return $this->object->getNormalizedData($ignoreTags); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php new file mode 100644 index 00000000..37e5bd7b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php @@ -0,0 +1,78 @@ +object; + + return Utils::hexToString($object->normalize()); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + if ($ignoreTags) { + return $this->object->getNormalizedData($ignoreTags); + } + + if (! $this->object instanceof ByteStringObject) { + return $this->object->getNormalizedData($ignoreTags); + } + + return Utils::hexToString($this->object->getValue()); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UriTag.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UriTag.php new file mode 100644 index 00000000..c14f1732 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Tag/UriTag.php @@ -0,0 +1,66 @@ +object; + + return $object->normalize(); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false) + { + return $this->object->getNormalizedData($ignoreTags); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TagObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TagObject.php new file mode 100644 index 00000000..0ccb5c80 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TagObject.php @@ -0,0 +1,21 @@ +data = $data; + $this->length = $length; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->length !== null) { + $result .= $this->length; + } + + return $result . $this->data; + } + + public static function create(string $data): self + { + return new self($data); + } + + public function getValue(): string + { + return $this->data; + } + + public function getLength(): int + { + return mb_strlen($this->data, 'utf8'); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false): string + { + return $this->data; + } + + public function normalize() + { + return $this->data; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TextStringWithChunkObject.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TextStringWithChunkObject.php new file mode 100644 index 00000000..0cb6b960 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/TextStringWithChunkObject.php @@ -0,0 +1,21 @@ +data = $data; + } + + public function __toString(): string + { + $result = parent::__toString(); + if ($this->data !== null) { + $result .= $this->data; + } + + return $result; + } + + public static function createObjectForValue(int $additionalInformation, ?string $data): self + { + return new self($additionalInformation, $data); + } + + public static function create(int $value): self + { + return self::createFromString((string) $value); + } + + public static function createFromHex(string $value): self + { + $integer = BigInteger::fromBase($value, 16); + + return self::createBigInteger($integer); + } + + public static function createFromString(string $value): self + { + $integer = BigInteger::of($value); + + return self::createBigInteger($integer); + } + + public function getMajorType(): int + { + return self::MAJOR_TYPE; + } + + public function getValue(): string + { + if ($this->data === null) { + return (string) $this->additionalInformation; + } + + $integer = BigInteger::fromBase(bin2hex($this->data), 16); + + return $integer->toBase(10); + } + + public function normalize(): string + { + return $this->getValue(); + } + + /** + * @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface + */ + public function getNormalizedData(bool $ignoreTags = false): string + { + return $this->getValue(); + } + + private static function createBigInteger(BigInteger $integer): self + { + if ($integer->isLessThan(BigInteger::zero())) { + throw new InvalidArgumentException('The value must be a positive integer.'); + } + + switch (true) { + case $integer->isLessThan(BigInteger::of(24)): + $ai = $integer->toInt(); + $data = null; + break; + case $integer->isLessThan(BigInteger::fromBase('FF', 16)): + $ai = 24; + $data = self::hex2bin(str_pad($integer->toBase(16), 2, '0', STR_PAD_LEFT)); + break; + case $integer->isLessThan(BigInteger::fromBase('FFFF', 16)): + $ai = 25; + $data = self::hex2bin(str_pad($integer->toBase(16), 4, '0', STR_PAD_LEFT)); + break; + case $integer->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)): + $ai = 26; + $data = self::hex2bin(str_pad($integer->toBase(16), 8, '0', STR_PAD_LEFT)); + break; + default: + throw new InvalidArgumentException( + 'Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.' + ); + } + + return new self($ai, $data); + } + + private static function hex2bin(string $data): string + { + $result = hex2bin($data); + if ($result === false) { + throw new InvalidArgumentException('Unable to convert the data'); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Utils.php b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Utils.php new file mode 100644 index 00000000..b671ed6e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/spomky-labs/cbor-php/src/Utils.php @@ -0,0 +1,69 @@ +toInt(); + } + + public static function binToBigInteger(string $value): BigInteger + { + return self::hexToBigInteger(bin2hex($value)); + } + + public static function hexToInt(string $value): int + { + return self::hexToBigInteger($value)->toInt(); + } + + public static function hexToBigInteger(string $value): BigInteger + { + return BigInteger::fromBase($value, 16); + } + + public static function hexToString(string $value): string + { + return BigInteger::fromBase(bin2hex($value), 16)->toBase(10); + } + + public static function decode(string $data): string + { + $decoded = base64_decode(strtr($data, '-_', '+/'), true); + if ($decoded === false) { + throw new InvalidArgumentException('Invalid data provided'); + } + + return $decoded; + } + + /** + * @param mixed|null $data + */ + public static function assertString($data, ?string $message = null): void + { + if (! is_string($data)) { + throw new InvalidArgumentException($message ?? ''); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/Ctype.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/Ctype.php new file mode 100644 index 00000000..ba75a2c9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/Ctype.php @@ -0,0 +1,232 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Ctype; + +/** + * Ctype implementation through regex. + * + * @internal + * + * @author Gert de Pagter + */ +final class Ctype +{ + /** + * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. + * + * @see https://php.net/ctype-alnum + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_alnum($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is a letter, FALSE otherwise. + * + * @see https://php.net/ctype-alpha + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_alpha($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); + } + + /** + * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. + * + * @see https://php.net/ctype-cntrl + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_cntrl($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); + } + + /** + * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. + * + * @see https://php.net/ctype-digit + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_digit($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. + * + * @see https://php.net/ctype-graph + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_graph($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); + } + + /** + * Returns TRUE if every character in text is a lowercase letter. + * + * @see https://php.net/ctype-lower + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_lower($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); + } + + /** + * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. + * + * @see https://php.net/ctype-print + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_print($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); + } + + /** + * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. + * + * @see https://php.net/ctype-punct + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_punct($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); + } + + /** + * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. + * + * @see https://php.net/ctype-space + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_space($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); + } + + /** + * Returns TRUE if every character in text is an uppercase letter. + * + * @see https://php.net/ctype-upper + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_upper($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); + } + + /** + * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. + * + * @see https://php.net/ctype-xdigit + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_xdigit($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); + } + + /** + * Converts integers to their char versions according to normal ctype behaviour, if needed. + * + * If an integer between -128 and 255 inclusive is provided, + * it is interpreted as the ASCII value of a single character + * (negative values have 256 added in order to allow characters in the Extended ASCII range). + * Any other integer is interpreted as a string containing the decimal digits of the integer. + * + * @param mixed $int + * @param string $function + * + * @return mixed + */ + private static function convert_int_to_char_for_ctype($int, $function) + { + if (!\is_int($int)) { + return $int; + } + + if ($int < -128 || $int > 255) { + return (string) $int; + } + + if (\PHP_VERSION_ID >= 80100) { + @trigger_error($function.'(): Argument of type int will be interpreted as string in the future', \E_USER_DEPRECATED); + } + + if ($int < 0) { + $int += 256; + } + + return \chr($int); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/LICENSE b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/LICENSE new file mode 100644 index 00000000..3f853aaf --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/README.md b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/README.md new file mode 100644 index 00000000..8add1ab0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/README.md @@ -0,0 +1,12 @@ +Symfony Polyfill / Ctype +======================== + +This component provides `ctype_*` functions to users who run php versions without the ctype extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap.php new file mode 100644 index 00000000..d54524b3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!function_exists('ctype_alnum')) { + function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } +} +if (!function_exists('ctype_alpha')) { + function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } +} +if (!function_exists('ctype_cntrl')) { + function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } +} +if (!function_exists('ctype_digit')) { + function ctype_digit($text) { return p\Ctype::ctype_digit($text); } +} +if (!function_exists('ctype_graph')) { + function ctype_graph($text) { return p\Ctype::ctype_graph($text); } +} +if (!function_exists('ctype_lower')) { + function ctype_lower($text) { return p\Ctype::ctype_lower($text); } +} +if (!function_exists('ctype_print')) { + function ctype_print($text) { return p\Ctype::ctype_print($text); } +} +if (!function_exists('ctype_punct')) { + function ctype_punct($text) { return p\Ctype::ctype_punct($text); } +} +if (!function_exists('ctype_space')) { + function ctype_space($text) { return p\Ctype::ctype_space($text); } +} +if (!function_exists('ctype_upper')) { + function ctype_upper($text) { return p\Ctype::ctype_upper($text); } +} +if (!function_exists('ctype_xdigit')) { + function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap80.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap80.php new file mode 100644 index 00000000..ab2f8611 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/bootstrap80.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (!function_exists('ctype_alnum')) { + function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); } +} +if (!function_exists('ctype_alpha')) { + function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); } +} +if (!function_exists('ctype_cntrl')) { + function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); } +} +if (!function_exists('ctype_digit')) { + function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); } +} +if (!function_exists('ctype_graph')) { + function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); } +} +if (!function_exists('ctype_lower')) { + function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); } +} +if (!function_exists('ctype_print')) { + function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); } +} +if (!function_exists('ctype_punct')) { + function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); } +} +if (!function_exists('ctype_space')) { + function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); } +} +if (!function_exists('ctype_upper')) { + function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); } +} +if (!function_exists('ctype_xdigit')) { + function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/composer.json b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/composer.json new file mode 100644 index 00000000..ccb8e570 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-ctype/composer.json @@ -0,0 +1,41 @@ +{ + "name": "symfony/polyfill-ctype", + "type": "library", + "description": "Symfony polyfill for ctype functions", + "keywords": ["polyfill", "compatibility", "portable", "ctype"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/LICENSE b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/LICENSE new file mode 100644 index 00000000..5593b1d8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Php80.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Php80.php new file mode 100644 index 00000000..362dd1a9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Php80.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Ion Bazan + * @author Nico Oelgart + * @author Nicolas Grekas + * + * @internal + */ +final class Php80 +{ + public static function fdiv(float $dividend, float $divisor): float + { + return @($dividend / $divisor); + } + + public static function get_debug_type($value): string + { + switch (true) { + case null === $value: return 'null'; + case \is_bool($value): return 'bool'; + case \is_string($value): return 'string'; + case \is_array($value): return 'array'; + case \is_int($value): return 'int'; + case \is_float($value): return 'float'; + case \is_object($value): break; + case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; + default: + if (null === $type = @get_resource_type($value)) { + return 'unknown'; + } + + if ('Unknown' === $type) { + $type = 'closed'; + } + + return "resource ($type)"; + } + + $class = \get_class($value); + + if (false === strpos($class, '@')) { + return $class; + } + + return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; + } + + public static function get_resource_id($res): int + { + if (!\is_resource($res) && null === @get_resource_type($res)) { + throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); + } + + return (int) $res; + } + + public static function preg_last_error_msg(): string + { + switch (preg_last_error()) { + case \PREG_INTERNAL_ERROR: + return 'Internal error'; + case \PREG_BAD_UTF8_ERROR: + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + case \PREG_BAD_UTF8_OFFSET_ERROR: + return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; + case \PREG_BACKTRACK_LIMIT_ERROR: + return 'Backtrack limit exhausted'; + case \PREG_RECURSION_LIMIT_ERROR: + return 'Recursion limit exhausted'; + case \PREG_JIT_STACKLIMIT_ERROR: + return 'JIT stack limit exhausted'; + case \PREG_NO_ERROR: + return 'No error'; + default: + return 'Unknown error'; + } + } + + public static function str_contains(string $haystack, string $needle): bool + { + return '' === $needle || false !== strpos($haystack, $needle); + } + + public static function str_starts_with(string $haystack, string $needle): bool + { + return 0 === strncmp($haystack, $needle, \strlen($needle)); + } + + public static function str_ends_with(string $haystack, string $needle): bool + { + if ('' === $needle || $needle === $haystack) { + return true; + } + + if ('' === $haystack) { + return false; + } + + $needleLength = \strlen($needle); + + return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/PhpToken.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/PhpToken.php new file mode 100644 index 00000000..fe6e6910 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/PhpToken.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Fedonyuk Anton + * + * @internal + */ +class PhpToken implements \Stringable +{ + /** + * @var int + */ + public $id; + + /** + * @var string + */ + public $text; + + /** + * @var int + */ + public $line; + + /** + * @var int + */ + public $pos; + + public function __construct(int $id, string $text, int $line = -1, int $position = -1) + { + $this->id = $id; + $this->text = $text; + $this->line = $line; + $this->pos = $position; + } + + public function getTokenName(): ?string + { + if ('UNKNOWN' === $name = token_name($this->id)) { + $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; + } + + return $name; + } + + /** + * @param int|string|array $kind + */ + public function is($kind): bool + { + foreach ((array) $kind as $value) { + if (\in_array($value, [$this->id, $this->text], true)) { + return true; + } + } + + return false; + } + + public function isIgnorable(): bool + { + return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); + } + + public function __toString(): string + { + return (string) $this->text; + } + + /** + * @return static[] + */ + public static function tokenize(string $code, int $flags = 0): array + { + $line = 1; + $position = 0; + $tokens = token_get_all($code, $flags); + foreach ($tokens as $index => $token) { + if (\is_string($token)) { + $id = \ord($token); + $text = $token; + } else { + [$id, $text, $line] = $token; + } + $tokens[$index] = new static($id, $text, $line, $position); + $position += \strlen($text); + } + + return $tokens; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/README.md b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/README.md new file mode 100644 index 00000000..10b8ee49 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/README.md @@ -0,0 +1,24 @@ +Symfony Polyfill / Php80 +======================== + +This component provides features added to PHP 8.0 core: + +- `Stringable` interface +- [`fdiv`](https://php.net/fdiv) +- `ValueError` class +- `UnhandledMatchError` class +- `FILTER_VALIDATE_BOOL` constant +- [`get_debug_type`](https://php.net/get_debug_type) +- [`preg_last_error_msg`](https://php.net/preg_last_error_msg) +- [`str_contains`](https://php.net/str_contains) +- [`str_starts_with`](https://php.net/str_starts_with) +- [`str_ends_with`](https://php.net/str_ends_with) +- [`get_resource_id`](https://php.net/get_resource_id) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php new file mode 100644 index 00000000..7ea6d277 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php @@ -0,0 +1,22 @@ +flags = $flags; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php new file mode 100644 index 00000000..72f10812 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php @@ -0,0 +1,7 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php80 as p; + +if (\PHP_VERSION_ID >= 80000) { + return; +} + +if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { + define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); +} + +if (!function_exists('fdiv')) { + function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } +} +if (!function_exists('preg_last_error_msg')) { + function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } +} +if (!function_exists('str_contains')) { + function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_starts_with')) { + function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_ends_with')) { + function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('get_debug_type')) { + function get_debug_type($value): string { return p\Php80::get_debug_type($value); } +} +if (!function_exists('get_resource_id')) { + function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/composer.json b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/composer.json new file mode 100644 index 00000000..5fe679db --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php80/composer.json @@ -0,0 +1,40 @@ +{ + "name": "symfony/polyfill-php80", + "type": "library", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/LICENSE b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/LICENSE new file mode 100644 index 00000000..efb17f98 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Php81.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Php81.php new file mode 100644 index 00000000..f0507b76 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Php81.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php81; + +/** + * @author Nicolas Grekas + * + * @internal + */ +final class Php81 +{ + public static function array_is_list(array $array): bool + { + if ([] === $array || $array === array_values($array)) { + return true; + } + + $nextKey = -1; + + foreach ($array as $k => $v) { + if ($k !== ++$nextKey) { + return false; + } + } + + return true; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/README.md b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/README.md new file mode 100644 index 00000000..5ef61be6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/README.md @@ -0,0 +1,16 @@ +Symfony Polyfill / Php81 +======================== + +This component provides features added to PHP 8.1 core: + +- [`array_is_list`](https://php.net/array_is_list) +- [`MYSQLI_REFRESH_REPLICA`](https://www.php.net/manual/en/mysqli.constants.php#constantmysqli-refresh-replica) constant +- [`ReturnTypeWillChange`](https://wiki.php.net/rfc/internal_method_return_types) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php new file mode 100644 index 00000000..f4cad34f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php @@ -0,0 +1,11 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php81 as p; + +if (\PHP_VERSION_ID >= 80100) { + return; +} + +if (defined('MYSQLI_REFRESH_SLAVE') && !defined('MYSQLI_REFRESH_REPLICA')) { + define('MYSQLI_REFRESH_REPLICA', 64); +} + +if (!function_exists('array_is_list')) { + function array_is_list(array $array): bool { return p\Php81::array_is_list($array); } +} + +if (!function_exists('enum_exists')) { + function enum_exists(string $enum, bool $autoload = true): bool { return $autoload && class_exists($enum) && false; } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/composer.json b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/composer.json new file mode 100644 index 00000000..c39ccf47 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/polyfill-php81/composer.json @@ -0,0 +1,36 @@ +{ + "name": "symfony/polyfill-php81", + "type": "library", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php81\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/CHANGELOG.md b/wp-content/plugins/wp-webauthn/vendor/symfony/process/CHANGELOG.md new file mode 100644 index 00000000..31b9ee6a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/CHANGELOG.md @@ -0,0 +1,116 @@ +CHANGELOG +========= + +5.2.0 +----- + + * added `Process::setOptions()` to set `Process` specific options + * added option `create_new_console` to allow a subprocess to continue + to run after the main script exited, both on Linux and on Windows + +5.1.0 +----- + + * added `Process::getStartTime()` to retrieve the start time of the process as float + +5.0.0 +----- + + * removed `Process::inheritEnvironmentVariables()` + * removed `PhpProcess::setPhpBinary()` + * `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell + * removed `Process::setCommandLine()` + +4.4.0 +----- + + * deprecated `Process::inheritEnvironmentVariables()`: env variables are always inherited. + * added `Process::getLastOutputTime()` method + +4.2.0 +----- + + * added the `Process::fromShellCommandline()` to run commands in a shell wrapper + * deprecated passing a command as string when creating a `Process` instance + * deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods + * added the `Process::waitUntil()` method to wait for the process only for a + specific output, then continue the normal execution of your application + +4.1.0 +----- + + * added the `Process::isTtySupported()` method that allows to check for TTY support + * made `PhpExecutableFinder` look for the `PHP_BINARY` env var when searching the php binary + * added the `ProcessSignaledException` class to properly catch signaled process errors + +4.0.0 +----- + + * environment variables will always be inherited + * added a second `array $env = []` argument to the `start()`, `run()`, + `mustRun()`, and `restart()` methods of the `Process` class + * added a second `array $env = []` argument to the `start()` method of the + `PhpProcess` class + * the `ProcessUtils::escapeArgument()` method has been removed + * the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()` + methods of the `Process` class have been removed + * support for passing `proc_open()` options has been removed + * removed the `ProcessBuilder` class, use the `Process` class instead + * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class + * passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not + supported anymore + +3.4.0 +----- + + * deprecated the ProcessBuilder class + * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor) + +3.3.0 +----- + + * added command line arrays in the `Process` class + * added `$env` argument to `Process::start()`, `run()`, `mustRun()` and `restart()` methods + * deprecated the `ProcessUtils::escapeArgument()` method + * deprecated not inheriting environment variables + * deprecated configuring `proc_open()` options + * deprecated configuring enhanced Windows compatibility + * deprecated configuring enhanced sigchild compatibility + +2.5.0 +----- + + * added support for PTY mode + * added the convenience method "mustRun" + * deprecation: Process::setStdin() is deprecated in favor of Process::setInput() + * deprecation: Process::getStdin() is deprecated in favor of Process::getInput() + * deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types + +2.4.0 +----- + + * added the ability to define an idle timeout + +2.3.0 +----- + + * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows + * added Process::signal() + * added Process::getPid() + * added support for a TTY mode + +2.2.0 +----- + + * added ProcessBuilder::setArguments() to reset the arguments on a builder + * added a way to retrieve the standard and error output incrementally + * added Process:restart() + +2.1.0 +----- + + * added support for non-blocking processes (start(), wait(), isRunning(), stop()) + * enhanced Windows compatibility + * added Process::getExitCodeText() that returns a string representation for + the exit code returned by the process + * added ProcessBuilder diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ExceptionInterface.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ExceptionInterface.php new file mode 100644 index 00000000..bd4a6040 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +/** + * Marker Interface for the Process Component. + * + * @author Johannes M. Schmitt + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/InvalidArgumentException.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..926ee211 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +/** + * InvalidArgumentException for the Process Component. + * + * @author Romain Neutron + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/LogicException.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/LogicException.php new file mode 100644 index 00000000..be3d490d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/LogicException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +/** + * LogicException for the Process Component. + * + * @author Romain Neutron + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessFailedException.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessFailedException.php new file mode 100644 index 00000000..328acfde --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessFailedException.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +use Symfony\Component\Process\Process; + +/** + * Exception for failed processes. + * + * @author Johannes M. Schmitt + */ +class ProcessFailedException extends RuntimeException +{ + private $process; + + public function __construct(Process $process) + { + if ($process->isSuccessful()) { + throw new InvalidArgumentException('Expected a failed process, but the given process was successful.'); + } + + $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s", + $process->getCommandLine(), + $process->getExitCode(), + $process->getExitCodeText(), + $process->getWorkingDirectory() + ); + + if (!$process->isOutputDisabled()) { + $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", + $process->getOutput(), + $process->getErrorOutput() + ); + } + + parent::__construct($error); + + $this->process = $process; + } + + public function getProcess() + { + return $this->process; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessSignaledException.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessSignaledException.php new file mode 100644 index 00000000..d4d32275 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessSignaledException.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +use Symfony\Component\Process\Process; + +/** + * Exception that is thrown when a process has been signaled. + * + * @author Sullivan Senechal + */ +final class ProcessSignaledException extends RuntimeException +{ + private $process; + + public function __construct(Process $process) + { + $this->process = $process; + + parent::__construct(sprintf('The process has been signaled with signal "%s".', $process->getTermSignal())); + } + + public function getProcess(): Process + { + return $this->process; + } + + public function getSignal(): int + { + return $this->getProcess()->getTermSignal(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessTimedOutException.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessTimedOutException.php new file mode 100644 index 00000000..94391a45 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/ProcessTimedOutException.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +use Symfony\Component\Process\Process; + +/** + * Exception that is thrown when a process times out. + * + * @author Johannes M. Schmitt + */ +class ProcessTimedOutException extends RuntimeException +{ + public const TYPE_GENERAL = 1; + public const TYPE_IDLE = 2; + + private $process; + private $timeoutType; + + public function __construct(Process $process, int $timeoutType) + { + $this->process = $process; + $this->timeoutType = $timeoutType; + + parent::__construct(sprintf( + 'The process "%s" exceeded the timeout of %s seconds.', + $process->getCommandLine(), + $this->getExceededTimeout() + )); + } + + public function getProcess() + { + return $this->process; + } + + public function isGeneralTimeout() + { + return self::TYPE_GENERAL === $this->timeoutType; + } + + public function isIdleTimeout() + { + return self::TYPE_IDLE === $this->timeoutType; + } + + public function getExceededTimeout() + { + switch ($this->timeoutType) { + case self::TYPE_GENERAL: + return $this->process->getTimeout(); + + case self::TYPE_IDLE: + return $this->process->getIdleTimeout(); + + default: + throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType)); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/RuntimeException.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/RuntimeException.php new file mode 100644 index 00000000..adead253 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Exception/RuntimeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +/** + * RuntimeException for the Process Component. + * + * @author Johannes M. Schmitt + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/ExecutableFinder.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/ExecutableFinder.php new file mode 100644 index 00000000..5914b4cd --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/ExecutableFinder.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +/** + * Generic executable finder. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class ExecutableFinder +{ + private $suffixes = ['.exe', '.bat', '.cmd', '.com']; + + /** + * Replaces default suffixes of executable. + */ + public function setSuffixes(array $suffixes) + { + $this->suffixes = $suffixes; + } + + /** + * Adds new possible suffix to check for executable. + */ + public function addSuffix(string $suffix) + { + $this->suffixes[] = $suffix; + } + + /** + * Finds an executable by name. + * + * @param string $name The executable name (without the extension) + * @param string|null $default The default to return if no executable is found + * @param array $extraDirs Additional dirs to check into + * + * @return string|null + */ + public function find(string $name, string $default = null, array $extraDirs = []) + { + if (ini_get('open_basedir')) { + $searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs); + $dirs = []; + foreach ($searchPath as $path) { + // Silencing against https://bugs.php.net/69240 + if (@is_dir($path)) { + $dirs[] = $path; + } else { + if (basename($path) == $name && @is_executable($path)) { + return $path; + } + } + } + } else { + $dirs = array_merge( + explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), + $extraDirs + ); + } + + $suffixes = ['']; + if ('\\' === \DIRECTORY_SEPARATOR) { + $pathExt = getenv('PATHEXT'); + $suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); + } + foreach ($suffixes as $suffix) { + foreach ($dirs as $dir) { + if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) { + return $file; + } + } + } + + return $default; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/InputStream.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/InputStream.php new file mode 100644 index 00000000..240665f3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/InputStream.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +use Symfony\Component\Process\Exception\RuntimeException; + +/** + * Provides a way to continuously write to the input of a Process until the InputStream is closed. + * + * @author Nicolas Grekas + * + * @implements \IteratorAggregate + */ +class InputStream implements \IteratorAggregate +{ + /** @var callable|null */ + private $onEmpty = null; + private $input = []; + private $open = true; + + /** + * Sets a callback that is called when the write buffer becomes empty. + */ + public function onEmpty(callable $onEmpty = null) + { + $this->onEmpty = $onEmpty; + } + + /** + * Appends an input to the write buffer. + * + * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar, + * stream resource or \Traversable + */ + public function write($input) + { + if (null === $input) { + return; + } + if ($this->isClosed()) { + throw new RuntimeException(sprintf('"%s" is closed.', static::class)); + } + $this->input[] = ProcessUtils::validateInput(__METHOD__, $input); + } + + /** + * Closes the write buffer. + */ + public function close() + { + $this->open = false; + } + + /** + * Tells whether the write buffer is closed or not. + */ + public function isClosed() + { + return !$this->open; + } + + /** + * @return \Traversable + */ + #[\ReturnTypeWillChange] + public function getIterator() + { + $this->open = true; + + while ($this->open || $this->input) { + if (!$this->input) { + yield ''; + continue; + } + $current = array_shift($this->input); + + if ($current instanceof \Iterator) { + yield from $current; + } else { + yield $current; + } + if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) { + $this->write($onEmpty($this)); + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/LICENSE b/wp-content/plugins/wp-webauthn/vendor/symfony/process/LICENSE new file mode 100644 index 00000000..88bf75bb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2022 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpExecutableFinder.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpExecutableFinder.php new file mode 100644 index 00000000..998808b6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpExecutableFinder.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +/** + * An executable finder specifically designed for the PHP executable. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class PhpExecutableFinder +{ + private $executableFinder; + + public function __construct() + { + $this->executableFinder = new ExecutableFinder(); + } + + /** + * Finds The PHP executable. + * + * @return string|false + */ + public function find(bool $includeArgs = true) + { + if ($php = getenv('PHP_BINARY')) { + if (!is_executable($php)) { + $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; + if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { + if (!is_executable($php)) { + return false; + } + } else { + return false; + } + } + + if (@is_dir($php)) { + return false; + } + + return $php; + } + + $args = $this->findArguments(); + $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; + + // PHP_BINARY return the current sapi executable + if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) { + return \PHP_BINARY.$args; + } + + if ($php = getenv('PHP_PATH')) { + if (!@is_executable($php) || @is_dir($php)) { + return false; + } + + return $php; + } + + if ($php = getenv('PHP_PEAR_PHP_BIN')) { + if (@is_executable($php) && !@is_dir($php)) { + return $php; + } + } + + if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php')) && !@is_dir($php)) { + return $php; + } + + $dirs = [\PHP_BINDIR]; + if ('\\' === \DIRECTORY_SEPARATOR) { + $dirs[] = 'C:\xampp\php\\'; + } + + return $this->executableFinder->find('php', false, $dirs); + } + + /** + * Finds the PHP executable arguments. + * + * @return array + */ + public function findArguments() + { + $arguments = []; + if ('phpdbg' === \PHP_SAPI) { + $arguments[] = '-qrr'; + } + + return $arguments; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpProcess.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpProcess.php new file mode 100644 index 00000000..2bc338e5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/PhpProcess.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +use Symfony\Component\Process\Exception\LogicException; +use Symfony\Component\Process\Exception\RuntimeException; + +/** + * PhpProcess runs a PHP script in an independent process. + * + * $p = new PhpProcess(''); + * $p->run(); + * print $p->getOutput()."\n"; + * + * @author Fabien Potencier + */ +class PhpProcess extends Process +{ + /** + * @param string $script The PHP script to run (as a string) + * @param string|null $cwd The working directory or null to use the working dir of the current PHP process + * @param array|null $env The environment variables or null to use the same environment as the current PHP process + * @param int $timeout The timeout in seconds + * @param array|null $php Path to the PHP binary to use with any additional arguments + */ + public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null) + { + if (null === $php) { + $executableFinder = new PhpExecutableFinder(); + $php = $executableFinder->find(false); + $php = false === $php ? null : array_merge([$php], $executableFinder->findArguments()); + } + if ('phpdbg' === \PHP_SAPI) { + $file = tempnam(sys_get_temp_dir(), 'dbg'); + file_put_contents($file, $script); + register_shutdown_function('unlink', $file); + $php[] = $file; + $script = null; + } + + parent::__construct($php, $cwd, $env, $script, $timeout); + } + + /** + * {@inheritdoc} + */ + public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) + { + throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class)); + } + + /** + * {@inheritdoc} + */ + public function start(callable $callback = null, array $env = []) + { + if (null === $this->getCommandLine()) { + throw new RuntimeException('Unable to find the PHP executable.'); + } + + parent::start($callback, $env); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/AbstractPipes.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/AbstractPipes.php new file mode 100644 index 00000000..01051005 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/AbstractPipes.php @@ -0,0 +1,180 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Pipes; + +use Symfony\Component\Process\Exception\InvalidArgumentException; + +/** + * @author Romain Neutron + * + * @internal + */ +abstract class AbstractPipes implements PipesInterface +{ + public $pipes = []; + + private $inputBuffer = ''; + private $input; + private $blocked = true; + private $lastError; + + /** + * @param resource|string|int|float|bool|\Iterator|null $input + */ + public function __construct($input) + { + if (\is_resource($input) || $input instanceof \Iterator) { + $this->input = $input; + } elseif (\is_string($input)) { + $this->inputBuffer = $input; + } else { + $this->inputBuffer = (string) $input; + } + } + + /** + * {@inheritdoc} + */ + public function close() + { + foreach ($this->pipes as $pipe) { + if (\is_resource($pipe)) { + fclose($pipe); + } + } + $this->pipes = []; + } + + /** + * Returns true if a system call has been interrupted. + */ + protected function hasSystemCallBeenInterrupted(): bool + { + $lastError = $this->lastError; + $this->lastError = null; + + // stream_select returns false when the `select` system call is interrupted by an incoming signal + return null !== $lastError && false !== stripos($lastError, 'interrupted system call'); + } + + /** + * Unblocks streams. + */ + protected function unblock() + { + if (!$this->blocked) { + return; + } + + foreach ($this->pipes as $pipe) { + stream_set_blocking($pipe, 0); + } + if (\is_resource($this->input)) { + stream_set_blocking($this->input, 0); + } + + $this->blocked = false; + } + + /** + * Writes input to stdin. + * + * @throws InvalidArgumentException When an input iterator yields a non supported value + */ + protected function write(): ?array + { + if (!isset($this->pipes[0])) { + return null; + } + $input = $this->input; + + if ($input instanceof \Iterator) { + if (!$input->valid()) { + $input = null; + } elseif (\is_resource($input = $input->current())) { + stream_set_blocking($input, 0); + } elseif (!isset($this->inputBuffer[0])) { + if (!\is_string($input)) { + if (!is_scalar($input)) { + throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input))); + } + $input = (string) $input; + } + $this->inputBuffer = $input; + $this->input->next(); + $input = null; + } else { + $input = null; + } + } + + $r = $e = []; + $w = [$this->pipes[0]]; + + // let's have a look if something changed in streams + if (false === @stream_select($r, $w, $e, 0, 0)) { + return null; + } + + foreach ($w as $stdin) { + if (isset($this->inputBuffer[0])) { + $written = fwrite($stdin, $this->inputBuffer); + $this->inputBuffer = substr($this->inputBuffer, $written); + if (isset($this->inputBuffer[0])) { + return [$this->pipes[0]]; + } + } + + if ($input) { + while (true) { + $data = fread($input, self::CHUNK_SIZE); + if (!isset($data[0])) { + break; + } + $written = fwrite($stdin, $data); + $data = substr($data, $written); + if (isset($data[0])) { + $this->inputBuffer = $data; + + return [$this->pipes[0]]; + } + } + if (feof($input)) { + if ($this->input instanceof \Iterator) { + $this->input->next(); + } else { + $this->input = null; + } + } + } + } + + // no input to read on resource, buffer is empty + if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) { + $this->input = null; + fclose($this->pipes[0]); + unset($this->pipes[0]); + } elseif (!$w) { + return [$this->pipes[0]]; + } + + return null; + } + + /** + * @internal + */ + public function handleError(int $type, string $msg) + { + $this->lastError = $msg; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/PipesInterface.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/PipesInterface.php new file mode 100644 index 00000000..50eb5c47 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/PipesInterface.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Pipes; + +/** + * PipesInterface manages descriptors and pipes for the use of proc_open. + * + * @author Romain Neutron + * + * @internal + */ +interface PipesInterface +{ + public const CHUNK_SIZE = 16384; + + /** + * Returns an array of descriptors for the use of proc_open. + */ + public function getDescriptors(): array; + + /** + * Returns an array of filenames indexed by their related stream in case these pipes use temporary files. + * + * @return string[] + */ + public function getFiles(): array; + + /** + * Reads data in file handles and pipes. + * + * @param bool $blocking Whether to use blocking calls or not + * @param bool $close Whether to close pipes if they've reached EOF + * + * @return string[] An array of read data indexed by their fd + */ + public function readAndWrite(bool $blocking, bool $close = false): array; + + /** + * Returns if the current state has open file handles or pipes. + */ + public function areOpen(): bool; + + /** + * Returns if pipes are able to read output. + */ + public function haveReadSupport(): bool; + + /** + * Closes file handles and pipes. + */ + public function close(); +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/UnixPipes.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/UnixPipes.php new file mode 100644 index 00000000..5a0e9d47 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/UnixPipes.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Pipes; + +use Symfony\Component\Process\Process; + +/** + * UnixPipes implementation uses unix pipes as handles. + * + * @author Romain Neutron + * + * @internal + */ +class UnixPipes extends AbstractPipes +{ + private $ttyMode; + private $ptyMode; + private $haveReadSupport; + + public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport) + { + $this->ttyMode = $ttyMode; + $this->ptyMode = $ptyMode; + $this->haveReadSupport = $haveReadSupport; + + parent::__construct($input); + } + + public function __sleep(): array + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + $this->close(); + } + + /** + * {@inheritdoc} + */ + public function getDescriptors(): array + { + if (!$this->haveReadSupport) { + $nullstream = fopen('/dev/null', 'c'); + + return [ + ['pipe', 'r'], + $nullstream, + $nullstream, + ]; + } + + if ($this->ttyMode) { + return [ + ['file', '/dev/tty', 'r'], + ['file', '/dev/tty', 'w'], + ['file', '/dev/tty', 'w'], + ]; + } + + if ($this->ptyMode && Process::isPtySupported()) { + return [ + ['pty'], + ['pty'], + ['pty'], + ]; + } + + return [ + ['pipe', 'r'], + ['pipe', 'w'], // stdout + ['pipe', 'w'], // stderr + ]; + } + + /** + * {@inheritdoc} + */ + public function getFiles(): array + { + return []; + } + + /** + * {@inheritdoc} + */ + public function readAndWrite(bool $blocking, bool $close = false): array + { + $this->unblock(); + $w = $this->write(); + + $read = $e = []; + $r = $this->pipes; + unset($r[0]); + + // let's have a look if something changed in streams + set_error_handler([$this, 'handleError']); + if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { + restore_error_handler(); + // if a system call has been interrupted, forget about it, let's try again + // otherwise, an error occurred, let's reset pipes + if (!$this->hasSystemCallBeenInterrupted()) { + $this->pipes = []; + } + + return $read; + } + restore_error_handler(); + + foreach ($r as $pipe) { + // prior PHP 5.4 the array passed to stream_select is modified and + // lose key association, we have to find back the key + $read[$type = array_search($pipe, $this->pipes, true)] = ''; + + do { + $data = @fread($pipe, self::CHUNK_SIZE); + $read[$type] .= $data; + } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1]))); + + if (!isset($read[$type][0])) { + unset($read[$type]); + } + + if ($close && feof($pipe)) { + fclose($pipe); + unset($this->pipes[$type]); + } + } + + return $read; + } + + /** + * {@inheritdoc} + */ + public function haveReadSupport(): bool + { + return $this->haveReadSupport; + } + + /** + * {@inheritdoc} + */ + public function areOpen(): bool + { + return (bool) $this->pipes; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/WindowsPipes.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/WindowsPipes.php new file mode 100644 index 00000000..bca84f57 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Pipes/WindowsPipes.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Pipes; + +use Symfony\Component\Process\Exception\RuntimeException; +use Symfony\Component\Process\Process; + +/** + * WindowsPipes implementation uses temporary files as handles. + * + * @see https://bugs.php.net/51800 + * @see https://bugs.php.net/65650 + * + * @author Romain Neutron + * + * @internal + */ +class WindowsPipes extends AbstractPipes +{ + private $files = []; + private $fileHandles = []; + private $lockHandles = []; + private $readBytes = [ + Process::STDOUT => 0, + Process::STDERR => 0, + ]; + private $haveReadSupport; + + public function __construct($input, bool $haveReadSupport) + { + $this->haveReadSupport = $haveReadSupport; + + if ($this->haveReadSupport) { + // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. + // Workaround for this problem is to use temporary files instead of pipes on Windows platform. + // + // @see https://bugs.php.net/51800 + $pipes = [ + Process::STDOUT => Process::OUT, + Process::STDERR => Process::ERR, + ]; + $tmpDir = sys_get_temp_dir(); + $lastError = 'unknown reason'; + set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; }); + for ($i = 0;; ++$i) { + foreach ($pipes as $pipe => $name) { + $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name); + + if (!$h = fopen($file.'.lock', 'w')) { + if (file_exists($file.'.lock')) { + continue 2; + } + restore_error_handler(); + throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError); + } + if (!flock($h, \LOCK_EX | \LOCK_NB)) { + continue 2; + } + if (isset($this->lockHandles[$pipe])) { + flock($this->lockHandles[$pipe], \LOCK_UN); + fclose($this->lockHandles[$pipe]); + } + $this->lockHandles[$pipe] = $h; + + if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) { + flock($this->lockHandles[$pipe], \LOCK_UN); + fclose($this->lockHandles[$pipe]); + unset($this->lockHandles[$pipe]); + continue 2; + } + $this->fileHandles[$pipe] = $h; + $this->files[$pipe] = $file; + } + break; + } + restore_error_handler(); + } + + parent::__construct($input); + } + + public function __sleep(): array + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + $this->close(); + } + + /** + * {@inheritdoc} + */ + public function getDescriptors(): array + { + if (!$this->haveReadSupport) { + $nullstream = fopen('NUL', 'c'); + + return [ + ['pipe', 'r'], + $nullstream, + $nullstream, + ]; + } + + // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800) + // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650 + // So we redirect output within the commandline and pass the nul device to the process + return [ + ['pipe', 'r'], + ['file', 'NUL', 'w'], + ['file', 'NUL', 'w'], + ]; + } + + /** + * {@inheritdoc} + */ + public function getFiles(): array + { + return $this->files; + } + + /** + * {@inheritdoc} + */ + public function readAndWrite(bool $blocking, bool $close = false): array + { + $this->unblock(); + $w = $this->write(); + $read = $r = $e = []; + + if ($blocking) { + if ($w) { + @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); + } elseif ($this->fileHandles) { + usleep(Process::TIMEOUT_PRECISION * 1E6); + } + } + foreach ($this->fileHandles as $type => $fileHandle) { + $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]); + + if (isset($data[0])) { + $this->readBytes[$type] += \strlen($data); + $read[$type] = $data; + } + if ($close) { + ftruncate($fileHandle, 0); + fclose($fileHandle); + flock($this->lockHandles[$type], \LOCK_UN); + fclose($this->lockHandles[$type]); + unset($this->fileHandles[$type], $this->lockHandles[$type]); + } + } + + return $read; + } + + /** + * {@inheritdoc} + */ + public function haveReadSupport(): bool + { + return $this->haveReadSupport; + } + + /** + * {@inheritdoc} + */ + public function areOpen(): bool + { + return $this->pipes && $this->fileHandles; + } + + /** + * {@inheritdoc} + */ + public function close() + { + parent::close(); + foreach ($this->fileHandles as $type => $handle) { + ftruncate($handle, 0); + fclose($handle); + flock($this->lockHandles[$type], \LOCK_UN); + fclose($this->lockHandles[$type]); + } + $this->fileHandles = $this->lockHandles = []; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/Process.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Process.php new file mode 100644 index 00000000..14e17774 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/Process.php @@ -0,0 +1,1652 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +use Symfony\Component\Process\Exception\InvalidArgumentException; +use Symfony\Component\Process\Exception\LogicException; +use Symfony\Component\Process\Exception\ProcessFailedException; +use Symfony\Component\Process\Exception\ProcessSignaledException; +use Symfony\Component\Process\Exception\ProcessTimedOutException; +use Symfony\Component\Process\Exception\RuntimeException; +use Symfony\Component\Process\Pipes\PipesInterface; +use Symfony\Component\Process\Pipes\UnixPipes; +use Symfony\Component\Process\Pipes\WindowsPipes; + +/** + * Process is a thin wrapper around proc_* functions to easily + * start independent PHP processes. + * + * @author Fabien Potencier + * @author Romain Neutron + * + * @implements \IteratorAggregate + */ +class Process implements \IteratorAggregate +{ + public const ERR = 'err'; + public const OUT = 'out'; + + public const STATUS_READY = 'ready'; + public const STATUS_STARTED = 'started'; + public const STATUS_TERMINATED = 'terminated'; + + public const STDIN = 0; + public const STDOUT = 1; + public const STDERR = 2; + + // Timeout Precision in seconds. + public const TIMEOUT_PRECISION = 0.2; + + public const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking + public const ITER_KEEP_OUTPUT = 2; // By default, outputs are cleared while iterating, use this flag to keep them in memory + public const ITER_SKIP_OUT = 4; // Use this flag to skip STDOUT while iterating + public const ITER_SKIP_ERR = 8; // Use this flag to skip STDERR while iterating + + private $callback; + private $hasCallback = false; + private $commandline; + private $cwd; + private $env = []; + private $input; + private $starttime; + private $lastOutputTime; + private $timeout; + private $idleTimeout; + private $exitcode; + private $fallbackStatus = []; + private $processInformation; + private $outputDisabled = false; + private $stdout; + private $stderr; + private $process; + private $status = self::STATUS_READY; + private $incrementalOutputOffset = 0; + private $incrementalErrorOutputOffset = 0; + private $tty = false; + private $pty; + private $options = ['suppress_errors' => true, 'bypass_shell' => true]; + + private $useFileHandles = false; + /** @var PipesInterface */ + private $processPipes; + + private $latestSignal; + + private static $sigchild; + + /** + * Exit codes translation table. + * + * User-defined errors must use exit codes in the 64-113 range. + */ + public static $exitCodes = [ + 0 => 'OK', + 1 => 'General error', + 2 => 'Misuse of shell builtins', + + 126 => 'Invoked command cannot execute', + 127 => 'Command not found', + 128 => 'Invalid exit argument', + + // signals + 129 => 'Hangup', + 130 => 'Interrupt', + 131 => 'Quit and dump core', + 132 => 'Illegal instruction', + 133 => 'Trace/breakpoint trap', + 134 => 'Process aborted', + 135 => 'Bus error: "access to undefined portion of memory object"', + 136 => 'Floating point exception: "erroneous arithmetic operation"', + 137 => 'Kill (terminate immediately)', + 138 => 'User-defined 1', + 139 => 'Segmentation violation', + 140 => 'User-defined 2', + 141 => 'Write to pipe with no one reading', + 142 => 'Signal raised by alarm', + 143 => 'Termination (request to terminate)', + // 144 - not defined + 145 => 'Child process terminated, stopped (or continued*)', + 146 => 'Continue if stopped', + 147 => 'Stop executing temporarily', + 148 => 'Terminal stop signal', + 149 => 'Background process attempting to read from tty ("in")', + 150 => 'Background process attempting to write to tty ("out")', + 151 => 'Urgent data available on socket', + 152 => 'CPU time limit exceeded', + 153 => 'File size limit exceeded', + 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"', + 155 => 'Profiling timer expired', + // 156 - not defined + 157 => 'Pollable event', + // 158 - not defined + 159 => 'Bad syscall', + ]; + + /** + * @param array $command The command to run and its arguments listed as separate entries + * @param string|null $cwd The working directory or null to use the working dir of the current PHP process + * @param array|null $env The environment variables or null to use the same environment as the current PHP process + * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input + * @param int|float|null $timeout The timeout in seconds or null to disable + * + * @throws LogicException When proc_open is not installed + */ + public function __construct(array $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) + { + if (!\function_exists('proc_open')) { + throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.'); + } + + $this->commandline = $command; + $this->cwd = $cwd; + + // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started + // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected + // @see : https://bugs.php.net/51800 + // @see : https://bugs.php.net/50524 + if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) { + $this->cwd = getcwd(); + } + if (null !== $env) { + $this->setEnv($env); + } + + $this->setInput($input); + $this->setTimeout($timeout); + $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR; + $this->pty = false; + } + + /** + * Creates a Process instance as a command-line to be run in a shell wrapper. + * + * Command-lines are parsed by the shell of your OS (/bin/sh on Unix-like, cmd.exe on Windows.) + * This allows using e.g. pipes or conditional execution. In this mode, signals are sent to the + * shell wrapper and not to your commands. + * + * In order to inject dynamic values into command-lines, we strongly recommend using placeholders. + * This will save escaping values, which is not portable nor secure anyway: + * + * $process = Process::fromShellCommandline('my_command "${:MY_VAR}"'); + * $process->run(null, ['MY_VAR' => $theValue]); + * + * @param string $command The command line to pass to the shell of the OS + * @param string|null $cwd The working directory or null to use the working dir of the current PHP process + * @param array|null $env The environment variables or null to use the same environment as the current PHP process + * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input + * @param int|float|null $timeout The timeout in seconds or null to disable + * + * @return static + * + * @throws LogicException When proc_open is not installed + */ + public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) + { + $process = new static([], $cwd, $env, $input, $timeout); + $process->commandline = $command; + + return $process; + } + + /** + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + if ($this->options['create_new_console'] ?? false) { + $this->processPipes->close(); + } else { + $this->stop(0); + } + } + + public function __clone() + { + $this->resetProcessData(); + } + + /** + * Runs the process. + * + * The callback receives the type of output (out or err) and + * some bytes from the output in real-time. It allows to have feedback + * from the independent process during execution. + * + * The STDOUT and STDERR are also available after the process is finished + * via the getOutput() and getErrorOutput() methods. + * + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * + * @return int The exit status code + * + * @throws RuntimeException When process can't be launched + * @throws RuntimeException When process is already running + * @throws ProcessTimedOutException When process timed out + * @throws ProcessSignaledException When process stopped after receiving signal + * @throws LogicException In case a callback is provided and output has been disabled + * + * @final + */ + public function run(callable $callback = null, array $env = []): int + { + $this->start($callback, $env); + + return $this->wait(); + } + + /** + * Runs the process. + * + * This is identical to run() except that an exception is thrown if the process + * exits with a non-zero exit code. + * + * @return $this + * + * @throws ProcessFailedException if the process didn't terminate successfully + * + * @final + */ + public function mustRun(callable $callback = null, array $env = []): self + { + if (0 !== $this->run($callback, $env)) { + throw new ProcessFailedException($this); + } + + return $this; + } + + /** + * Starts the process and returns after writing the input to STDIN. + * + * This method blocks until all STDIN data is sent to the process then it + * returns while the process runs in the background. + * + * The termination of the process can be awaited with wait(). + * + * The callback receives the type of output (out or err) and some bytes from + * the output in real-time while writing the standard input to the process. + * It allows to have feedback from the independent process during execution. + * + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * + * @throws RuntimeException When process can't be launched + * @throws RuntimeException When process is already running + * @throws LogicException In case a callback is provided and output has been disabled + */ + public function start(callable $callback = null, array $env = []) + { + if ($this->isRunning()) { + throw new RuntimeException('Process is already running.'); + } + + $this->resetProcessData(); + $this->starttime = $this->lastOutputTime = microtime(true); + $this->callback = $this->buildCallback($callback); + $this->hasCallback = null !== $callback; + $descriptors = $this->getDescriptors(); + + if ($this->env) { + $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env; + } + + $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv(); + + if (\is_array($commandline = $this->commandline)) { + $commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline)); + + if ('\\' !== \DIRECTORY_SEPARATOR) { + // exec is mandatory to deal with sending a signal to the process + $commandline = 'exec '.$commandline; + } + } else { + $commandline = $this->replacePlaceholders($commandline, $env); + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $commandline = $this->prepareWindowsCommandLine($commandline, $env); + } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) { + // last exit code is output on the fourth pipe and caught to work around --enable-sigchild + $descriptors[3] = ['pipe', 'w']; + + // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input + $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;'; + $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code'; + + // Workaround for the bug, when PTS functionality is enabled. + // @see : https://bugs.php.net/69442 + $ptsWorkaround = fopen(__FILE__, 'r'); + } + + $envPairs = []; + foreach ($env as $k => $v) { + if (false !== $v && false === \in_array($k, ['argc', 'argv', 'ARGC', 'ARGV'], true)) { + $envPairs[] = $k.'='.$v; + } + } + + if (!is_dir($this->cwd)) { + throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd)); + } + + $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); + + if (!\is_resource($this->process)) { + throw new RuntimeException('Unable to launch a new process.'); + } + $this->status = self::STATUS_STARTED; + + if (isset($descriptors[3])) { + $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]); + } + + if ($this->tty) { + return; + } + + $this->updateStatus(false); + $this->checkTimeout(); + } + + /** + * Restarts the process. + * + * Be warned that the process is cloned before being started. + * + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * + * @return static + * + * @throws RuntimeException When process can't be launched + * @throws RuntimeException When process is already running + * + * @see start() + * + * @final + */ + public function restart(callable $callback = null, array $env = []): self + { + if ($this->isRunning()) { + throw new RuntimeException('Process is already running.'); + } + + $process = clone $this; + $process->start($callback, $env); + + return $process; + } + + /** + * Waits for the process to terminate. + * + * The callback receives the type of output (out or err) and some bytes + * from the output in real-time while writing the standard input to the process. + * It allows to have feedback from the independent process during execution. + * + * @param callable|null $callback A valid PHP callback + * + * @return int The exitcode of the process + * + * @throws ProcessTimedOutException When process timed out + * @throws ProcessSignaledException When process stopped after receiving signal + * @throws LogicException When process is not yet started + */ + public function wait(callable $callback = null) + { + $this->requireProcessIsStarted(__FUNCTION__); + + $this->updateStatus(false); + + if (null !== $callback) { + if (!$this->processPipes->haveReadSupport()) { + $this->stop(0); + throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait".'); + } + $this->callback = $this->buildCallback($callback); + } + + do { + $this->checkTimeout(); + $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); + $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); + } while ($running); + + while ($this->isRunning()) { + $this->checkTimeout(); + usleep(1000); + } + + if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) { + throw new ProcessSignaledException($this); + } + + return $this->exitcode; + } + + /** + * Waits until the callback returns true. + * + * The callback receives the type of output (out or err) and some bytes + * from the output in real-time while writing the standard input to the process. + * It allows to have feedback from the independent process during execution. + * + * @throws RuntimeException When process timed out + * @throws LogicException When process is not yet started + * @throws ProcessTimedOutException In case the timeout was reached + */ + public function waitUntil(callable $callback): bool + { + $this->requireProcessIsStarted(__FUNCTION__); + $this->updateStatus(false); + + if (!$this->processPipes->haveReadSupport()) { + $this->stop(0); + throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::waitUntil".'); + } + $callback = $this->buildCallback($callback); + + $ready = false; + while (true) { + $this->checkTimeout(); + $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); + $output = $this->processPipes->readAndWrite($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); + + foreach ($output as $type => $data) { + if (3 !== $type) { + $ready = $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data) || $ready; + } elseif (!isset($this->fallbackStatus['signaled'])) { + $this->fallbackStatus['exitcode'] = (int) $data; + } + } + if ($ready) { + return true; + } + if (!$running) { + return false; + } + + usleep(1000); + } + } + + /** + * Returns the Pid (process identifier), if applicable. + * + * @return int|null The process id if running, null otherwise + */ + public function getPid() + { + return $this->isRunning() ? $this->processInformation['pid'] : null; + } + + /** + * Sends a POSIX signal to the process. + * + * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants) + * + * @return $this + * + * @throws LogicException In case the process is not running + * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed + * @throws RuntimeException In case of failure + */ + public function signal(int $signal) + { + $this->doSignal($signal, true); + + return $this; + } + + /** + * Disables fetching output and error output from the underlying process. + * + * @return $this + * + * @throws RuntimeException In case the process is already running + * @throws LogicException if an idle timeout is set + */ + public function disableOutput() + { + if ($this->isRunning()) { + throw new RuntimeException('Disabling output while the process is running is not possible.'); + } + if (null !== $this->idleTimeout) { + throw new LogicException('Output cannot be disabled while an idle timeout is set.'); + } + + $this->outputDisabled = true; + + return $this; + } + + /** + * Enables fetching output and error output from the underlying process. + * + * @return $this + * + * @throws RuntimeException In case the process is already running + */ + public function enableOutput() + { + if ($this->isRunning()) { + throw new RuntimeException('Enabling output while the process is running is not possible.'); + } + + $this->outputDisabled = false; + + return $this; + } + + /** + * Returns true in case the output is disabled, false otherwise. + * + * @return bool + */ + public function isOutputDisabled() + { + return $this->outputDisabled; + } + + /** + * Returns the current output of the process (STDOUT). + * + * @return string + * + * @throws LogicException in case the output has been disabled + * @throws LogicException In case the process is not started + */ + public function getOutput() + { + $this->readPipesForOutput(__FUNCTION__); + + if (false === $ret = stream_get_contents($this->stdout, -1, 0)) { + return ''; + } + + return $ret; + } + + /** + * Returns the output incrementally. + * + * In comparison with the getOutput method which always return the whole + * output, this one returns the new output since the last call. + * + * @return string + * + * @throws LogicException in case the output has been disabled + * @throws LogicException In case the process is not started + */ + public function getIncrementalOutput() + { + $this->readPipesForOutput(__FUNCTION__); + + $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset); + $this->incrementalOutputOffset = ftell($this->stdout); + + if (false === $latest) { + return ''; + } + + return $latest; + } + + /** + * Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR). + * + * @param int $flags A bit field of Process::ITER_* flags + * + * @throws LogicException in case the output has been disabled + * @throws LogicException In case the process is not started + * + * @return \Generator + */ + #[\ReturnTypeWillChange] + public function getIterator(int $flags = 0) + { + $this->readPipesForOutput(__FUNCTION__, false); + + $clearOutput = !(self::ITER_KEEP_OUTPUT & $flags); + $blocking = !(self::ITER_NON_BLOCKING & $flags); + $yieldOut = !(self::ITER_SKIP_OUT & $flags); + $yieldErr = !(self::ITER_SKIP_ERR & $flags); + + while (null !== $this->callback || ($yieldOut && !feof($this->stdout)) || ($yieldErr && !feof($this->stderr))) { + if ($yieldOut) { + $out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset); + + if (isset($out[0])) { + if ($clearOutput) { + $this->clearOutput(); + } else { + $this->incrementalOutputOffset = ftell($this->stdout); + } + + yield self::OUT => $out; + } + } + + if ($yieldErr) { + $err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset); + + if (isset($err[0])) { + if ($clearOutput) { + $this->clearErrorOutput(); + } else { + $this->incrementalErrorOutputOffset = ftell($this->stderr); + } + + yield self::ERR => $err; + } + } + + if (!$blocking && !isset($out[0]) && !isset($err[0])) { + yield self::OUT => ''; + } + + $this->checkTimeout(); + $this->readPipesForOutput(__FUNCTION__, $blocking); + } + } + + /** + * Clears the process output. + * + * @return $this + */ + public function clearOutput() + { + ftruncate($this->stdout, 0); + fseek($this->stdout, 0); + $this->incrementalOutputOffset = 0; + + return $this; + } + + /** + * Returns the current error output of the process (STDERR). + * + * @return string + * + * @throws LogicException in case the output has been disabled + * @throws LogicException In case the process is not started + */ + public function getErrorOutput() + { + $this->readPipesForOutput(__FUNCTION__); + + if (false === $ret = stream_get_contents($this->stderr, -1, 0)) { + return ''; + } + + return $ret; + } + + /** + * Returns the errorOutput incrementally. + * + * In comparison with the getErrorOutput method which always return the + * whole error output, this one returns the new error output since the last + * call. + * + * @return string + * + * @throws LogicException in case the output has been disabled + * @throws LogicException In case the process is not started + */ + public function getIncrementalErrorOutput() + { + $this->readPipesForOutput(__FUNCTION__); + + $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset); + $this->incrementalErrorOutputOffset = ftell($this->stderr); + + if (false === $latest) { + return ''; + } + + return $latest; + } + + /** + * Clears the process output. + * + * @return $this + */ + public function clearErrorOutput() + { + ftruncate($this->stderr, 0); + fseek($this->stderr, 0); + $this->incrementalErrorOutputOffset = 0; + + return $this; + } + + /** + * Returns the exit code returned by the process. + * + * @return int|null The exit status code, null if the Process is not terminated + */ + public function getExitCode() + { + $this->updateStatus(false); + + return $this->exitcode; + } + + /** + * Returns a string representation for the exit code returned by the process. + * + * This method relies on the Unix exit code status standardization + * and might not be relevant for other operating systems. + * + * @return string|null A string representation for the exit status code, null if the Process is not terminated + * + * @see http://tldp.org/LDP/abs/html/exitcodes.html + * @see http://en.wikipedia.org/wiki/Unix_signal + */ + public function getExitCodeText() + { + if (null === $exitcode = $this->getExitCode()) { + return null; + } + + return self::$exitCodes[$exitcode] ?? 'Unknown error'; + } + + /** + * Checks if the process ended successfully. + * + * @return bool + */ + public function isSuccessful() + { + return 0 === $this->getExitCode(); + } + + /** + * Returns true if the child process has been terminated by an uncaught signal. + * + * It always returns false on Windows. + * + * @return bool + * + * @throws LogicException In case the process is not terminated + */ + public function hasBeenSignaled() + { + $this->requireProcessIsTerminated(__FUNCTION__); + + return $this->processInformation['signaled']; + } + + /** + * Returns the number of the signal that caused the child process to terminate its execution. + * + * It is only meaningful if hasBeenSignaled() returns true. + * + * @return int + * + * @throws RuntimeException In case --enable-sigchild is activated + * @throws LogicException In case the process is not terminated + */ + public function getTermSignal() + { + $this->requireProcessIsTerminated(__FUNCTION__); + + if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) { + throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.'); + } + + return $this->processInformation['termsig']; + } + + /** + * Returns true if the child process has been stopped by a signal. + * + * It always returns false on Windows. + * + * @return bool + * + * @throws LogicException In case the process is not terminated + */ + public function hasBeenStopped() + { + $this->requireProcessIsTerminated(__FUNCTION__); + + return $this->processInformation['stopped']; + } + + /** + * Returns the number of the signal that caused the child process to stop its execution. + * + * It is only meaningful if hasBeenStopped() returns true. + * + * @return int + * + * @throws LogicException In case the process is not terminated + */ + public function getStopSignal() + { + $this->requireProcessIsTerminated(__FUNCTION__); + + return $this->processInformation['stopsig']; + } + + /** + * Checks if the process is currently running. + * + * @return bool + */ + public function isRunning() + { + if (self::STATUS_STARTED !== $this->status) { + return false; + } + + $this->updateStatus(false); + + return $this->processInformation['running']; + } + + /** + * Checks if the process has been started with no regard to the current state. + * + * @return bool + */ + public function isStarted() + { + return self::STATUS_READY != $this->status; + } + + /** + * Checks if the process is terminated. + * + * @return bool + */ + public function isTerminated() + { + $this->updateStatus(false); + + return self::STATUS_TERMINATED == $this->status; + } + + /** + * Gets the process status. + * + * The status is one of: ready, started, terminated. + * + * @return string + */ + public function getStatus() + { + $this->updateStatus(false); + + return $this->status; + } + + /** + * Stops the process. + * + * @param int|float $timeout The timeout in seconds + * @param int $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) + * + * @return int|null The exit-code of the process or null if it's not running + */ + public function stop(float $timeout = 10, int $signal = null) + { + $timeoutMicro = microtime(true) + $timeout; + if ($this->isRunning()) { + // given SIGTERM may not be defined and that "proc_terminate" uses the constant value and not the constant itself, we use the same here + $this->doSignal(15, false); + do { + usleep(1000); + } while ($this->isRunning() && microtime(true) < $timeoutMicro); + + if ($this->isRunning()) { + // Avoid exception here: process is supposed to be running, but it might have stopped just + // after this line. In any case, let's silently discard the error, we cannot do anything. + $this->doSignal($signal ?: 9, false); + } + } + + if ($this->isRunning()) { + if (isset($this->fallbackStatus['pid'])) { + unset($this->fallbackStatus['pid']); + + return $this->stop(0, $signal); + } + $this->close(); + } + + return $this->exitcode; + } + + /** + * Adds a line to the STDOUT stream. + * + * @internal + */ + public function addOutput(string $line) + { + $this->lastOutputTime = microtime(true); + + fseek($this->stdout, 0, \SEEK_END); + fwrite($this->stdout, $line); + fseek($this->stdout, $this->incrementalOutputOffset); + } + + /** + * Adds a line to the STDERR stream. + * + * @internal + */ + public function addErrorOutput(string $line) + { + $this->lastOutputTime = microtime(true); + + fseek($this->stderr, 0, \SEEK_END); + fwrite($this->stderr, $line); + fseek($this->stderr, $this->incrementalErrorOutputOffset); + } + + /** + * Gets the last output time in seconds. + */ + public function getLastOutputTime(): ?float + { + return $this->lastOutputTime; + } + + /** + * Gets the command line to be executed. + * + * @return string + */ + public function getCommandLine() + { + return \is_array($this->commandline) ? implode(' ', array_map([$this, 'escapeArgument'], $this->commandline)) : $this->commandline; + } + + /** + * Gets the process timeout in seconds (max. runtime). + * + * @return float|null + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * Gets the process idle timeout in seconds (max. time since last output). + * + * @return float|null + */ + public function getIdleTimeout() + { + return $this->idleTimeout; + } + + /** + * Sets the process timeout (max. runtime) in seconds. + * + * To disable the timeout, set this value to null. + * + * @return $this + * + * @throws InvalidArgumentException if the timeout is negative + */ + public function setTimeout(?float $timeout) + { + $this->timeout = $this->validateTimeout($timeout); + + return $this; + } + + /** + * Sets the process idle timeout (max. time since last output) in seconds. + * + * To disable the timeout, set this value to null. + * + * @return $this + * + * @throws LogicException if the output is disabled + * @throws InvalidArgumentException if the timeout is negative + */ + public function setIdleTimeout(?float $timeout) + { + if (null !== $timeout && $this->outputDisabled) { + throw new LogicException('Idle timeout cannot be set while the output is disabled.'); + } + + $this->idleTimeout = $this->validateTimeout($timeout); + + return $this; + } + + /** + * Enables or disables the TTY mode. + * + * @return $this + * + * @throws RuntimeException In case the TTY mode is not supported + */ + public function setTty(bool $tty) + { + if ('\\' === \DIRECTORY_SEPARATOR && $tty) { + throw new RuntimeException('TTY mode is not supported on Windows platform.'); + } + + if ($tty && !self::isTtySupported()) { + throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); + } + + $this->tty = $tty; + + return $this; + } + + /** + * Checks if the TTY mode is enabled. + * + * @return bool + */ + public function isTty() + { + return $this->tty; + } + + /** + * Sets PTY mode. + * + * @return $this + */ + public function setPty(bool $bool) + { + $this->pty = $bool; + + return $this; + } + + /** + * Returns PTY state. + * + * @return bool + */ + public function isPty() + { + return $this->pty; + } + + /** + * Gets the working directory. + * + * @return string|null + */ + public function getWorkingDirectory() + { + if (null === $this->cwd) { + // getcwd() will return false if any one of the parent directories does not have + // the readable or search mode set, even if the current directory does + return getcwd() ?: null; + } + + return $this->cwd; + } + + /** + * Sets the current working directory. + * + * @return $this + */ + public function setWorkingDirectory(string $cwd) + { + $this->cwd = $cwd; + + return $this; + } + + /** + * Gets the environment variables. + * + * @return array + */ + public function getEnv() + { + return $this->env; + } + + /** + * Sets the environment variables. + * + * @param array $env The new environment variables + * + * @return $this + */ + public function setEnv(array $env) + { + $this->env = $env; + + return $this; + } + + /** + * Gets the Process input. + * + * @return resource|string|\Iterator|null + */ + public function getInput() + { + return $this->input; + } + + /** + * Sets the input. + * + * This content will be passed to the underlying process standard input. + * + * @param string|int|float|bool|resource|\Traversable|null $input The content + * + * @return $this + * + * @throws LogicException In case the process is running + */ + public function setInput($input) + { + if ($this->isRunning()) { + throw new LogicException('Input cannot be set while the process is running.'); + } + + $this->input = ProcessUtils::validateInput(__METHOD__, $input); + + return $this; + } + + /** + * Performs a check between the timeout definition and the time the process started. + * + * In case you run a background process (with the start method), you should + * trigger this method regularly to ensure the process timeout + * + * @throws ProcessTimedOutException In case the timeout was reached + */ + public function checkTimeout() + { + if (self::STATUS_STARTED !== $this->status) { + return; + } + + if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { + $this->stop(0); + + throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); + } + + if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { + $this->stop(0); + + throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); + } + } + + /** + * @throws LogicException in case process is not started + */ + public function getStartTime(): float + { + if (!$this->isStarted()) { + throw new LogicException('Start time is only available after process start.'); + } + + return $this->starttime; + } + + /** + * Defines options to pass to the underlying proc_open(). + * + * @see https://php.net/proc_open for the options supported by PHP. + * + * Enabling the "create_new_console" option allows a subprocess to continue + * to run after the main process exited, on both Windows and *nix + */ + public function setOptions(array $options) + { + if ($this->isRunning()) { + throw new RuntimeException('Setting options while the process is running is not possible.'); + } + + $defaultOptions = $this->options; + $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console']; + + foreach ($options as $key => $value) { + if (!\in_array($key, $existingOptions)) { + $this->options = $defaultOptions; + throw new LogicException(sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions))); + } + $this->options[$key] = $value; + } + } + + /** + * Returns whether TTY is supported on the current operating system. + */ + public static function isTtySupported(): bool + { + static $isTtySupported; + + if (null === $isTtySupported) { + $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); + } + + return $isTtySupported; + } + + /** + * Returns whether PTY is supported on the current operating system. + * + * @return bool + */ + public static function isPtySupported() + { + static $result; + + if (null !== $result) { + return $result; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + return $result = false; + } + + return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes); + } + + /** + * Creates the descriptors needed by the proc_open. + */ + private function getDescriptors(): array + { + if ($this->input instanceof \Iterator) { + $this->input->rewind(); + } + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback); + } else { + $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback); + } + + return $this->processPipes->getDescriptors(); + } + + /** + * Builds up the callback used by wait(). + * + * The callbacks adds all occurred output to the specific buffer and calls + * the user callback (if present) with the received output. + * + * @param callable|null $callback The user defined PHP callback + * + * @return \Closure + */ + protected function buildCallback(callable $callback = null) + { + if ($this->outputDisabled) { + return function ($type, $data) use ($callback): bool { + return null !== $callback && $callback($type, $data); + }; + } + + $out = self::OUT; + + return function ($type, $data) use ($callback, $out): bool { + if ($out == $type) { + $this->addOutput($data); + } else { + $this->addErrorOutput($data); + } + + return null !== $callback && $callback($type, $data); + }; + } + + /** + * Updates the status of the process, reads pipes. + * + * @param bool $blocking Whether to use a blocking read call + */ + protected function updateStatus(bool $blocking) + { + if (self::STATUS_STARTED !== $this->status) { + return; + } + + $this->processInformation = proc_get_status($this->process); + $running = $this->processInformation['running']; + + $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running); + + if ($this->fallbackStatus && $this->isSigchildEnabled()) { + $this->processInformation = $this->fallbackStatus + $this->processInformation; + } + + if (!$running) { + $this->close(); + } + } + + /** + * Returns whether PHP has been compiled with the '--enable-sigchild' option or not. + * + * @return bool + */ + protected function isSigchildEnabled() + { + if (null !== self::$sigchild) { + return self::$sigchild; + } + + if (!\function_exists('phpinfo')) { + return self::$sigchild = false; + } + + ob_start(); + phpinfo(\INFO_GENERAL); + + return self::$sigchild = str_contains(ob_get_clean(), '--enable-sigchild'); + } + + /** + * Reads pipes for the freshest output. + * + * @param string $caller The name of the method that needs fresh outputs + * @param bool $blocking Whether to use blocking calls or not + * + * @throws LogicException in case output has been disabled or process is not started + */ + private function readPipesForOutput(string $caller, bool $blocking = false) + { + if ($this->outputDisabled) { + throw new LogicException('Output has been disabled.'); + } + + $this->requireProcessIsStarted($caller); + + $this->updateStatus($blocking); + } + + /** + * Validates and returns the filtered timeout. + * + * @throws InvalidArgumentException if the given timeout is a negative number + */ + private function validateTimeout(?float $timeout): ?float + { + $timeout = (float) $timeout; + + if (0.0 === $timeout) { + $timeout = null; + } elseif ($timeout < 0) { + throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); + } + + return $timeout; + } + + /** + * Reads pipes, executes callback. + * + * @param bool $blocking Whether to use blocking calls or not + * @param bool $close Whether to close file handles or not + */ + private function readPipes(bool $blocking, bool $close) + { + $result = $this->processPipes->readAndWrite($blocking, $close); + + $callback = $this->callback; + foreach ($result as $type => $data) { + if (3 !== $type) { + $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data); + } elseif (!isset($this->fallbackStatus['signaled'])) { + $this->fallbackStatus['exitcode'] = (int) $data; + } + } + } + + /** + * Closes process resource, closes file handles, sets the exitcode. + * + * @return int The exitcode + */ + private function close(): int + { + $this->processPipes->close(); + if (\is_resource($this->process)) { + proc_close($this->process); + } + $this->exitcode = $this->processInformation['exitcode']; + $this->status = self::STATUS_TERMINATED; + + if (-1 === $this->exitcode) { + if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { + // if process has been signaled, no exitcode but a valid termsig, apply Unix convention + $this->exitcode = 128 + $this->processInformation['termsig']; + } elseif ($this->isSigchildEnabled()) { + $this->processInformation['signaled'] = true; + $this->processInformation['termsig'] = -1; + } + } + + // Free memory from self-reference callback created by buildCallback + // Doing so in other contexts like __destruct or by garbage collector is ineffective + // Now pipes are closed, so the callback is no longer necessary + $this->callback = null; + + return $this->exitcode; + } + + /** + * Resets data related to the latest run of the process. + */ + private function resetProcessData() + { + $this->starttime = null; + $this->callback = null; + $this->exitcode = null; + $this->fallbackStatus = []; + $this->processInformation = null; + $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+'); + $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+'); + $this->process = null; + $this->latestSignal = null; + $this->status = self::STATUS_READY; + $this->incrementalOutputOffset = 0; + $this->incrementalErrorOutputOffset = 0; + } + + /** + * Sends a POSIX signal to the process. + * + * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants) + * @param bool $throwException Whether to throw exception in case signal failed + * + * @throws LogicException In case the process is not running + * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed + * @throws RuntimeException In case of failure + */ + private function doSignal(int $signal, bool $throwException): bool + { + if (null === $pid = $this->getPid()) { + if ($throwException) { + throw new LogicException('Cannot send signal on a non running process.'); + } + + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode); + if ($exitCode && $this->isRunning()) { + if ($throwException) { + throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output))); + } + + return false; + } + } else { + if (!$this->isSigchildEnabled()) { + $ok = @proc_terminate($this->process, $signal); + } elseif (\function_exists('posix_kill')) { + $ok = @posix_kill($pid, $signal); + } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) { + $ok = false === fgets($pipes[2]); + } + if (!$ok) { + if ($throwException) { + throw new RuntimeException(sprintf('Error while sending signal "%s".', $signal)); + } + + return false; + } + } + + $this->latestSignal = $signal; + $this->fallbackStatus['signaled'] = true; + $this->fallbackStatus['exitcode'] = -1; + $this->fallbackStatus['termsig'] = $this->latestSignal; + + return true; + } + + private function prepareWindowsCommandLine(string $cmd, array &$env): string + { + $uid = uniqid('', true); + $varCount = 0; + $varCache = []; + $cmd = preg_replace_callback( + '/"(?:( + [^"%!^]*+ + (?: + (?: !LF! | "(?:\^[%!^])?+" ) + [^"%!^]*+ + )++ + ) | [^"]*+ )"/x', + function ($m) use (&$env, &$varCache, &$varCount, $uid) { + if (!isset($m[1])) { + return $m[0]; + } + if (isset($varCache[$m[0]])) { + return $varCache[$m[0]]; + } + if (str_contains($value = $m[1], "\0")) { + $value = str_replace("\0", '?', $value); + } + if (false === strpbrk($value, "\"%!\n")) { + return '"'.$value.'"'; + } + + $value = str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value); + $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"'; + $var = $uid.++$varCount; + + $env[$var] = $value; + + return $varCache[$m[0]] = '!'.$var.'!'; + }, + $cmd + ); + + $cmd = 'cmd /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')'; + foreach ($this->processPipes->getFiles() as $offset => $filename) { + $cmd .= ' '.$offset.'>"'.$filename.'"'; + } + + return $cmd; + } + + /** + * Ensures the process is running or terminated, throws a LogicException if the process has a not started. + * + * @throws LogicException if the process has not run + */ + private function requireProcessIsStarted(string $functionName) + { + if (!$this->isStarted()) { + throw new LogicException(sprintf('Process must be started before calling "%s()".', $functionName)); + } + } + + /** + * Ensures the process is terminated, throws a LogicException if the process has a status different than "terminated". + * + * @throws LogicException if the process is not yet terminated + */ + private function requireProcessIsTerminated(string $functionName) + { + if (!$this->isTerminated()) { + throw new LogicException(sprintf('Process must be terminated before calling "%s()".', $functionName)); + } + } + + /** + * Escapes a string to be used as a shell argument. + */ + private function escapeArgument(?string $argument): string + { + if ('' === $argument || null === $argument) { + return '""'; + } + if ('\\' !== \DIRECTORY_SEPARATOR) { + return "'".str_replace("'", "'\\''", $argument)."'"; + } + if (str_contains($argument, "\0")) { + $argument = str_replace("\0", '?', $argument); + } + if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) { + return $argument; + } + $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument); + + return '"'.str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument).'"'; + } + + private function replacePlaceholders(string $commandline, array $env) + { + return preg_replace_callback('/"\$\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\}"/', function ($matches) use ($commandline, $env) { + if (!isset($env[$matches[1]]) || false === $env[$matches[1]]) { + throw new InvalidArgumentException(sprintf('Command line is missing a value for parameter "%s": ', $matches[1]).$commandline); + } + + return $this->escapeArgument($env[$matches[1]]); + }, $commandline); + } + + private function getDefaultEnv(): array + { + $env = getenv(); + $env = ('\\' === \DIRECTORY_SEPARATOR ? array_intersect_ukey($env, $_SERVER, 'strcasecmp') : array_intersect_key($env, $_SERVER)) ?: $env; + + return $_ENV + ('\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($env, $_ENV, 'strcasecmp') : $env); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/ProcessUtils.php b/wp-content/plugins/wp-webauthn/vendor/symfony/process/ProcessUtils.php new file mode 100644 index 00000000..6cc7a610 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/ProcessUtils.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +use Symfony\Component\Process\Exception\InvalidArgumentException; + +/** + * ProcessUtils is a bunch of utility methods. + * + * This class contains static methods only and is not meant to be instantiated. + * + * @author Martin Hasoň + */ +class ProcessUtils +{ + /** + * This class should not be instantiated. + */ + private function __construct() + { + } + + /** + * Validates and normalizes a Process input. + * + * @param string $caller The name of method call that validates the input + * @param mixed $input The input to validate + * + * @return mixed + * + * @throws InvalidArgumentException In case the input is not valid + */ + public static function validateInput(string $caller, $input) + { + if (null !== $input) { + if (\is_resource($input)) { + return $input; + } + if (\is_string($input)) { + return $input; + } + if (is_scalar($input)) { + return (string) $input; + } + if ($input instanceof Process) { + return $input->getIterator($input::ITER_SKIP_ERR); + } + if ($input instanceof \Iterator) { + return $input; + } + if ($input instanceof \Traversable) { + return new \IteratorIterator($input); + } + + throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller)); + } + + return $input; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/README.md b/wp-content/plugins/wp-webauthn/vendor/symfony/process/README.md new file mode 100644 index 00000000..8777de4a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/README.md @@ -0,0 +1,28 @@ +Process Component +================= + +The Process component executes commands in sub-processes. + +Sponsor +------- + +The Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2]. + +As the creator of Symfony, SensioLabs supports companies using Symfony, with an +offering encompassing consultancy, expertise, services, training, and technical +assistance to ensure the success of web application development projects. + +Help Symfony by [sponsoring][3] its development! + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/process.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://sensiolabs.com +[3]: https://symfony.com/sponsor diff --git a/wp-content/plugins/wp-webauthn/vendor/symfony/process/composer.json b/wp-content/plugins/wp-webauthn/vendor/symfony/process/composer.json new file mode 100644 index 00000000..1669eba5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/symfony/process/composer.json @@ -0,0 +1,29 @@ +{ + "name": "symfony/process", + "type": "library", + "description": "Executes commands in sub-processes", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Process\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/LICENSE b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/LICENSE new file mode 100644 index 00000000..4188a9bb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 TheCodingMachine + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/README.md b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/README.md new file mode 100644 index 00000000..3c2ee624 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/README.md @@ -0,0 +1,178 @@ +[![Latest Stable Version](https://poser.pugx.org/thecodingmachine/safe/v/stable.svg)](https://packagist.org/packages/thecodingmachine/safe) +[![Total Downloads](https://poser.pugx.org/thecodingmachine/safe/downloads.svg)](https://packagist.org/packages/thecodingmachine/safe) +[![Latest Unstable Version](https://poser.pugx.org/thecodingmachine/safe/v/unstable.svg)](https://packagist.org/packages/thecodingmachine/safe) +[![License](https://poser.pugx.org/thecodingmachine/safe/license.svg)](https://packagist.org/packages/thecodingmachine/safe) +[![Build Status](https://travis-ci.org/thecodingmachine/safe.svg?branch=master)](https://travis-ci.org/thecodingmachine/safe) +[![Continuous Integration](https://github.com/thecodingmachine/safe/workflows/Continuous%20Integration/badge.svg)](https://github.com/thecodingmachine/safe/actions) +[![codecov](https://codecov.io/gh/thecodingmachine/safe/branch/master/graph/badge.svg)](https://codecov.io/gh/thecodingmachine/safe) + +Safe PHP +======== + +**Work in progress** + +A set of core PHP functions rewritten to throw exceptions instead of returning `false` when an error is encountered. + +## The problem + +Most PHP core functions were written before exception handling was added to the language. Therefore, most PHP functions +do not throw exceptions. Instead, they return `false` in case of error. + +But most of us are too lazy to check explicitly for every single return of every core PHP function. + +```php +// This code is incorrect. Twice. +// "file_get_contents" can return false if the file does not exists +// "json_decode" can return false if the file content is not valid JSON +$content = file_get_contents('foobar.json'); +$foobar = json_decode($content); +``` + +The correct version of this code would be: + +```php +$content = file_get_contents('foobar.json'); +if ($content === false) { + throw new FileLoadingException('Could not load file foobar.json'); +} +$foobar = json_decode($content); +if (json_last_error() !== JSON_ERROR_NONE) { + throw new FileLoadingException('foobar.json does not contain valid JSON: '.json_last_error_msg()); +} +``` + +Obviously, while this snippet is correct, it is less easy to read. + +## The solution + +Enter *thecodingmachine/safe* aka Safe-PHP. + +Safe-PHP redeclares all core PHP functions. The new PHP functions act exactly as the old ones, except they +throw exceptions properly when an error is encountered. The "safe" functions have the same name as the core PHP +functions, except they are in the `Safe` namespace. + +```php +use function Safe\file_get_contents; +use function Safe\json_decode; + +// This code is both safe and simple! +$content = file_get_contents('foobar.json'); +$foobar = json_decode($content); +``` + +All PHP functions that can return `false` on error are part of Safe. +In addition, Safe also provide 2 'Safe' classes: `Safe\DateTime` and `Safe\DateTimeImmutable` whose methods will throw exceptions instead of returning false. + +## PHPStan integration + +> Yeah... but I must explicitly think about importing the "safe" variant of the function, for each and every file of my application. +> I'm sure I will forget some "use function" statements! + +Fear not! thecodingmachine/safe comes with a PHPStan rule. + +Never heard of [PHPStan](https://github.com/phpstan/phpstan) before? +Check it out, it's an amazing code analyzer for PHP. + +Simply install the Safe rule in your PHPStan setup (explained in the "Installation" section) and PHPStan will let you know each time you are using an "unsafe" function. + +The code below will trigger this warning: + +```php +$content = file_get_contents('foobar.json'); +``` + +> Function file_get_contents is unsafe to use. It can return FALSE instead of throwing an exception. Please add 'use function Safe\\file_get_contents;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library. + +## Installation + +Use composer to install Safe-PHP: + +```bash +$ composer require thecodingmachine/safe +``` + +*Highly recommended*: install PHPStan and PHPStan extension: + +```bash +$ composer require --dev thecodingmachine/phpstan-safe-rule +``` + +Now, edit your `phpstan.neon` file and add these rules: + +```yml +includes: + - vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon +``` + +## Automated refactoring + +You have a large legacy codebase and want to use "Safe-PHP" functions throughout your project? PHPStan will help you +find these functions but changing the namespace of the functions one function at a time might be a tedious task. + +Fortunately, Safe comes bundled with a "Rector" configuration file. [Rector](https://github.com/rectorphp/rector) is a command-line +tool that performs instant refactoring of your application. + +Run + +```bash +$ composer require --dev rector/rector:^0.7 +``` + +to install `rector/rector`. + +Run + +```bash +vendor/bin/rector process src/ --config vendor/thecodingmachine/safe/rector-migrate-0.7.php +``` + +to run `rector/rector`. + +*Note:* do not forget to replace "src/" with the path to your source directory. + +**Important:** the refactoring only performs a "dumb" replacement of functions. It will not modify the way +"false" return values are handled. So if your code was already performing error handling, you will have to deal +with it manually. + +Especially, you should look for error handling that was already performed, like: + +```php +if (!mkdir($dirPath)) { + // Do something on error +} +``` + +This code will be refactored by Rector to: + +```php +if (!\Safe\mkdir($dirPath)) { + // Do something on error +} +``` + +You should then (manually) refactor it to: + +```php +try { + \Safe\mkdir($dirPath)); +} catch (\Safe\FilesystemException $e) { + // Do something on error +} +``` + +## Performance impact + +Safe is loading 1000+ functions from ~85 files on each request. Yet, the performance impact of this loading is quite low. + +In case you worry, using Safe will "cost" you ~700µs on each request. The [performance section](performance/README.md) +contains more information regarding the way we tested the performance impact of Safe. + +## Learn more + +Read [the release article on TheCodingMachine's blog](https://thecodingmachine.io/introducing-safe-php) if you want to +learn more about what triggered the development of Safe-PHP. + +## Contributing + +The files that contain all the functions are auto-generated from the PHP doc. +Read the [CONTRIBUTING.md](CONTRIBUTING.md) file to learn how to regenerate these files and to contribute to this library. diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/composer.json b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/composer.json new file mode 100644 index 00000000..2cd03fcc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/composer.json @@ -0,0 +1,123 @@ +{ + "name": "thecodingmachine/safe", + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "license": "MIT", + "autoload": { + "psr-4": { + "Safe\\": [ + "lib/", + "deprecated/", + "generated/" + ] + }, + "files": [ + "deprecated/apc.php", + "deprecated/libevent.php", + "deprecated/mssql.php", + "deprecated/stats.php", + "lib/special_cases.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/ingres-ii.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/msql.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/mysqlndMs.php", + "generated/mysqlndQc.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/password.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pdf.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/simplexml.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ] + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "phpstan/phpstan": "^0.12", + "thecodingmachine/phpstan-strict-rules": "^0.12", + "squizlabs/php_codesniffer": "^3.2" + }, + "scripts": { + "phpstan": "phpstan analyse lib -c phpstan.neon --level=max --no-progress -vvv", + "cs-fix": "phpcbf", + "cs-check": "phpcs" + }, + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + } +} \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/Exceptions/ApcException.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/Exceptions/ApcException.php new file mode 100644 index 00000000..f344490d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/deprecated/Exceptions/ApcException.php @@ -0,0 +1,11 @@ + + * + * + * + * The mode parameter consists of three octal + * number components specifying access restrictions for the owner, + * the user group in which the owner is in, and to everybody else in + * this order. One component can be computed by adding up the needed + * permissions for that target user base. Number 1 means that you + * grant execute rights, number 2 means that you make the file + * writeable, number 4 means that you make the file readable. Add + * up these numbers to specify needed rights. You can also read more + * about modes on Unix systems with 'man 1 chmod' + * and 'man 2 chmod'. + * + * + * + * + */ +function chmod(string $filename, int $mode): void +{ + error_clear_last(); + $result = \chmod($filename, $mode); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Attempts to change the owner of the file filename + * to user user. Only the superuser may change the + * owner of a file. + * + * @param string $filename Path to the file. + * @param string|int $user A user name or number. + * @throws FilesystemException + * + */ +function chown(string $filename, $user): void +{ + error_clear_last(); + $result = \chown($filename, $user); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Makes a copy of the file source to + * dest. + * + * If you wish to move a file, use the rename function. + * + * @param string $source Path to the source file. + * @param string $dest The destination path. If dest is a URL, the + * copy operation may fail if the wrapper does not support overwriting of + * existing files. + * + * If the destination file already exists, it will be overwritten. + * @param resource $context A valid context resource created with + * stream_context_create. + * @throws FilesystemException + * + */ +function copy(string $source, string $dest, $context = null): void +{ + error_clear_last(); + if ($context !== null) { + $result = \copy($source, $dest, $context); + } else { + $result = \copy($source, $dest); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Given a string containing a directory, this function will return the + * number of bytes available on the corresponding filesystem or disk + * partition. + * + * @param string $directory A directory of the filesystem or disk partition. + * + * Given a file name instead of a directory, the behaviour of the + * function is unspecified and may differ between operating systems and + * PHP versions. + * @return float Returns the number of available bytes as a float. + * @throws FilesystemException + * + */ +function disk_free_space(string $directory): float +{ + error_clear_last(); + $result = \disk_free_space($directory); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Given a string containing a directory, this function will return the total + * number of bytes on the corresponding filesystem or disk partition. + * + * @param string $directory A directory of the filesystem or disk partition. + * @return float Returns the total number of bytes as a float. + * @throws FilesystemException + * + */ +function disk_total_space(string $directory): float +{ + error_clear_last(); + $result = \disk_total_space($directory); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * The file pointed to by handle is closed. + * + * @param resource $handle The file pointer must be valid, and must point to a file successfully + * opened by fopen or fsockopen. + * @throws FilesystemException + * + */ +function fclose($handle): void +{ + error_clear_last(); + $result = \fclose($handle); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * This function forces a write of all buffered output to the resource + * pointed to by the file handle. + * + * @param resource $handle The file pointer must be valid, and must point to + * a file successfully opened by fopen or + * fsockopen (and not yet closed by + * fclose). + * @throws FilesystemException + * + */ +function fflush($handle): void +{ + error_clear_last(); + $result = \fflush($handle); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * This function is similar to file, except that + * file_get_contents returns the file in a + * string, starting at the specified offset + * up to maxlen bytes. On failure, + * file_get_contents will return FALSE. + * + * file_get_contents is the preferred way to read the + * contents of a file into a string. It will use memory mapping techniques if + * supported by your OS to enhance performance. + * + * @param string $filename Name of the file to read. + * @param bool $use_include_path The FILE_USE_INCLUDE_PATH constant can be used + * to trigger include path + * search. + * This is not possible if strict typing + * is enabled, since FILE_USE_INCLUDE_PATH is an + * int. Use TRUE instead. + * @param resource|null $context A valid context resource created with + * stream_context_create. If you don't need to use a + * custom context, you can skip this parameter by NULL. + * @param int $offset The offset where the reading starts on the original stream. + * Negative offsets count from the end of the stream. + * + * Seeking (offset) is not supported with remote files. + * Attempting to seek on non-local files may work with small offsets, but this + * is unpredictable because it works on the buffered stream. + * @param int $maxlen Maximum length of data read. The default is to read until end + * of file is reached. Note that this parameter is applied to the + * stream processed by the filters. + * @return string The function returns the read data. + * @throws FilesystemException + * + */ +function file_get_contents(string $filename, bool $use_include_path = false, $context = null, int $offset = 0, int $maxlen = null): string +{ + error_clear_last(); + if ($maxlen !== null) { + $result = \file_get_contents($filename, $use_include_path, $context, $offset, $maxlen); + } elseif ($offset !== 0) { + $result = \file_get_contents($filename, $use_include_path, $context, $offset); + } elseif ($context !== null) { + $result = \file_get_contents($filename, $use_include_path, $context); + } else { + $result = \file_get_contents($filename, $use_include_path); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * This function is identical to calling fopen, + * fwrite and fclose successively + * to write data to a file. + * + * If filename does not exist, the file is created. + * Otherwise, the existing file is overwritten, unless the + * FILE_APPEND flag is set. + * + * @param string $filename Path to the file where to write the data. + * @param mixed $data The data to write. Can be either a string, an + * array or a stream resource. + * + * If data is a stream resource, the + * remaining buffer of that stream will be copied to the specified file. + * This is similar with using stream_copy_to_stream. + * + * You can also specify the data parameter as a single + * dimension array. This is equivalent to + * file_put_contents($filename, implode('', $array)). + * @param int $flags The value of flags can be any combination of + * the following flags, joined with the binary OR (|) + * operator. + * + * + * Available flags + * + * + * + * Flag + * Description + * + * + * + * + * + * FILE_USE_INCLUDE_PATH + * + * + * Search for filename in the include directory. + * See include_path for more + * information. + * + * + * + * + * FILE_APPEND + * + * + * If file filename already exists, append + * the data to the file instead of overwriting it. + * + * + * + * + * LOCK_EX + * + * + * Acquire an exclusive lock on the file while proceeding to the + * writing. In other words, a flock call happens + * between the fopen call and the + * fwrite call. This is not identical to an + * fopen call with mode "x". + * + * + * + * + * + * @param resource $context A valid context resource created with + * stream_context_create. + * @return int This function returns the number of bytes that were written to the file. + * @throws FilesystemException + * + */ +function file_put_contents(string $filename, $data, int $flags = 0, $context = null): int +{ + error_clear_last(); + if ($context !== null) { + $result = \file_put_contents($filename, $data, $flags, $context); + } else { + $result = \file_put_contents($filename, $data, $flags); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Reads an entire file into an array. + * + * @param string $filename Path to the file. + * @param int $flags The optional parameter flags can be one, or + * more, of the following constants: + * + * + * + * FILE_USE_INCLUDE_PATH + * + * + * + * Search for the file in the include_path. + * + * + * + * + * + * FILE_IGNORE_NEW_LINES + * + * + * + * Omit newline at the end of each array element + * + * + * + * + * + * FILE_SKIP_EMPTY_LINES + * + * + * + * Skip empty lines + * + * + * + * + * @param resource $context + * @return array Returns the file in an array. Each element of the array corresponds to a + * line in the file, with the newline still attached. Upon failure, + * file returns FALSE. + * @throws FilesystemException + * + */ +function file(string $filename, int $flags = 0, $context = null): array +{ + error_clear_last(); + if ($context !== null) { + $result = \file($filename, $flags, $context); + } else { + $result = \file($filename, $flags); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * + * + * @param string $filename Path to the file. + * @return int Returns the time the file was last accessed. + * The time is returned as a Unix timestamp. + * @throws FilesystemException + * + */ +function fileatime(string $filename): int +{ + error_clear_last(); + $result = \fileatime($filename); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Gets the inode change time of a file. + * + * @param string $filename Path to the file. + * @return int Returns the time the file was last changed. + * The time is returned as a Unix timestamp. + * @throws FilesystemException + * + */ +function filectime(string $filename): int +{ + error_clear_last(); + $result = \filectime($filename); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Gets the file inode. + * + * @param string $filename Path to the file. + * @return int Returns the inode number of the file. + * @throws FilesystemException + * + */ +function fileinode(string $filename): int +{ + error_clear_last(); + $result = \fileinode($filename); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * This function returns the time when the data blocks of a file were being + * written to, that is, the time when the content of the file was changed. + * + * @param string $filename Path to the file. + * @return int Returns the time the file was last modified. + * The time is returned as a Unix timestamp, which is + * suitable for the date function. + * @throws FilesystemException + * + */ +function filemtime(string $filename): int +{ + error_clear_last(); + $result = \filemtime($filename); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Gets the file owner. + * + * @param string $filename Path to the file. + * @return int Returns the user ID of the owner of the file. + * The user ID is returned in numerical format, use + * posix_getpwuid to resolve it to a username. + * @throws FilesystemException + * + */ +function fileowner(string $filename): int +{ + error_clear_last(); + $result = \fileowner($filename); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Gets the size for the given file. + * + * @param string $filename Path to the file. + * @return int Returns the size of the file in bytes, or FALSE (and generates an error + * of level E_WARNING) in case of an error. + * @throws FilesystemException + * + */ +function filesize(string $filename): int +{ + error_clear_last(); + $result = \filesize($filename); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * flock allows you to perform a simple reader/writer + * model which can be used on virtually every platform (including most Unix + * derivatives and even Windows). + * + * On versions of PHP before 5.3.2, the lock is released also by + * fclose (which is also called automatically when script + * finished). + * + * PHP supports a portable way of locking complete files in an advisory way + * (which means all accessing programs have to use the same way of locking + * or it will not work). By default, this function will block until the + * requested lock is acquired; this may be controlled with the LOCK_NB option documented below. + * + * @param resource $handle A file system pointer resource + * that is typically created using fopen. + * @param int $operation operation is one of the following: + * + * + * + * LOCK_SH to acquire a shared lock (reader). + * + * + * + * + * LOCK_EX to acquire an exclusive lock (writer). + * + * + * + * + * LOCK_UN to release a lock (shared or exclusive). + * + * + * + * + * It is also possible to add LOCK_NB as a bitmask to one + * of the above operations, if flock should not + * block during the locking attempt. + * @param int|null $wouldblock The optional third argument is set to 1 if the lock would block + * (EWOULDBLOCK errno condition). + * @throws FilesystemException + * + */ +function flock($handle, int $operation, ?int &$wouldblock = null): void +{ + error_clear_last(); + $result = \flock($handle, $operation, $wouldblock); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * fopen binds a named resource, specified by + * filename, to a stream. + * + * @param string $filename If filename is of the form "scheme://...", it + * is assumed to be a URL and PHP will search for a protocol handler + * (also known as a wrapper) for that scheme. If no wrappers for that + * protocol are registered, PHP will emit a notice to help you track + * potential problems in your script and then continue as though + * filename specifies a regular file. + * + * If PHP has decided that filename specifies + * a local file, then it will try to open a stream on that file. + * The file must be accessible to PHP, so you need to ensure that + * the file access permissions allow this access. + * If you have enabled + * open_basedir further + * restrictions may apply. + * + * If PHP has decided that filename specifies + * a registered protocol, and that protocol is registered as a + * network URL, PHP will check to make sure that + * allow_url_fopen is + * enabled. If it is switched off, PHP will emit a warning and + * the fopen call will fail. + * + * The list of supported protocols can be found in . Some protocols (also referred to as + * wrappers) support context + * and/or php.ini options. Refer to the specific page for the + * protocol in use for a list of options which can be set. (e.g. + * php.ini value user_agent used by the + * http wrapper). + * + * On the Windows platform, be careful to escape any backslashes + * used in the path to the file, or use forward slashes. + * + * + * + * ]]> + * + * + * @param string $mode The mode parameter specifies the type of access + * you require to the stream. It may be any of the following: + * + * + * A list of possible modes for fopen + * using mode + * + * + * + * + * mode + * Description + * + * + * + * + * 'r' + * + * Open for reading only; place the file pointer at the + * beginning of the file. + * + * + * + * 'r+' + * + * Open for reading and writing; place the file pointer at + * the beginning of the file. + * + * + * + * 'w' + * + * Open for writing only; place the file pointer at the + * beginning of the file and truncate the file to zero length. + * If the file does not exist, attempt to create it. + * + * + * + * 'w+' + * + * Open for reading and writing; place the file pointer at + * the beginning of the file and truncate the file to zero + * length. If the file does not exist, attempt to create it. + * + * + * + * 'a' + * + * Open for writing only; place the file pointer at the end of + * the file. If the file does not exist, attempt to create it. + * In this mode, fseek has no effect, writes are always appended. + * + * + * + * 'a+' + * + * Open for reading and writing; place the file pointer at + * the end of the file. If the file does not exist, attempt to + * create it. In this mode, fseek only affects + * the reading position, writes are always appended. + * + * + * + * 'x' + * + * Create and open for writing only; place the file pointer at the + * beginning of the file. If the file already exists, the + * fopen call will fail by returning FALSE and + * generating an error of level E_WARNING. If + * the file does not exist, attempt to create it. This is equivalent + * to specifying O_EXCL|O_CREAT flags for the + * underlying open(2) system call. + * + * + * + * 'x+' + * + * Create and open for reading and writing; otherwise it has the + * same behavior as 'x'. + * + * + * + * 'c' + * + * Open the file for writing only. If the file does not exist, it is + * created. If it exists, it is neither truncated (as opposed to + * 'w'), nor the call to this function fails (as is + * the case with 'x'). The file pointer is + * positioned on the beginning of the file. This may be useful if it's + * desired to get an advisory lock (see flock) + * before attempting to modify the file, as using + * 'w' could truncate the file before the lock + * was obtained (if truncation is desired, + * ftruncate can be used after the lock is + * requested). + * + * + * + * 'c+' + * + * Open the file for reading and writing; otherwise it has the same + * behavior as 'c'. + * + * + * + * 'e' + * + * Set close-on-exec flag on the opened file descriptor. Only + * available in PHP compiled on POSIX.1-2008 conform systems. + * + * + * + * + * + * + * Different operating system families have different line-ending + * conventions. When you write a text file and want to insert a line + * break, you need to use the correct line-ending character(s) for your + * operating system. Unix based systems use \n as the + * line ending character, Windows based systems use \r\n + * as the line ending characters and Macintosh based systems (Mac OS Classic) used + * \r as the line ending character. + * + * If you use the wrong line ending characters when writing your files, you + * might find that other applications that open those files will "look + * funny". + * + * Windows offers a text-mode translation flag ('t') + * which will transparently translate \n to + * \r\n when working with the file. In contrast, you + * can also use 'b' to force binary mode, which will not + * translate your data. To use these flags, specify either + * 'b' or 't' as the last character + * of the mode parameter. + * + * The default translation mode is 'b'. + * You can use the 't' + * mode if you are working with plain-text files and you use + * \n to delimit your line endings in your script, but + * expect your files to be readable with applications such as old versions of notepad. You + * should use the 'b' in all other cases. + * + * If you specify the 't' flag when working with binary files, you + * may experience strange problems with your data, including broken image + * files and strange problems with \r\n characters. + * + * For portability, it is also strongly recommended that + * you re-write code that uses or relies upon the 't' + * mode so that it uses the correct line endings and + * 'b' mode instead. + * @param bool $use_include_path The optional third use_include_path parameter + * can be set to '1' or TRUE if you want to search for the file in the + * include_path, too. + * @param resource $context + * @return resource Returns a file pointer resource on success + * @throws FilesystemException + * + */ +function fopen(string $filename, string $mode, bool $use_include_path = false, $context = null) +{ + error_clear_last(); + if ($context !== null) { + $result = \fopen($filename, $mode, $use_include_path, $context); + } else { + $result = \fopen($filename, $mode, $use_include_path); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * fputcsv formats a line (passed as a + * fields array) as CSV and writes it (terminated by a + * newline) to the specified file handle. + * + * @param resource $handle The file pointer must be valid, and must point to + * a file successfully opened by fopen or + * fsockopen (and not yet closed by + * fclose). + * @param array $fields An array of strings. + * @param string $delimiter The optional delimiter parameter sets the field + * delimiter (one character only). + * @param string $enclosure The optional enclosure parameter sets the field + * enclosure (one character only). + * @param string $escape_char The optional escape_char parameter sets the + * escape character (at most one character). + * An empty string ("") disables the proprietary escape mechanism. + * @return int Returns the length of the written string. + * @throws FilesystemException + * + */ +function fputcsv($handle, array $fields, string $delimiter = ",", string $enclosure = '"', string $escape_char = "\\"): int +{ + error_clear_last(); + $result = \fputcsv($handle, $fields, $delimiter, $enclosure, $escape_char); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * fread reads up to + * length bytes from the file pointer + * referenced by handle. Reading stops as soon as one + * of the following conditions is met: + * + * + * + * length bytes have been read + * + * + * + * + * EOF (end of file) is reached + * + * + * + * + * a packet becomes available or the + * socket timeout occurs (for network streams) + * + * + * + * + * if the stream is read buffered and it does not represent a plain file, at + * most one read of up to a number of bytes equal to the chunk size (usually + * 8192) is made; depending on the previously buffered data, the size of the + * returned data may be larger than the chunk size. + * + * + * + * + * @param resource $handle A file system pointer resource + * that is typically created using fopen. + * @param int $length Up to length number of bytes read. + * @return string Returns the read string. + * @throws FilesystemException + * + */ +function fread($handle, int $length): string +{ + error_clear_last(); + $result = \fread($handle, $length); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Takes the filepointer, handle, and truncates the file to + * length, size. + * + * @param resource $handle The file pointer. + * + * The handle must be open for writing. + * @param int $size The size to truncate to. + * + * If size is larger than the file then the file + * is extended with null bytes. + * + * If size is smaller than the file then the file + * is truncated to that size. + * @throws FilesystemException + * + */ +function ftruncate($handle, int $size): void +{ + error_clear_last(); + $result = \ftruncate($handle, $size); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * + * + * @param resource $handle A file system pointer resource + * that is typically created using fopen. + * @param string $string The string that is to be written. + * @param int $length If the length argument is given, writing will + * stop after length bytes have been written or + * the end of string is reached, whichever comes + * first. + * + * Note that if the length argument is given, + * then the magic_quotes_runtime + * configuration option will be ignored and no slashes will be + * stripped from string. + * @return int + * @throws FilesystemException + * + */ +function fwrite($handle, string $string, int $length = null): int +{ + error_clear_last(); + if ($length !== null) { + $result = \fwrite($handle, $string, $length); + } else { + $result = \fwrite($handle, $string); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * The glob function searches for all the pathnames + * matching pattern according to the rules used by + * the libc glob() function, which is similar to the rules used by common + * shells. + * + * @param string $pattern The pattern. No tilde expansion or parameter substitution is done. + * + * Special characters: + * + * + * + * * - Matches zero or more characters. + * + * + * + * + * ? - Matches exactly one character (any character). + * + * + * + * + * [...] - Matches one character from a group of + * characters. If the first character is !, + * matches any character not in the group. + * + * + * + * + * \ - Escapes the following character, + * except when the GLOB_NOESCAPE flag is used. + * + * + * + * @param int $flags Valid flags: + * + * + * + * GLOB_MARK - Adds a slash (a backslash on Windows) to each directory returned + * + * + * + * + * GLOB_NOSORT - Return files as they appear in the + * directory (no sorting). When this flag is not used, the pathnames are + * sorted alphabetically + * + * + * + * + * GLOB_NOCHECK - Return the search pattern if no + * files matching it were found + * + * + * + * + * GLOB_NOESCAPE - Backslashes do not quote + * metacharacters + * + * + * + * + * GLOB_BRACE - Expands {a,b,c} to match 'a', 'b', + * or 'c' + * + * + * + * + * GLOB_ONLYDIR - Return only directory entries + * which match the pattern + * + * + * + * + * GLOB_ERR - Stop on read errors (like unreadable + * directories), by default errors are ignored. + * + * + * + * @return array Returns an array containing the matched files/directories, an empty array + * if no file matched. + * @throws FilesystemException + * + */ +function glob(string $pattern, int $flags = 0): array +{ + error_clear_last(); + $result = \glob($pattern, $flags); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Attempts to change the group of the symlink filename + * to group. + * + * Only the superuser may change the group of a symlink arbitrarily; other + * users may change the group of a symlink to any group of which that user is + * a member. + * + * @param string $filename Path to the symlink. + * @param string|int $group The group specified by name or number. + * @throws FilesystemException + * + */ +function lchgrp(string $filename, $group): void +{ + error_clear_last(); + $result = \lchgrp($filename, $group); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Attempts to change the owner of the symlink filename + * to user user. + * + * Only the superuser may change the owner of a symlink. + * + * @param string $filename Path to the file. + * @param string|int $user User name or number. + * @throws FilesystemException + * + */ +function lchown(string $filename, $user): void +{ + error_clear_last(); + $result = \lchown($filename, $user); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * link creates a hard link. + * + * @param string $target Target of the link. + * @param string $link The link name. + * @throws FilesystemException + * + */ +function link(string $target, string $link): void +{ + error_clear_last(); + $result = \link($target, $link); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Attempts to create the directory specified by pathname. + * + * @param string $pathname The directory path. + * @param int $mode The mode is 0777 by default, which means the widest possible + * access. For more information on modes, read the details + * on the chmod page. + * + * mode is ignored on Windows. + * + * Note that you probably want to specify the mode as an octal number, + * which means it should have a leading zero. The mode is also modified + * by the current umask, which you can change using + * umask. + * @param bool $recursive Allows the creation of nested directories specified in the + * pathname. + * @param resource $context + * @throws FilesystemException + * + */ +function mkdir(string $pathname, int $mode = 0777, bool $recursive = false, $context = null): void +{ + error_clear_last(); + if ($context !== null) { + $result = \mkdir($pathname, $mode, $recursive, $context); + } else { + $result = \mkdir($pathname, $mode, $recursive); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * parse_ini_file loads in the + * ini file specified in filename, + * and returns the settings in it in an associative array. + * + * The structure of the ini file is the same as the php.ini's. + * + * @param string $filename The filename of the ini file being parsed. If a relative path is used, + * it is evaluated relative to the current working directory, then the + * include_path. + * @param bool $process_sections By setting the process_sections + * parameter to TRUE, you get a multidimensional array, with + * the section names and settings included. The default + * for process_sections is FALSE + * @param int $scanner_mode Can either be INI_SCANNER_NORMAL (default) or + * INI_SCANNER_RAW. If INI_SCANNER_RAW + * is supplied, then option values will not be parsed. + * + * + * As of PHP 5.6.1 can also be specified as INI_SCANNER_TYPED. + * In this mode boolean, null and integer types are preserved when possible. + * String values "true", "on" and "yes" + * are converted to TRUE. "false", "off", "no" + * and "none" are considered FALSE. "null" is converted to NULL + * in typed mode. Also, all numeric strings are converted to integer type if it is possible. + * @return array The settings are returned as an associative array on success. + * @throws FilesystemException + * + */ +function parse_ini_file(string $filename, bool $process_sections = false, int $scanner_mode = INI_SCANNER_NORMAL): array +{ + error_clear_last(); + $result = \parse_ini_file($filename, $process_sections, $scanner_mode); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * parse_ini_string returns the settings in string + * ini in an associative array. + * + * The structure of the ini string is the same as the php.ini's. + * + * @param string $ini The contents of the ini file being parsed. + * @param bool $process_sections By setting the process_sections + * parameter to TRUE, you get a multidimensional array, with + * the section names and settings included. The default + * for process_sections is FALSE + * @param int $scanner_mode Can either be INI_SCANNER_NORMAL (default) or + * INI_SCANNER_RAW. If INI_SCANNER_RAW + * is supplied, then option values will not be parsed. + * + * + * As of PHP 5.6.1 can also be specified as INI_SCANNER_TYPED. + * In this mode boolean, null and integer types are preserved when possible. + * String values "true", "on" and "yes" + * are converted to TRUE. "false", "off", "no" + * and "none" are considered FALSE. "null" is converted to NULL + * in typed mode. Also, all numeric strings are converted to integer type if it is possible. + * @return array The settings are returned as an associative array on success. + * @throws FilesystemException + * + */ +function parse_ini_string(string $ini, bool $process_sections = false, int $scanner_mode = INI_SCANNER_NORMAL): array +{ + error_clear_last(); + $result = \parse_ini_string($ini, $process_sections, $scanner_mode); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Reads a file and writes it to the output buffer. + * + * @param string $filename The filename being read. + * @param bool $use_include_path You can use the optional second parameter and set it to TRUE, if + * you want to search for the file in the include_path, too. + * @param resource $context A context stream resource. + * @return int Returns the number of bytes read from the file on success + * @throws FilesystemException + * + */ +function readfile(string $filename, bool $use_include_path = false, $context = null): int +{ + error_clear_last(); + if ($context !== null) { + $result = \readfile($filename, $use_include_path, $context); + } else { + $result = \readfile($filename, $use_include_path); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * readlink does the same as the readlink C function. + * + * @param string $path The symbolic link path. + * @return string Returns the contents of the symbolic link path. + * @throws FilesystemException + * + */ +function readlink(string $path): string +{ + error_clear_last(); + $result = \readlink($path); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * realpath expands all symbolic links and + * resolves references to /./, /../ and extra / characters in + * the input path and returns the canonicalized + * absolute pathname. + * + * @param string $path The path being checked. + * + * + * Whilst a path must be supplied, the value can be an empty string. + * In this case, the value is interpreted as the current directory. + * + * + * + * Whilst a path must be supplied, the value can be an empty string. + * In this case, the value is interpreted as the current directory. + * @return string Returns the canonicalized absolute pathname on success. The resulting path + * will have no symbolic link, /./ or /../ components. Trailing delimiters, + * such as \ and /, are also removed. + * + * realpath returns FALSE on failure, e.g. if + * the file does not exist. + * @throws FilesystemException + * + */ +function realpath(string $path): string +{ + error_clear_last(); + $result = \realpath($path); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Attempts to rename oldname to + * newname, moving it between directories if necessary. + * If renaming a file and newname exists, + * it will be overwritten. If renaming a directory and + * newname exists, + * this function will emit a warning. + * + * @param string $oldname The old name. + * + * The wrapper used in oldname + * must match the wrapper used in + * newname. + * @param string $newname The new name. + * @param resource $context + * @throws FilesystemException + * + */ +function rename(string $oldname, string $newname, $context = null): void +{ + error_clear_last(); + if ($context !== null) { + $result = \rename($oldname, $newname, $context); + } else { + $result = \rename($oldname, $newname); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Sets the file position indicator for handle + * to the beginning of the file stream. + * + * @param resource $handle The file pointer must be valid, and must point to a file + * successfully opened by fopen. + * @throws FilesystemException + * + */ +function rewind($handle): void +{ + error_clear_last(); + $result = \rewind($handle); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Attempts to remove the directory named by dirname. + * The directory must be empty, and the relevant permissions must permit this. + * A E_WARNING level error will be generated on failure. + * + * @param string $dirname Path to the directory. + * @param resource $context + * @throws FilesystemException + * + */ +function rmdir(string $dirname, $context = null): void +{ + error_clear_last(); + if ($context !== null) { + $result = \rmdir($dirname, $context); + } else { + $result = \rmdir($dirname); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * symlink creates a symbolic link to the existing + * target with the specified name + * link. + * + * @param string $target Target of the link. + * @param string $link The link name. + * @throws FilesystemException + * + */ +function symlink(string $target, string $link): void +{ + error_clear_last(); + $result = \symlink($target, $link); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Creates a file with a unique filename, with access permission set to 0600, in the specified directory. + * If the directory does not exist or is not writable, tempnam may + * generate a file in the system's temporary directory, and return + * the full path to that file, including its name. + * + * @param string $dir The directory where the temporary filename will be created. + * @param string $prefix The prefix of the generated temporary filename. + * @return string Returns the new temporary filename (with path). + * @throws FilesystemException + * + */ +function tempnam(string $dir, string $prefix): string +{ + error_clear_last(); + $result = \tempnam($dir, $prefix); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Creates a temporary file with a unique name in read-write (w+) mode and + * returns a file handle. + * + * The file is automatically removed when closed (for example, by calling + * fclose, or when there are no remaining references to + * the file handle returned by tmpfile), or when the + * script ends. + * + * @return resource Returns a file handle, similar to the one returned by + * fopen, for the new file. + * @throws FilesystemException + * + */ +function tmpfile() +{ + error_clear_last(); + $result = \tmpfile(); + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } + return $result; +} + + +/** + * Attempts to set the access and modification times of the file named in the + * filename parameter to the value given in + * time. + * Note that the access time is always modified, regardless of the number + * of parameters. + * + * If the file does not exist, it will be created. + * + * @param string $filename The name of the file being touched. + * @param int $time The touch time. If time is not supplied, + * the current system time is used. + * @param int $atime If present, the access time of the given filename is set to + * the value of atime. Otherwise, it is set to + * the value passed to the time parameter. + * If neither are present, the current system time is used. + * @throws FilesystemException + * + */ +function touch(string $filename, int $time = null, int $atime = null): void +{ + error_clear_last(); + if ($atime !== null) { + $result = \touch($filename, $time, $atime); + } elseif ($time !== null) { + $result = \touch($filename, $time); + } else { + $result = \touch($filename); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} + + +/** + * Deletes filename. Similar to the Unix C unlink() + * function. An E_WARNING level error will be generated on + * failure. + * + * @param string $filename Path to the file. + * @param resource $context + * @throws FilesystemException + * + */ +function unlink(string $filename, $context = null): void +{ + error_clear_last(); + if ($context !== null) { + $result = \unlink($filename, $context); + } else { + $result = \unlink($filename); + } + if ($result === false) { + throw FilesystemException::createFromPhpError(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/filter.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/filter.php new file mode 100644 index 00000000..2d836c6c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/filter.php @@ -0,0 +1,93 @@ + + * + * + * + * channels will be 3 for RGB pictures and 4 for CMYK + * pictures. + * + * bits is the number of bits for each color. + * + * For some image types, the presence of channels and + * bits values can be a bit + * confusing. As an example, GIF always uses 3 channels + * per pixel, but the number of bits per pixel cannot be calculated for an + * animated GIF with a global color table. + * + * On failure, FALSE is returned. + * @throws ImageException + * + */ +function getimagesize(string $filename, array &$imageinfo = null): array +{ + error_clear_last(); + $result = \getimagesize($filename, $imageinfo); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * image2wbmp outputs or save a WBMP + * version of the given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param string|null $filename Path to the saved file. If not given, the raw image stream will be + * output directly. + * @param int $foreground You can set the foreground color with this parameter by setting an + * identifier obtained from imagecolorallocate. + * The default foreground color is black. + * @throws ImageException + * + */ +function image2wbmp($image, ?string $filename = null, int $foreground = null): void +{ + error_clear_last(); + if ($foreground !== null) { + $result = \image2wbmp($image, $filename, $foreground); + } elseif ($filename !== null) { + $result = \image2wbmp($image, $filename); + } else { + $result = \image2wbmp($image); + } + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param array $affine Array with keys 0 to 5. + * @param array $clip Array with keys "x", "y", "width" and "height". + * @return resource Return affined image resource on success. + * @throws ImageException + * + */ +function imageaffine($image, array $affine, array $clip = null) +{ + error_clear_last(); + if ($clip !== null) { + $result = \imageaffine($image, $affine, $clip); + } else { + $result = \imageaffine($image, $affine); + } + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Returns the concatenation of two affine transformation matrices, + * what is useful if multiple transformations should be applied to the same + * image in one go. + * + * @param array $m1 An affine transformation matrix (an array with keys + * 0 to 5 and float values). + * @param array $m2 An affine transformation matrix (an array with keys + * 0 to 5 and float values). + * @return array{0:float,1:float,2:float,3:float,4:float,5:float} An affine transformation matrix (an array with keys + * 0 to 5 and float values). + * @throws ImageException + * + */ +function imageaffinematrixconcat(array $m1, array $m2): array +{ + error_clear_last(); + $result = \imageaffinematrixconcat($m1, $m2); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Returns an affine transformation matrix. + * + * @param int $type One of the IMG_AFFINE_* constants. + * @param array|float $options If type is IMG_AFFINE_TRANSLATE + * or IMG_AFFINE_SCALE, + * options has to be an array with keys x + * and y, both having float values. + * + * If type is IMG_AFFINE_ROTATE, + * IMG_AFFINE_SHEAR_HORIZONTAL or IMG_AFFINE_SHEAR_VERTICAL, + * options has to be a float specifying the angle. + * @return array{0:float,1:float,2:float,3:float,4:float,5:float} An affine transformation matrix (an array with keys + * 0 to 5 and float values). + * @throws ImageException + * + */ +function imageaffinematrixget(int $type, $options = null): array +{ + error_clear_last(); + if ($options !== null) { + $result = \imageaffinematrixget($type, $options); + } else { + $result = \imageaffinematrixget($type); + } + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagealphablending allows for two different + * modes of drawing on truecolor images. In blending mode, the + * alpha channel component of the color supplied to all drawing function, + * such as imagesetpixel determines how much of the + * underlying color should be allowed to shine through. As a result, gd + * automatically blends the existing color at that point with the drawing color, + * and stores the result in the image. The resulting pixel is opaque. In + * non-blending mode, the drawing color is copied literally with its alpha channel + * information, replacing the destination pixel. Blending mode is not available + * when drawing on palette images. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param bool $blendmode Whether to enable the blending mode or not. On true color images + * the default value is TRUE otherwise the default value is FALSE + * @throws ImageException + * + */ +function imagealphablending($image, bool $blendmode): void +{ + error_clear_last(); + $result = \imagealphablending($image, $blendmode); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Activate the fast drawing antialiased methods for lines and wired polygons. + * It does not support alpha components. It works using a direct blend + * operation. It works only with truecolor images. + * + * Thickness and styled are not supported. + * + * Using antialiased primitives with transparent background color can end with + * some unexpected results. The blend method uses the background color as any + * other colors. The lack of alpha component support does not allow an alpha + * based antialiasing method. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param bool $enabled Whether to enable antialiasing or not. + * @throws ImageException + * + */ +function imageantialias($image, bool $enabled): void +{ + error_clear_last(); + $result = \imageantialias($image, $enabled); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagearc draws an arc of circle centered at the given + * coordinates. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $cx x-coordinate of the center. + * @param int $cy y-coordinate of the center. + * @param int $width The arc width. + * @param int $height The arc height. + * @param int $start The arc start angle, in degrees. + * @param int $end The arc end angle, in degrees. + * 0° is located at the three-o'clock position, and the arc is drawn + * clockwise. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagearc($image, int $cx, int $cy, int $width, int $height, int $start, int $end, int $color): void +{ + error_clear_last(); + $result = \imagearc($image, $cx, $cy, $width, $height, $start, $end, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Outputs or saves a BMP version of the given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * + * NULL is invalid if the compressed arguments is + * not used. + * @param bool $compressed Whether the BMP should be compressed with run-length encoding (RLE), or not. + * @throws ImageException + * + */ +function imagebmp($image, $to = null, bool $compressed = true): void +{ + error_clear_last(); + $result = \imagebmp($image, $to, $compressed); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagechar draws the first character of + * c in the image identified by + * image with its upper-left at + * x,y (top left is 0, + * 0) with the color color. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $font Can be 1, 2, 3, 4, 5 for built-in + * fonts in latin2 encoding (where higher numbers corresponding to larger fonts) or any of your + * own font identifiers registered with imageloadfont. + * @param int $x x-coordinate of the start. + * @param int $y y-coordinate of the start. + * @param string $c The character to draw. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagechar($image, int $font, int $x, int $y, string $c, int $color): void +{ + error_clear_last(); + $result = \imagechar($image, $font, $x, $y, $c, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Draws the character c vertically at the specified + * coordinate on the given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $font Can be 1, 2, 3, 4, 5 for built-in + * fonts in latin2 encoding (where higher numbers corresponding to larger fonts) or any of your + * own font identifiers registered with imageloadfont. + * @param int $x x-coordinate of the start. + * @param int $y y-coordinate of the start. + * @param string $c The character to draw. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagecharup($image, int $font, int $x, int $y, string $c, int $color): void +{ + error_clear_last(); + $result = \imagecharup($image, $font, $x, $y, $c, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Returns the index of the color of the pixel at the + * specified location in the image specified by image. + * + * If the image is a + * truecolor image, this function returns the RGB value of that pixel as + * integer. Use bitshifting and masking to access the distinct red, green and blue + * component values: + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x x-coordinate of the point. + * @param int $y y-coordinate of the point. + * @return int Returns the index of the color. + * @throws ImageException + * + */ +function imagecolorat($image, int $x, int $y): int +{ + error_clear_last(); + $result = \imagecolorat($image, $x, $y); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * De-allocates a color previously allocated with + * imagecolorallocate or + * imagecolorallocatealpha. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $color The color identifier. + * @throws ImageException + * + */ +function imagecolordeallocate($image, int $color): void +{ + error_clear_last(); + $result = \imagecolordeallocate($image, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Makes the colors of the palette version of an image more closely match the true color version. + * + * @param resource $image1 A truecolor image resource. + * @param resource $image2 A palette image resource pointing to an image that has the same + * size as image1. + * @throws ImageException + * + */ +function imagecolormatch($image1, $image2): void +{ + error_clear_last(); + $result = \imagecolormatch($image1, $image2); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Applies a convolution matrix on the image, using the given coefficient and + * offset. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param array $matrix A 3x3 matrix: an array of three arrays of three floats. + * @param float $div The divisor of the result of the convolution, used for normalization. + * @param float $offset Color offset. + * @throws ImageException + * + */ +function imageconvolution($image, array $matrix, float $div, float $offset): void +{ + error_clear_last(); + $result = \imageconvolution($image, $matrix, $div, $offset); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Copy a part of src_im onto + * dst_im starting at the x,y coordinates + * src_x, src_y with + * a width of src_w and a height of + * src_h. The portion defined will be copied + * onto the x,y coordinates, dst_x and + * dst_y. + * + * @param resource $dst_im Destination image resource. + * @param resource $src_im Source image resource. + * @param int $dst_x x-coordinate of destination point. + * @param int $dst_y y-coordinate of destination point. + * @param int $src_x x-coordinate of source point. + * @param int $src_y y-coordinate of source point. + * @param int $src_w Source width. + * @param int $src_h Source height. + * @throws ImageException + * + */ +function imagecopy($dst_im, $src_im, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_w, int $src_h): void +{ + error_clear_last(); + $result = \imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Copy a part of src_im onto + * dst_im starting at the x,y coordinates + * src_x, src_y with + * a width of src_w and a height of + * src_h. The portion defined will be copied + * onto the x,y coordinates, dst_x and + * dst_y. + * + * @param resource $dst_im Destination image resource. + * @param resource $src_im Source image resource. + * @param int $dst_x x-coordinate of destination point. + * @param int $dst_y y-coordinate of destination point. + * @param int $src_x x-coordinate of source point. + * @param int $src_y y-coordinate of source point. + * @param int $src_w Source width. + * @param int $src_h Source height. + * @param int $pct The two images will be merged according to pct + * which can range from 0 to 100. When pct = 0, + * no action is taken, when 100 this function behaves identically + * to imagecopy for pallete images, except for + * ignoring alpha components, while it implements alpha transparency + * for true colour images. + * @throws ImageException + * + */ +function imagecopymerge($dst_im, $src_im, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_w, int $src_h, int $pct): void +{ + error_clear_last(); + $result = \imagecopymerge($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagecopymergegray copy a part of src_im onto + * dst_im starting at the x,y coordinates + * src_x, src_y with + * a width of src_w and a height of + * src_h. The portion defined will be copied + * onto the x,y coordinates, dst_x and + * dst_y. + * + * This function is identical to imagecopymerge except + * that when merging it preserves the hue of the source by converting + * the destination pixels to gray scale before the copy operation. + * + * @param resource $dst_im Destination image resource. + * @param resource $src_im Source image resource. + * @param int $dst_x x-coordinate of destination point. + * @param int $dst_y y-coordinate of destination point. + * @param int $src_x x-coordinate of source point. + * @param int $src_y y-coordinate of source point. + * @param int $src_w Source width. + * @param int $src_h Source height. + * @param int $pct The src_im will be changed to grayscale according + * to pct where 0 is fully grayscale and 100 is + * unchanged. When pct = 100 this function behaves + * identically to imagecopy for pallete images, except for + * ignoring alpha components, while + * it implements alpha transparency for true colour images. + * @throws ImageException + * + */ +function imagecopymergegray($dst_im, $src_im, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_w, int $src_h, int $pct): void +{ + error_clear_last(); + $result = \imagecopymergegray($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagecopyresampled copies a rectangular + * portion of one image to another image, smoothly interpolating pixel + * values so that, in particular, reducing the size of an image still + * retains a great deal of clarity. + * + * In other words, imagecopyresampled will take a + * rectangular area from src_image of width + * src_w and height src_h at + * position (src_x,src_y) + * and place it in a rectangular area of dst_image + * of width dst_w and height dst_h + * at position (dst_x,dst_y). + * + * If the source and destination coordinates and width and heights + * differ, appropriate stretching or shrinking of the image fragment + * will be performed. The coordinates refer to the upper left + * corner. This function can be used to copy regions within the + * same image (if dst_image is the same as + * src_image) but if the regions overlap the + * results will be unpredictable. + * + * @param resource $dst_image Destination image resource. + * @param resource $src_image Source image resource. + * @param int $dst_x x-coordinate of destination point. + * @param int $dst_y y-coordinate of destination point. + * @param int $src_x x-coordinate of source point. + * @param int $src_y y-coordinate of source point. + * @param int $dst_w Destination width. + * @param int $dst_h Destination height. + * @param int $src_w Source width. + * @param int $src_h Source height. + * @throws ImageException + * + */ +function imagecopyresampled($dst_image, $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_w, int $dst_h, int $src_w, int $src_h): void +{ + error_clear_last(); + $result = \imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagecopyresized copies a rectangular + * portion of one image to another image. + * dst_image is the destination image, + * src_image is the source image identifier. + * + * In other words, imagecopyresized will take a + * rectangular area from src_image of width + * src_w and height src_h at + * position (src_x,src_y) + * and place it in a rectangular area of dst_image + * of width dst_w and height dst_h + * at position (dst_x,dst_y). + * + * If the source and destination coordinates and width and heights + * differ, appropriate stretching or shrinking of the image fragment + * will be performed. The coordinates refer to the upper left + * corner. This function can be used to copy regions within the + * same image (if dst_image is the same as + * src_image) but if the regions overlap the + * results will be unpredictable. + * + * @param resource $dst_image Destination image resource. + * @param resource $src_image Source image resource. + * @param int $dst_x x-coordinate of destination point. + * @param int $dst_y y-coordinate of destination point. + * @param int $src_x x-coordinate of source point. + * @param int $src_y y-coordinate of source point. + * @param int $dst_w Destination width. + * @param int $dst_h Destination height. + * @param int $src_w Source width. + * @param int $src_h Source height. + * @throws ImageException + * + */ +function imagecopyresized($dst_image, $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_w, int $dst_h, int $src_w, int $src_h): void +{ + error_clear_last(); + $result = \imagecopyresized($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagecreate returns an image identifier + * representing a blank image of specified size. + * + * In general, we recommend the use of + * imagecreatetruecolor instead of + * imagecreate so that image processing occurs on the + * highest quality image possible. If you want to output a palette image, then + * imagetruecolortopalette should be called immediately + * before saving the image with imagepng or + * imagegif. + * + * @param int $width The image width. + * @param int $height The image height. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreate(int $width, int $height) +{ + error_clear_last(); + $result = \imagecreate($width, $height); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefrombmp returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the BMP image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefrombmp(string $filename) +{ + error_clear_last(); + $result = \imagecreatefrombmp($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Create a new image from GD file or URL. + * + * @param string $filename Path to the GD file. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromgd(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromgd($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Create a new image from GD2 file or URL. + * + * @param string $filename Path to the GD2 image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromgd2(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromgd2($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Create a new image from a given part of GD2 file or URL. + * + * @param string $filename Path to the GD2 image. + * @param int $srcX x-coordinate of source point. + * @param int $srcY y-coordinate of source point. + * @param int $width Source width. + * @param int $height Source height. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromgd2part(string $filename, int $srcX, int $srcY, int $width, int $height) +{ + error_clear_last(); + $result = \imagecreatefromgd2part($filename, $srcX, $srcY, $width, $height); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefromgif returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the GIF image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromgif(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromgif($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefromjpeg returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the JPEG image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromjpeg(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromjpeg($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefrompng returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the PNG image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefrompng(string $filename) +{ + error_clear_last(); + $result = \imagecreatefrompng($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefromwbmp returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the WBMP image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromwbmp(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromwbmp($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefromwebp returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the WebP image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromwebp(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromwebp($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefromxbm returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the XBM image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromxbm(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromxbm($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatefromxpm returns an image identifier + * representing the image obtained from the given filename. + * + * @param string $filename Path to the XPM image. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatefromxpm(string $filename) +{ + error_clear_last(); + $result = \imagecreatefromxpm($filename); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagecreatetruecolor returns an image identifier + * representing a black image of the specified size. + * + * @param int $width Image width. + * @param int $height Image height. + * @return resource Returns an image resource identifier on success, FALSE on errors. + * @throws ImageException + * + */ +function imagecreatetruecolor(int $width, int $height) +{ + error_clear_last(); + $result = \imagecreatetruecolor($width, $height); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Crops an image to the given rectangular area and returns the resulting image. + * The given image is not modified. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param array $rect The cropping rectangle as array with keys + * x, y, width and + * height. + * @return resource Return cropped image resource on success. + * @throws ImageException + * + */ +function imagecrop($image, array $rect) +{ + error_clear_last(); + $result = \imagecrop($image, $rect); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Automatically crops an image according to the given + * mode. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $mode One of the following constants: + * @param float $threshold + * @param int $color + * @return resource Returns a cropped image resource on success. + * If the complete image was cropped, imagecrop returns FALSE. + * @throws ImageException + * + */ +function imagecropauto($image, int $mode = IMG_CROP_DEFAULT, float $threshold = .5, int $color = -1) +{ + error_clear_last(); + $result = \imagecropauto($image, $mode, $threshold, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * This function is deprecated. Use combination of + * imagesetstyle and imageline + * instead. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x1 Upper left x coordinate. + * @param int $y1 Upper left y coordinate 0, 0 is the top left corner of the image. + * @param int $x2 Bottom right x coordinate. + * @param int $y2 Bottom right y coordinate. + * @param int $color The fill color. A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagedashedline($image, int $x1, int $y1, int $x2, int $y2, int $color): void +{ + error_clear_last(); + $result = \imagedashedline($image, $x1, $y1, $x2, $y2, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagedestroy frees any memory associated + * with image image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @throws ImageException + * + */ +function imagedestroy($image): void +{ + error_clear_last(); + $result = \imagedestroy($image); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Draws an ellipse centered at the specified coordinates. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $cx x-coordinate of the center. + * @param int $cy y-coordinate of the center. + * @param int $width The ellipse width. + * @param int $height The ellipse height. + * @param int $color The color of the ellipse. A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imageellipse($image, int $cx, int $cy, int $width, int $height, int $color): void +{ + error_clear_last(); + $result = \imageellipse($image, $cx, $cy, $width, $height, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Performs a flood fill starting at the given coordinate (top left is 0, 0) + * with the given color in the + * image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x x-coordinate of start point. + * @param int $y y-coordinate of start point. + * @param int $color The fill color. A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagefill($image, int $x, int $y, int $color): void +{ + error_clear_last(); + $result = \imagefill($image, $x, $y, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Draws a partial arc centered at the specified coordinate in the + * given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $cx x-coordinate of the center. + * @param int $cy y-coordinate of the center. + * @param int $width The arc width. + * @param int $height The arc height. + * @param int $start The arc start angle, in degrees. + * @param int $end The arc end angle, in degrees. + * 0° is located at the three-o'clock position, and the arc is drawn + * clockwise. + * @param int $color A color identifier created with imagecolorallocate. + * @param int $style A bitwise OR of the following possibilities: + * + * IMG_ARC_PIE + * IMG_ARC_CHORD + * IMG_ARC_NOFILL + * IMG_ARC_EDGED + * + * IMG_ARC_PIE and IMG_ARC_CHORD are + * mutually exclusive; IMG_ARC_CHORD just + * connects the starting and ending angles with a straight line, while + * IMG_ARC_PIE produces a rounded edge. + * IMG_ARC_NOFILL indicates that the arc + * or chord should be outlined, not filled. IMG_ARC_EDGED, + * used together with IMG_ARC_NOFILL, indicates that the + * beginning and ending angles should be connected to the center - this is a + * good way to outline (rather than fill) a 'pie slice'. + * @throws ImageException + * + */ +function imagefilledarc($image, int $cx, int $cy, int $width, int $height, int $start, int $end, int $color, int $style): void +{ + error_clear_last(); + $result = \imagefilledarc($image, $cx, $cy, $width, $height, $start, $end, $color, $style); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Draws an ellipse centered at the specified coordinate on the given + * image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $cx x-coordinate of the center. + * @param int $cy y-coordinate of the center. + * @param int $width The ellipse width. + * @param int $height The ellipse height. + * @param int $color The fill color. A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagefilledellipse($image, int $cx, int $cy, int $width, int $height, int $color): void +{ + error_clear_last(); + $result = \imagefilledellipse($image, $cx, $cy, $width, $height, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagefilledpolygon creates a filled polygon + * in the given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param array $points An array containing the x and y + * coordinates of the polygons vertices consecutively. + * @param int $num_points Total number of points (vertices), which must be at least 3. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagefilledpolygon($image, array $points, int $num_points, int $color): void +{ + error_clear_last(); + $result = \imagefilledpolygon($image, $points, $num_points, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Creates a rectangle filled with color in the given + * image starting at point 1 and ending at point 2. + * 0, 0 is the top left corner of the image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x1 x-coordinate for point 1. + * @param int $y1 y-coordinate for point 1. + * @param int $x2 x-coordinate for point 2. + * @param int $y2 y-coordinate for point 2. + * @param int $color The fill color. A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagefilledrectangle($image, int $x1, int $y1, int $x2, int $y2, int $color): void +{ + error_clear_last(); + $result = \imagefilledrectangle($image, $x1, $y1, $x2, $y2, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagefilltoborder performs a flood fill + * whose border color is defined by border. + * The starting point for the fill is x, + * y (top left is 0, 0) and the region is + * filled with color color. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x x-coordinate of start. + * @param int $y y-coordinate of start. + * @param int $border The border color. A color identifier created with imagecolorallocate. + * @param int $color The fill color. A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagefilltoborder($image, int $x, int $y, int $border, int $color): void +{ + error_clear_last(); + $result = \imagefilltoborder($image, $x, $y, $border, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagefilter applies the given filter + * filtertype on the image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $filtertype filtertype can be one of the following: + * + * + * + * IMG_FILTER_NEGATE: Reverses all colors of + * the image. + * + * + * + * + * IMG_FILTER_GRAYSCALE: Converts the image into + * grayscale by changing the red, green and blue components to their + * weighted sum using the same coefficients as the REC.601 luma (Y') + * calculation. The alpha components are retained. For palette images the + * result may differ due to palette limitations. + * + * + * + * + * IMG_FILTER_BRIGHTNESS: Changes the brightness + * of the image. Use arg1 to set the level of + * brightness. The range for the brightness is -255 to 255. + * + * + * + * + * IMG_FILTER_CONTRAST: Changes the contrast of + * the image. Use arg1 to set the level of + * contrast. + * + * + * + * + * IMG_FILTER_COLORIZE: Like + * IMG_FILTER_GRAYSCALE, except you can specify the + * color. Use arg1, arg2 and + * arg3 in the form of + * red, green, + * blue and arg4 for the + * alpha channel. The range for each color is 0 to 255. + * + * + * + * + * IMG_FILTER_EDGEDETECT: Uses edge detection to + * highlight the edges in the image. + * + * + * + * + * IMG_FILTER_EMBOSS: Embosses the image. + * + * + * + * + * IMG_FILTER_GAUSSIAN_BLUR: Blurs the image using + * the Gaussian method. + * + * + * + * + * IMG_FILTER_SELECTIVE_BLUR: Blurs the image. + * + * + * + * + * IMG_FILTER_MEAN_REMOVAL: Uses mean removal to + * achieve a "sketchy" effect. + * + * + * + * + * IMG_FILTER_SMOOTH: Makes the image smoother. + * Use arg1 to set the level of smoothness. + * + * + * + * + * IMG_FILTER_PIXELATE: Applies pixelation effect + * to the image, use arg1 to set the block size + * and arg2 to set the pixelation effect mode. + * + * + * + * + * IMG_FILTER_SCATTER: Applies scatter effect + * to the image, use arg1 and + * arg2 to define the effect strength and + * additionally arg3 to only apply the + * on select pixel colors. + * + * + * + * @param int $arg1 + * + * + * IMG_FILTER_BRIGHTNESS: Brightness level. + * + * + * + * + * IMG_FILTER_CONTRAST: Contrast level. + * + * + * + * + * IMG_FILTER_COLORIZE: Value of red component. + * + * + * + * + * IMG_FILTER_SMOOTH: Smoothness level. + * + * + * + * + * IMG_FILTER_PIXELATE: Block size in pixels. + * + * + * + * + * IMG_FILTER_SCATTER: Effect substraction level. + * This must not be higher or equal to the addition level set with + * arg2. + * + * + * + * @param int $arg2 + * + * + * IMG_FILTER_COLORIZE: Value of green component. + * + * + * + * + * IMG_FILTER_PIXELATE: Whether to use advanced pixelation + * effect or not (defaults to FALSE). + * + * + * + * + * IMG_FILTER_SCATTER: Effect addition level. + * + * + * + * @param int $arg3 + * + * + * IMG_FILTER_COLORIZE: Value of blue component. + * + * + * + * + * IMG_FILTER_SCATTER: Optional array indexed color values + * to apply effect at. + * + * + * + * @param int $arg4 + * + * + * IMG_FILTER_COLORIZE: Alpha channel, A value + * between 0 and 127. 0 indicates completely opaque while 127 indicates + * completely transparent. + * + * + * + * @throws ImageException + * + */ +function imagefilter($image, int $filtertype, int $arg1 = null, int $arg2 = null, int $arg3 = null, int $arg4 = null): void +{ + error_clear_last(); + if ($arg4 !== null) { + $result = \imagefilter($image, $filtertype, $arg1, $arg2, $arg3, $arg4); + } elseif ($arg3 !== null) { + $result = \imagefilter($image, $filtertype, $arg1, $arg2, $arg3); + } elseif ($arg2 !== null) { + $result = \imagefilter($image, $filtertype, $arg1, $arg2); + } elseif ($arg1 !== null) { + $result = \imagefilter($image, $filtertype, $arg1); + } else { + $result = \imagefilter($image, $filtertype); + } + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Flips the image image using the given + * mode. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $mode Flip mode, this can be one of the IMG_FLIP_* constants: + * + * + * + * + * + * Constant + * Meaning + * + * + * + * + * IMG_FLIP_HORIZONTAL + * + * Flips the image horizontally. + * + * + * + * IMG_FLIP_VERTICAL + * + * Flips the image vertically. + * + * + * + * IMG_FLIP_BOTH + * + * Flips the image both horizontally and vertically. + * + * + * + * + * + * @throws ImageException + * + */ +function imageflip($image, int $mode): void +{ + error_clear_last(); + $result = \imageflip($image, $mode); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Applies gamma correction to the given gd image + * given an input and an output gamma. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param float $inputgamma The input gamma. + * @param float $outputgamma The output gamma. + * @throws ImageException + * + */ +function imagegammacorrect($image, float $inputgamma, float $outputgamma): void +{ + error_clear_last(); + $result = \imagegammacorrect($image, $inputgamma, $outputgamma); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Outputs a GD image to the given to. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * @throws ImageException + * + */ +function imagegd($image, $to = null): void +{ + error_clear_last(); + $result = \imagegd($image, $to); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Outputs a GD2 image to the given to. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * @param int $chunk_size Chunk size. + * @param int $type Either IMG_GD2_RAW or + * IMG_GD2_COMPRESSED. Default is + * IMG_GD2_RAW. + * @throws ImageException + * + */ +function imagegd2($image, $to = null, int $chunk_size = 128, int $type = IMG_GD2_RAW): void +{ + error_clear_last(); + $result = \imagegd2($image, $to, $chunk_size, $type); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagegif creates the GIF + * file in to from the image image. The + * image argument is the return from the + * imagecreate or imagecreatefrom* + * function. + * + * The image format will be GIF87a unless the + * image has been made transparent with + * imagecolortransparent, in which case the + * image format will be GIF89a. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * @throws ImageException + * + */ +function imagegif($image, $to = null): void +{ + error_clear_last(); + $result = \imagegif($image, $to); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Grabs a screenshot of the whole screen. + * + * @return resource Returns an image resource identifier on success, FALSE on failure. + * @throws ImageException + * + */ +function imagegrabscreen() +{ + error_clear_last(); + $result = \imagegrabscreen(); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Grabs a window or its client area using a windows handle (HWND property in COM instance) + * + * @param int $window_handle The HWND window ID. + * @param int $client_area Include the client area of the application window. + * @return resource Returns an image resource identifier on success, FALSE on failure. + * @throws ImageException + * + */ +function imagegrabwindow(int $window_handle, int $client_area = 0) +{ + error_clear_last(); + $result = \imagegrabwindow($window_handle, $client_area); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagejpeg creates a JPEG file from + * the given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * @param int $quality quality is optional, and ranges from 0 (worst + * quality, smaller file) to 100 (best quality, biggest file). The + * default (-1) uses the default IJG quality value (about 75). + * @throws ImageException + * + */ +function imagejpeg($image, $to = null, int $quality = -1): void +{ + error_clear_last(); + $result = \imagejpeg($image, $to, $quality); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Set the alpha blending flag to use layering effects. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $effect One of the following constants: + * + * + * IMG_EFFECT_REPLACE + * + * + * Use pixel replacement (equivalent of passing TRUE to + * imagealphablending) + * + * + * + * + * IMG_EFFECT_ALPHABLEND + * + * + * Use normal pixel blending (equivalent of passing FALSE to + * imagealphablending) + * + * + * + * + * IMG_EFFECT_NORMAL + * + * + * Same as IMG_EFFECT_ALPHABLEND. + * + * + * + * + * IMG_EFFECT_OVERLAY + * + * + * Overlay has the effect that black background pixels will remain + * black, white background pixels will remain white, but grey + * background pixels will take the colour of the foreground pixel. + * + * + * + * + * IMG_EFFECT_MULTIPLY + * + * + * Overlays with a multiply effect. + * + * + * + * + * @throws ImageException + * + */ +function imagelayereffect($image, int $effect): void +{ + error_clear_last(); + $result = \imagelayereffect($image, $effect); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Draws a line between the two given points. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x1 x-coordinate for first point. + * @param int $y1 y-coordinate for first point. + * @param int $x2 x-coordinate for second point. + * @param int $y2 y-coordinate for second point. + * @param int $color The line color. A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imageline($image, int $x1, int $y1, int $x2, int $y2, int $color): void +{ + error_clear_last(); + $result = \imageline($image, $x1, $y1, $x2, $y2, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imageloadfont loads a user-defined bitmap and returns + * its identifier. + * + * @param string $file The font file format is currently binary and architecture + * dependent. This means you should generate the font files on the + * same type of CPU as the machine you are running PHP on. + * + * + * Font file format + * + * + * + * byte position + * C data type + * description + * + * + * + * + * byte 0-3 + * int + * number of characters in the font + * + * + * byte 4-7 + * int + * + * value of first character in the font (often 32 for space) + * + * + * + * byte 8-11 + * int + * pixel width of each character + * + * + * byte 12-15 + * int + * pixel height of each character + * + * + * byte 16- + * char + * + * array with character data, one byte per pixel in each + * character, for a total of (nchars*width*height) bytes. + * + * + * + * + * + * @return int The font identifier which is always bigger than 5 to avoid conflicts with + * built-in fontss. + * @throws ImageException + * + */ +function imageloadfont(string $file): int +{ + error_clear_last(); + $result = \imageloadfont($file); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imageopenpolygon draws an open polygon on the given + * image. Contrary to imagepolygon, + * no line is drawn between the last and the first point. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param array $points An array containing the polygon's vertices, e.g.: + * + * + * + * + * points[0] + * = x0 + * + * + * points[1] + * = y0 + * + * + * points[2] + * = x1 + * + * + * points[3] + * = y1 + * + * + * + * + * @param int $num_points Total number of points (vertices), which must be at least 3. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imageopenpolygon($image, array $points, int $num_points, int $color): void +{ + error_clear_last(); + $result = \imageopenpolygon($image, $points, $num_points, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Outputs or saves a PNG image from the given + * image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * + * NULL is invalid if the quality and + * filters arguments are not used. + * @param int $quality Compression level: from 0 (no compression) to 9. + * The default (-1) uses the zlib compression default. + * For more information see the zlib manual. + * @param int $filters Allows reducing the PNG file size. It is a bitmask field which may be + * set to any combination of the PNG_FILTER_XXX + * constants. PNG_NO_FILTER or + * PNG_ALL_FILTERS may also be used to respectively + * disable or activate all filters. + * The default value (-1) disables filtering. + * @throws ImageException + * + */ +function imagepng($image, $to = null, int $quality = -1, int $filters = -1): void +{ + error_clear_last(); + $result = \imagepng($image, $to, $quality, $filters); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagepolygon creates a polygon in the given + * image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param array $points An array containing the polygon's vertices, e.g.: + * + * + * + * + * points[0] + * = x0 + * + * + * points[1] + * = y0 + * + * + * points[2] + * = x1 + * + * + * points[3] + * = y1 + * + * + * + * + * @param int $num_points Total number of points (vertices), which must be at least 3. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagepolygon($image, array $points, int $num_points, int $color): void +{ + error_clear_last(); + $result = \imagepolygon($image, $points, $num_points, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagerectangle creates a rectangle starting at + * the specified coordinates. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x1 Upper left x coordinate. + * @param int $y1 Upper left y coordinate + * 0, 0 is the top left corner of the image. + * @param int $x2 Bottom right x coordinate. + * @param int $y2 Bottom right y coordinate. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagerectangle($image, int $x1, int $y1, int $x2, int $y2, int $color): void +{ + error_clear_last(); + $result = \imagerectangle($image, $x1, $y1, $x2, $y2, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Rotates the image image using the given + * angle in degrees. + * + * The center of rotation is the center of the image, and the rotated + * image may have different dimensions than the original image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param float $angle Rotation angle, in degrees. The rotation angle is interpreted as the + * number of degrees to rotate the image anticlockwise. + * @param int $bgd_color Specifies the color of the uncovered zone after the rotation + * @param int $dummy This parameter is unused. + * @return resource Returns an image resource for the rotated image. + * @throws ImageException + * + */ +function imagerotate($image, float $angle, int $bgd_color, int $dummy = 0) +{ + error_clear_last(); + $result = \imagerotate($image, $angle, $bgd_color, $dummy); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagesavealpha sets the flag which determines whether to retain + * full alpha channel information (as opposed to single-color transparency) + * when saving PNG images. + * + * Alphablending has to be disabled (imagealphablending($im, false)) + * to retain the alpha-channel in the first place. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param bool $saveflag Whether to save the alpha channel or not. Defaults to FALSE. + * @throws ImageException + * + */ +function imagesavealpha($image, bool $saveflag): void +{ + error_clear_last(); + $result = \imagesavealpha($image, $saveflag); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagescale scales an image using the given + * interpolation algorithm. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $new_width The width to scale the image to. + * @param int $new_height The height to scale the image to. If omitted or negative, the aspect + * ratio will be preserved. + * @param int $mode One of IMG_NEAREST_NEIGHBOUR, + * IMG_BILINEAR_FIXED, + * IMG_BICUBIC, + * IMG_BICUBIC_FIXED or anything else (will use two + * pass). + * + * + * IMG_WEIGHTED4 is not yet supported. + * + * + * @return resource Return the scaled image resource on success. + * @throws ImageException + * + */ +function imagescale($image, int $new_width, int $new_height = -1, int $mode = IMG_BILINEAR_FIXED) +{ + error_clear_last(); + $result = \imagescale($image, $new_width, $new_height, $mode); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagesetbrush sets the brush image to be + * used by all line drawing functions (such as imageline + * and imagepolygon) when drawing with the special + * colors IMG_COLOR_BRUSHED or + * IMG_COLOR_STYLEDBRUSHED. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param resource $brush An image resource. + * @throws ImageException + * + */ +function imagesetbrush($image, $brush): void +{ + error_clear_last(); + $result = \imagesetbrush($image, $brush); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagesetclip sets the current clipping rectangle, i.e. + * the area beyond which no pixels will be drawn. + * + * @param resource $im An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x1 The x-coordinate of the upper left corner. + * @param int $y1 The y-coordinate of the upper left corner. + * @param int $x2 The x-coordinate of the lower right corner. + * @param int $y2 The y-coordinate of the lower right corner. + * @throws ImageException + * + */ +function imagesetclip($im, int $x1, int $y1, int $x2, int $y2): void +{ + error_clear_last(); + $result = \imagesetclip($im, $x1, $y1, $x2, $y2); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Sets the interpolation method, setting an interpolation method affects the rendering + * of various functions in GD, such as the imagerotate function. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $method The interpolation method, which can be one of the following: + * + * + * + * IMG_BELL: Bell filter. + * + * + * + * + * IMG_BESSEL: Bessel filter. + * + * + * + * + * IMG_BICUBIC: Bicubic interpolation. + * + * + * + * + * IMG_BICUBIC_FIXED: Fixed point implementation of the bicubic interpolation. + * + * + * + * + * IMG_BILINEAR_FIXED: Fixed point implementation of the bilinear interpolation (default (also on image creation)). + * + * + * + * + * IMG_BLACKMAN: Blackman window function. + * + * + * + * + * IMG_BOX: Box blur filter. + * + * + * + * + * IMG_BSPLINE: Spline interpolation. + * + * + * + * + * IMG_CATMULLROM: Cubic Hermite spline interpolation. + * + * + * + * + * IMG_GAUSSIAN: Gaussian function. + * + * + * + * + * IMG_GENERALIZED_CUBIC: Generalized cubic spline fractal interpolation. + * + * + * + * + * IMG_HERMITE: Hermite interpolation. + * + * + * + * + * IMG_HAMMING: Hamming filter. + * + * + * + * + * IMG_HANNING: Hanning filter. + * + * + * + * + * IMG_MITCHELL: Mitchell filter. + * + * + * + * + * IMG_POWER: Power interpolation. + * + * + * + * + * IMG_QUADRATIC: Inverse quadratic interpolation. + * + * + * + * + * IMG_SINC: Sinc function. + * + * + * + * + * IMG_NEAREST_NEIGHBOUR: Nearest neighbour interpolation. + * + * + * + * + * IMG_WEIGHTED4: Weighting filter. + * + * + * + * + * IMG_TRIANGLE: Triangle interpolation. + * + * + * + * @throws ImageException + * + */ +function imagesetinterpolation($image, int $method = IMG_BILINEAR_FIXED): void +{ + error_clear_last(); + $result = \imagesetinterpolation($image, $method); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagesetpixel draws a pixel at the specified + * coordinate. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $x x-coordinate. + * @param int $y y-coordinate. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagesetpixel($image, int $x, int $y, int $color): void +{ + error_clear_last(); + $result = \imagesetpixel($image, $x, $y, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagesetstyle sets the style to be used by all + * line drawing functions (such as imageline + * and imagepolygon) when drawing with the special + * color IMG_COLOR_STYLED or lines of images with color + * IMG_COLOR_STYLEDBRUSHED. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param array $style An array of pixel colors. You can use the + * IMG_COLOR_TRANSPARENT constant to add a + * transparent pixel. + * Note that style must not be an empty array. + * @throws ImageException + * + */ +function imagesetstyle($image, array $style): void +{ + error_clear_last(); + $result = \imagesetstyle($image, $style); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagesetthickness sets the thickness of the lines + * drawn when drawing rectangles, polygons, arcs etc. to + * thickness pixels. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $thickness Thickness, in pixels. + * @throws ImageException + * + */ +function imagesetthickness($image, int $thickness): void +{ + error_clear_last(); + $result = \imagesetthickness($image, $thickness); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * imagesettile sets the tile image to be + * used by all region filling functions (such as imagefill + * and imagefilledpolygon) when filling with the special + * color IMG_COLOR_TILED. + * + * A tile is an image used to fill an area with a repeated pattern. Any + * GD image can be used as a tile, and by setting the transparent color index of the tile + * image with imagecolortransparent, a tile allows certain parts + * of the underlying area to shine through can be created. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param resource $tile The image resource to be used as a tile. + * @throws ImageException + * + */ +function imagesettile($image, $tile): void +{ + error_clear_last(); + $result = \imagesettile($image, $tile); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Draws a string at the given coordinates. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $font Can be 1, 2, 3, 4, 5 for built-in + * fonts in latin2 encoding (where higher numbers corresponding to larger fonts) or any of your + * own font identifiers registered with imageloadfont. + * @param int $x x-coordinate of the upper left corner. + * @param int $y y-coordinate of the upper left corner. + * @param string $string The string to be written. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagestring($image, int $font, int $x, int $y, string $string, int $color): void +{ + error_clear_last(); + $result = \imagestring($image, $font, $x, $y, $string, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Draws a string vertically at the given + * coordinates. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param int $font Can be 1, 2, 3, 4, 5 for built-in + * fonts in latin2 encoding (where higher numbers corresponding to larger fonts) or any of your + * own font identifiers registered with imageloadfont. + * @param int $x x-coordinate of the bottom left corner. + * @param int $y y-coordinate of the bottom left corner. + * @param string $string The string to be written. + * @param int $color A color identifier created with imagecolorallocate. + * @throws ImageException + * + */ +function imagestringup($image, int $font, int $x, int $y, string $string, int $color): void +{ + error_clear_last(); + $result = \imagestringup($image, $font, $x, $y, $string, $color); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Returns the width of the given image resource. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @return int Return the width of the images. + * @throws ImageException + * + */ +function imagesx($image): int +{ + error_clear_last(); + $result = \imagesx($image); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Returns the height of the given image resource. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @return int Return the height of the images. + * @throws ImageException + * + */ +function imagesy($image): int +{ + error_clear_last(); + $result = \imagesy($image); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagetruecolortopalette converts a truecolor image + * to a palette image. The code for this function was originally drawn from + * the Independent JPEG Group library code, which is excellent. The code + * has been modified to preserve as much alpha channel information as + * possible in the resulting palette, in addition to preserving colors as + * well as possible. This does not work as well as might be hoped. It is + * usually best to simply produce a truecolor output image instead, which + * guarantees the highest output quality. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param bool $dither Indicates if the image should be dithered - if it is TRUE then + * dithering will be used which will result in a more speckled image but + * with better color approximation. + * @param int $ncolors Sets the maximum number of colors that should be retained in the palette. + * @throws ImageException + * + */ +function imagetruecolortopalette($image, bool $dither, int $ncolors): void +{ + error_clear_last(); + $result = \imagetruecolortopalette($image, $dither, $ncolors); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * This function calculates and returns the bounding box in pixels + * for a TrueType text. + * + * @param float $size The font size in points. + * @param float $angle Angle in degrees in which text will be measured. + * @param string $fontfile The path to the TrueType font you wish to use. + * + * Depending on which version of the GD library PHP is using, when + * fontfile does not begin with a leading + * / then .ttf will be appended + * to the filename and the library will attempt to search for that + * filename along a library-defined font path. + * + * When using versions of the GD library lower than 2.0.18, a space character, + * rather than a semicolon, was used as the 'path separator' for different font files. + * Unintentional use of this feature will result in the warning message: + * Warning: Could not find/open font. For these affected versions, the + * only solution is moving the font to a path which does not contain spaces. + * + * In many cases where a font resides in the same directory as the script using it + * the following trick will alleviate any include problems. + * + * + * ]]> + * + * + * Note that open_basedir does + * not apply to fontfile. + * @param string $text The string to be measured. + * @return array imagettfbbox returns an array with 8 + * elements representing four points making the bounding box of the + * text on success and FALSE on error. + * + * + * + * + * key + * contents + * + * + * + * + * 0 + * lower left corner, X position + * + * + * 1 + * lower left corner, Y position + * + * + * 2 + * lower right corner, X position + * + * + * 3 + * lower right corner, Y position + * + * + * 4 + * upper right corner, X position + * + * + * 5 + * upper right corner, Y position + * + * + * 6 + * upper left corner, X position + * + * + * 7 + * upper left corner, Y position + * + * + * + * + * + * The points are relative to the text regardless of the + * angle, so "upper left" means in the top left-hand + * corner seeing the text horizontally. + * @throws ImageException + * + */ +function imagettfbbox(float $size, float $angle, string $fontfile, string $text): array +{ + error_clear_last(); + $result = \imagettfbbox($size, $angle, $fontfile, $text); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Writes the given text into the image using TrueType + * fonts. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param float $size The font size in points. + * @param float $angle The angle in degrees, with 0 degrees being left-to-right reading text. + * Higher values represent a counter-clockwise rotation. For example, a + * value of 90 would result in bottom-to-top reading text. + * @param int $x The coordinates given by x and + * y will define the basepoint of the first + * character (roughly the lower-left corner of the character). This + * is different from the imagestring, where + * x and y define the + * upper-left corner of the first character. For example, "top left" + * is 0, 0. + * @param int $y The y-ordinate. This sets the position of the fonts baseline, not the + * very bottom of the character. + * @param int $color The color index. Using the negative of a color index has the effect of + * turning off antialiasing. See imagecolorallocate. + * @param string $fontfile The path to the TrueType font you wish to use. + * + * Depending on which version of the GD library PHP is using, when + * fontfile does not begin with a leading + * / then .ttf will be appended + * to the filename and the library will attempt to search for that + * filename along a library-defined font path. + * + * When using versions of the GD library lower than 2.0.18, a space character, + * rather than a semicolon, was used as the 'path separator' for different font files. + * Unintentional use of this feature will result in the warning message: + * Warning: Could not find/open font. For these affected versions, the + * only solution is moving the font to a path which does not contain spaces. + * + * In many cases where a font resides in the same directory as the script using it + * the following trick will alleviate any include problems. + * + * + * ]]> + * + * + * Note that open_basedir does + * not apply to fontfile. + * @param string $text The text string in UTF-8 encoding. + * + * May include decimal numeric character references (of the form: + * &#8364;) to access characters in a font beyond position 127. + * The hexadecimal format (like &#xA9;) is supported. + * Strings in UTF-8 encoding can be passed directly. + * + * Named entities, such as &copy;, are not supported. Consider using + * html_entity_decode + * to decode these named entities into UTF-8 strings. + * + * If a character is used in the string which is not supported by the + * font, a hollow rectangle will replace the character. + * @return array Returns an array with 8 elements representing four points making the + * bounding box of the text. The order of the points is lower left, lower + * right, upper right, upper left. The points are relative to the text + * regardless of the angle, so "upper left" means in the top left-hand + * corner when you see the text horizontally. + * @throws ImageException + * + */ +function imagettftext($image, float $size, float $angle, int $x, int $y, int $color, string $fontfile, string $text): array +{ + error_clear_last(); + $result = \imagettftext($image, $size, $angle, $x, $y, $color, $fontfile, $text); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * imagewbmp outputs or save a WBMP + * version of the given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * @param int $foreground You can set the foreground color with this parameter by setting an + * identifier obtained from imagecolorallocate. + * The default foreground color is black. + * @throws ImageException + * + */ +function imagewbmp($image, $to = null, int $foreground = null): void +{ + error_clear_last(); + if ($foreground !== null) { + $result = \imagewbmp($image, $to, $foreground); + } else { + $result = \imagewbmp($image, $to); + } + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Outputs or saves a WebP version of the given image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param mixed $to The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. + * @param int $quality quality ranges from 0 (worst + * quality, smaller file) to 100 (best quality, biggest file). + * @throws ImageException + * + */ +function imagewebp($image, $to = null, int $quality = 80): void +{ + error_clear_last(); + $result = \imagewebp($image, $to, $quality); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Outputs or save an XBM version of the given + * image. + * + * @param resource $image An image resource, returned by one of the image creation functions, + * such as imagecreatetruecolor. + * @param string|null $filename The path to save the file to, given as string. If NULL, the raw image stream will be output directly. + * + * The filename (without the .xbm extension) is also + * used for the C identifiers of the XBM, whereby non + * alphanumeric characters of the current locale are substituted by + * underscores. If filename is set to NULL, + * image is used to build the C identifiers. + * @param int $foreground You can set the foreground color with this parameter by setting an + * identifier obtained from imagecolorallocate. + * The default foreground color is black. All other colors are treated as + * background. + * @throws ImageException + * + */ +function imagexbm($image, ?string $filename, int $foreground = null): void +{ + error_clear_last(); + if ($foreground !== null) { + $result = \imagexbm($image, $filename, $foreground); + } else { + $result = \imagexbm($image, $filename); + } + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Embeds binary IPTC data into a JPEG image. + * + * @param string $iptcdata The data to be written. + * @param string $jpeg_file_name Path to the JPEG image. + * @param int $spool Spool flag. If the spool flag is less than 2 then the JPEG will be + * returned as a string. Otherwise the JPEG will be printed to STDOUT. + * @return string|bool If spool is less than 2, the JPEG will be returned. Otherwise returns TRUE on success. + * @throws ImageException + * + */ +function iptcembed(string $iptcdata, string $jpeg_file_name, int $spool = 0) +{ + error_clear_last(); + $result = \iptcembed($iptcdata, $jpeg_file_name, $spool); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Parses an IPTC block into its single tags. + * + * @param string $iptcblock A binary IPTC block. + * @return array Returns an array using the tagmarker as an index and the value as the + * value. It returns FALSE on error or if no IPTC data was found. + * @throws ImageException + * + */ +function iptcparse(string $iptcblock): array +{ + error_clear_last(); + $result = \iptcparse($iptcblock); + if ($result === false) { + throw ImageException::createFromPhpError(); + } + return $result; +} + + +/** + * Converts a JPEG file into a WBMP file. + * + * @param string $jpegname Path to JPEG file. + * @param string $wbmpname Path to destination WBMP file. + * @param int $dest_height Destination image height. + * @param int $dest_width Destination image width. + * @param int $threshold Threshold value, between 0 and 8 (inclusive). + * @throws ImageException + * + */ +function jpeg2wbmp(string $jpegname, string $wbmpname, int $dest_height, int $dest_width, int $threshold): void +{ + error_clear_last(); + $result = \jpeg2wbmp($jpegname, $wbmpname, $dest_height, $dest_width, $threshold); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} + + +/** + * Converts a PNG file into a WBMP file. + * + * @param string $pngname Path to PNG file. + * @param string $wbmpname Path to destination WBMP file. + * @param int $dest_height Destination image height. + * @param int $dest_width Destination image width. + * @param int $threshold Threshold value, between 0 and 8 (inclusive). + * @throws ImageException + * + */ +function png2wbmp(string $pngname, string $wbmpname, int $dest_height, int $dest_width, int $threshold): void +{ + error_clear_last(); + $result = \png2wbmp($pngname, $wbmpname, $dest_height, $dest_width, $threshold); + if ($result === false) { + throw ImageException::createFromPhpError(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/imap.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/imap.php new file mode 100644 index 00000000..acd8672c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/imap.php @@ -0,0 +1,1481 @@ + + * + * + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @throws LdapException + * + */ +function ldap_add($link_identifier, string $dn, array $entry, array $serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_add($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Does the same thing as ldap_bind but returns the LDAP result resource to be parsed with ldap_parse_result. + * + * @param resource $link_identifier + * @param string|null $bind_rdn + * @param string|null $bind_password + * @param array $serverctrls + * @return resource Returns an LDAP result identifier. + * @throws LdapException + * + */ +function ldap_bind_ext($link_identifier, ?string $bind_rdn = null, ?string $bind_password = null, array $serverctrls = null) +{ + error_clear_last(); + $result = \ldap_bind_ext($link_identifier, $bind_rdn, $bind_password, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Binds to the LDAP directory with specified RDN and password. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string|null $bind_rdn + * @param string|null $bind_password + * @throws LdapException + * + */ +function ldap_bind($link_identifier, ?string $bind_rdn = null, ?string $bind_password = null): void +{ + error_clear_last(); + $result = \ldap_bind($link_identifier, $bind_rdn, $bind_password); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Retrieve the pagination information send by the server. + * + * @param resource $link An LDAP link identifier, returned by ldap_connect. + * @param resource $result + * @param string|null $cookie An opaque structure sent by the server. + * @param int|null $estimated The estimated number of entries to retrieve. + * @throws LdapException + * + */ +function ldap_control_paged_result_response($link, $result, ?string &$cookie = null, ?int &$estimated = null): void +{ + error_clear_last(); + $result = \ldap_control_paged_result_response($link, $result, $cookie, $estimated); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Enable LDAP pagination by sending the pagination control (page size, cookie...). + * + * @param resource $link An LDAP link identifier, returned by ldap_connect. + * @param int $pagesize The number of entries by page. + * @param bool $iscritical Indicates whether the pagination is critical or not. + * If true and if the server doesn't support pagination, the search + * will return no result. + * @param string $cookie An opaque structure sent by the server + * (ldap_control_paged_result_response). + * @throws LdapException + * + */ +function ldap_control_paged_result($link, int $pagesize, bool $iscritical = false, string $cookie = ""): void +{ + error_clear_last(); + $result = \ldap_control_paged_result($link, $pagesize, $iscritical, $cookie); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Returns the number of entries stored in the result of previous search + * operations. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_identifier The internal LDAP result. + * @return int Returns number of entries in the result. + * @throws LdapException + * + */ +function ldap_count_entries($link_identifier, $result_identifier): int +{ + error_clear_last(); + $result = \ldap_count_entries($link_identifier, $result_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Does the same thing as ldap_delete but returns the LDAP result resource to be parsed with ldap_parse_result. + * + * @param resource $link_identifier + * @param string $dn + * @param array $serverctrls + * @return resource Returns an LDAP result identifier. + * @throws LdapException + * + */ +function ldap_delete_ext($link_identifier, string $dn, array $serverctrls = null) +{ + error_clear_last(); + $result = \ldap_delete_ext($link_identifier, $dn, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Deletes a particular entry in LDAP directory. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $dn The distinguished name of an LDAP entity. + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @throws LdapException + * + */ +function ldap_delete($link_identifier, string $dn, array $serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_delete($link_identifier, $dn, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Performs a PASSWD extended operation. + * + * @param resource $link An LDAP link identifier, returned by ldap_connect. + * @param string $user dn of the user to change the password of. + * @param string $oldpw The old password of this user. May be ommited depending of server configuration. + * @param string $newpw The new password for this user. May be omitted or empty to have a generated password. + * @param array $serverctrls If provided, a password policy request control is send with the request and this is + * filled with an array of LDAP Controls + * returned with the request. + * @return mixed Returns the generated password if newpw is empty or omitted. + * Otherwise returns TRUE on success. + * @throws LdapException + * + */ +function ldap_exop_passwd($link, string $user = "", string $oldpw = "", string $newpw = "", array &$serverctrls = null) +{ + error_clear_last(); + $result = \ldap_exop_passwd($link, $user, $oldpw, $newpw, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Performs a WHOAMI extended operation and returns the data. + * + * @param resource $link An LDAP link identifier, returned by ldap_connect. + * @return string The data returned by the server. + * @throws LdapException + * + */ +function ldap_exop_whoami($link): string +{ + error_clear_last(); + $result = \ldap_exop_whoami($link); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Performs an extended operation on the specified link with + * reqoid the OID of the operation and + * reqdata the data. + * + * @param resource $link An LDAP link identifier, returned by ldap_connect. + * @param string $reqoid The extended operation request OID. You may use one of LDAP_EXOP_START_TLS, LDAP_EXOP_MODIFY_PASSWD, LDAP_EXOP_REFRESH, LDAP_EXOP_WHO_AM_I, LDAP_EXOP_TURN, or a string with the OID of the operation you want to send. + * @param string $reqdata The extended operation request data. May be NULL for some operations like LDAP_EXOP_WHO_AM_I, may also need to be BER encoded. + * @param array|null $serverctrls Array of LDAP Controls to send with the request. + * @param string|null $retdata Will be filled with the extended operation response data if provided. + * If not provided you may use ldap_parse_exop on the result object + * later to get this data. + * @param string|null $retoid Will be filled with the response OID if provided, usually equal to the request OID. + * @return mixed When used with retdata, returns TRUE on success. + * When used without retdata, returns a result identifier. + * @throws LdapException + * + */ +function ldap_exop($link, string $reqoid, string $reqdata = null, ?array $serverctrls = null, ?string &$retdata = null, ?string &$retoid = null) +{ + error_clear_last(); + $result = \ldap_exop($link, $reqoid, $reqdata, $serverctrls, $retdata, $retoid); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Splits the DN returned by ldap_get_dn and breaks it + * up into its component parts. Each part is known as Relative Distinguished + * Name, or RDN. + * + * @param string $dn The distinguished name of an LDAP entity. + * @param int $with_attrib Used to request if the RDNs are returned with only values or their + * attributes as well. To get RDNs with the attributes (i.e. in + * attribute=value format) set with_attrib to 0 + * and to get only values set it to 1. + * @return array Returns an array of all DN components. + * The first element in the array has count key and + * represents the number of returned values, next elements are numerically + * indexed DN components. + * @throws LdapException + * + */ +function ldap_explode_dn(string $dn, int $with_attrib): array +{ + error_clear_last(); + $result = \ldap_explode_dn($dn, $with_attrib); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Gets the first attribute in the given entry. Remaining attributes are + * retrieved by calling ldap_next_attribute successively. + * + * Similar to reading entries, attributes are also read one by one from a + * particular entry. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_entry_identifier + * @return string Returns the first attribute in the entry on success and FALSE on + * error. + * @throws LdapException + * + */ +function ldap_first_attribute($link_identifier, $result_entry_identifier): string +{ + error_clear_last(); + $result = \ldap_first_attribute($link_identifier, $result_entry_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Returns the entry identifier for first entry in the result. This entry + * identifier is then supplied to ldap_next_entry + * routine to get successive entries from the result. + * + * Entries in the LDAP result are read sequentially using the + * ldap_first_entry and + * ldap_next_entry functions. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_identifier + * @return resource Returns the result entry identifier for the first entry on success and + * FALSE on error. + * @throws LdapException + * + */ +function ldap_first_entry($link_identifier, $result_identifier) +{ + error_clear_last(); + $result = \ldap_first_entry($link_identifier, $result_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Frees up the memory allocated internally to store the result. All result + * memory will be automatically freed when the script terminates. + * + * Typically all the memory allocated for the LDAP result gets freed at the + * end of the script. In case the script is making successive searches which + * return large result sets, ldap_free_result could be + * called to keep the runtime memory usage by the script low. + * + * @param resource $result_identifier + * @throws LdapException + * + */ +function ldap_free_result($result_identifier): void +{ + error_clear_last(); + $result = \ldap_free_result($result_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Reads attributes and values from an entry in the search result. + * + * Having located a specific entry in the directory, you can find out what + * information is held for that entry by using this call. You would use this + * call for an application which "browses" directory entries and/or where you + * do not know the structure of the directory entries. In many applications + * you will be searching for a specific attribute such as an email address or + * a surname, and won't care what other data is held. + * + * + * + * + * + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_entry_identifier + * @return array Returns a complete entry information in a multi-dimensional array + * on success and FALSE on error. + * @throws LdapException + * + */ +function ldap_get_attributes($link_identifier, $result_entry_identifier): array +{ + error_clear_last(); + $result = \ldap_get_attributes($link_identifier, $result_entry_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Finds out the DN of an entry in the result. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_entry_identifier + * @return string Returns the DN of the result entry and FALSE on error. + * @throws LdapException + * + */ +function ldap_get_dn($link_identifier, $result_entry_identifier): string +{ + error_clear_last(); + $result = \ldap_get_dn($link_identifier, $result_entry_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Reads multiple entries from the given result, and then reading the + * attributes and multiple values. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_identifier + * @return array Returns a complete result information in a multi-dimensional array on + * success and FALSE on error. + * + * The structure of the array is as follows. + * The attribute index is converted to lowercase. (Attributes are + * case-insensitive for directory servers, but not when used as + * array indices.) + * + * + * + * + * + * @throws LdapException + * + */ +function ldap_get_entries($link_identifier, $result_identifier): array +{ + error_clear_last(); + $result = \ldap_get_entries($link_identifier, $result_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Sets retval to the value of the specified option. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param int $option The parameter option can be one of: + * + * + * + * + * Option + * Type + * since + * + * + * + * + * LDAP_OPT_DEREF + * integer + * + * + * + * LDAP_OPT_SIZELIMIT + * integer + * + * + * + * LDAP_OPT_TIMELIMIT + * integer + * + * + * + * LDAP_OPT_NETWORK_TIMEOUT + * integer + * + * + * + * LDAP_OPT_PROTOCOL_VERSION + * integer + * + * + * + * LDAP_OPT_ERROR_NUMBER + * integer + * + * + * + * LDAP_OPT_DIAGNOSTIC_MESSAGE + * integer + * + * + * + * LDAP_OPT_REFERRALS + * bool + * + * + * + * LDAP_OPT_RESTART + * bool + * + * + * + * LDAP_OPT_HOST_NAME + * string + * + * + * + * LDAP_OPT_ERROR_STRING + * string + * + * + * + * LDAP_OPT_MATCHED_DN + * string + * + * + * + * LDAP_OPT_SERVER_CONTROLS + * array + * + * + * + * LDAP_OPT_CLIENT_CONTROLS + * array + * + * + * + * LDAP_OPT_X_KEEPALIVE_IDLE + * int + * 7.1 + * + * + * LDAP_OPT_X_KEEPALIVE_PROBES + * int + * 7.1 + * + * + * LDAP_OPT_X_KEEPALIVE_INTERVAL + * int + * 7.1 + * + * + * LDAP_OPT_X_TLS_CACERTDIR + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_CACERTFILE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_CERTFILE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_CIPHER_SUITE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_CRLCHECK + * integer + * 7.1 + * + * + * LDAP_OPT_X_TLS_CRL_NONE + * integer + * 7.1 + * + * + * LDAP_OPT_X_TLS_CRL_PEER + * integer + * 7.1 + * + * + * LDAP_OPT_X_TLS_CRL_ALL + * integer + * 7.1 + * + * + * LDAP_OPT_X_TLS_CRLFILE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_DHFILE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_KEYILE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_PACKAGE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_PROTOCOL_MIN + * integer + * 7.1 + * + * + * LDAP_OPT_X_TLS_RANDOM_FILE + * string + * 7.1 + * + * + * LDAP_OPT_X_TLS_REQUIRE_CERT + * integer + * + * + * + * + * + * @param mixed $retval This will be set to the option value. + * @throws LdapException + * + */ +function ldap_get_option($link_identifier, int $option, &$retval): void +{ + error_clear_last(); + $result = \ldap_get_option($link_identifier, $option, $retval); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Reads all the values of the attribute in the entry in the result. + * + * This function is used exactly like ldap_get_values + * except that it handles binary data and not string data. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_entry_identifier + * @param string $attribute + * @return array Returns an array of values for the attribute on success and FALSE on + * error. Individual values are accessed by integer index in the array. The + * first index is 0. The number of values can be found by indexing "count" + * in the resultant array. + * @throws LdapException + * + */ +function ldap_get_values_len($link_identifier, $result_entry_identifier, string $attribute): array +{ + error_clear_last(); + $result = \ldap_get_values_len($link_identifier, $result_entry_identifier, $attribute); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Reads all the values of the attribute in the entry in the result. + * + * This call needs a result_entry_identifier, + * so needs to be preceded by one of the ldap search calls and one + * of the calls to get an individual entry. + * + * You application will either be hard coded to look for certain + * attributes (such as "surname" or "mail") or you will have to use + * the ldap_get_attributes call to work out + * what attributes exist for a given entry. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_entry_identifier + * @param string $attribute + * @return array Returns an array of values for the attribute on success and FALSE on + * error. The number of values can be found by indexing "count" in the + * resultant array. Individual values are accessed by integer index in the + * array. The first index is 0. + * + * LDAP allows more than one entry for an attribute, so it can, for example, + * store a number of email addresses for one person's directory entry all + * labeled with the attribute "mail" + * + * + * return_value["count"] = number of values for attribute + * return_value[0] = first value of attribute + * return_value[i] = ith value of attribute + * + * + * @throws LdapException + * + */ +function ldap_get_values($link_identifier, $result_entry_identifier, string $attribute): array +{ + error_clear_last(); + $result = \ldap_get_values($link_identifier, $result_entry_identifier, $attribute); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Performs the search for a specified filter on the + * directory with the scope LDAP_SCOPE_ONELEVEL. + * + * LDAP_SCOPE_ONELEVEL means that the search should only + * return information that is at the level immediately below the + * base_dn given in the call. + * (Equivalent to typing "ls" and getting a list of files and folders in the + * current working directory.) + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $base_dn The base DN for the directory. + * @param string $filter + * @param array $attributes An array of the required attributes, e.g. array("mail", "sn", "cn"). + * Note that the "dn" is always returned irrespective of which attributes + * types are requested. + * + * Using this parameter is much more efficient than the default action + * (which is to return all attributes and their associated values). + * The use of this parameter should therefore be considered good + * practice. + * @param int $attrsonly Should be set to 1 if only attribute types are wanted. If set to 0 + * both attributes types and attribute values are fetched which is the + * default behaviour. + * @param int $sizelimit Enables you to limit the count of entries fetched. Setting this to 0 + * means no limit. + * + * This parameter can NOT override server-side preset sizelimit. You can + * set it lower though. + * + * Some directory server hosts will be configured to return no more than + * a preset number of entries. If this occurs, the server will indicate + * that it has only returned a partial results set. This also occurs if + * you use this parameter to limit the count of fetched entries. + * @param int $timelimit Sets the number of seconds how long is spend on the search. Setting + * this to 0 means no limit. + * + * This parameter can NOT override server-side preset timelimit. You can + * set it lower though. + * @param int $deref Specifies how aliases should be handled during the search. It can be + * one of the following: + * + * + * + * LDAP_DEREF_NEVER - (default) aliases are never + * dereferenced. + * + * + * + * + * LDAP_DEREF_SEARCHING - aliases should be + * dereferenced during the search but not when locating the base object + * of the search. + * + * + * + * + * LDAP_DEREF_FINDING - aliases should be + * dereferenced when locating the base object but not during the search. + * + * + * + * + * LDAP_DEREF_ALWAYS - aliases should be dereferenced + * always. + * + * + * + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @return resource Returns a search result identifier. + * @throws LdapException + * + */ +function ldap_list($link_identifier, string $base_dn, string $filter, array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $serverctrls = null) +{ + error_clear_last(); + if ($serverctrls !== null) { + $result = \ldap_list($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref, $serverctrls); + } elseif ($deref !== LDAP_DEREF_NEVER) { + $result = \ldap_list($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref); + } elseif ($timelimit !== -1) { + $result = \ldap_list($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit); + } elseif ($sizelimit !== -1) { + $result = \ldap_list($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit); + } elseif ($attrsonly !== 0) { + $result = \ldap_list($link_identifier, $base_dn, $filter, $attributes, $attrsonly); + } elseif ($attributes !== null) { + $result = \ldap_list($link_identifier, $base_dn, $filter, $attributes); + } else { + $result = \ldap_list($link_identifier, $base_dn, $filter); + } + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Does the same thing as ldap_mod_add but returns the LDAP result resource to be parsed with ldap_parse_result. + * + * @param resource $link_identifier + * @param string $dn + * @param array $entry + * @param array $serverctrls + * @return resource Returns an LDAP result identifier. + * @throws LdapException + * + */ +function ldap_mod_add_ext($link_identifier, string $dn, array $entry, array $serverctrls = null) +{ + error_clear_last(); + $result = \ldap_mod_add_ext($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Adds one or more attribute values to the specified dn. + * To add a whole new object see ldap_add function. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $dn The distinguished name of an LDAP entity. + * @param array $entry An associative array listing the attirbute values to add. If an attribute was not existing yet it will be added. If an attribute is existing you can only add values to it if it supports multiple values. + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @throws LdapException + * + */ +function ldap_mod_add($link_identifier, string $dn, array $entry, array $serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_mod_add($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Does the same thing as ldap_mod_del but returns the LDAP result resource to be parsed with ldap_parse_result. + * + * @param resource $link_identifier + * @param string $dn + * @param array $entry + * @param array $serverctrls + * @return resource Returns an LDAP result identifier. + * @throws LdapException + * + */ +function ldap_mod_del_ext($link_identifier, string $dn, array $entry, array $serverctrls = null) +{ + error_clear_last(); + $result = \ldap_mod_del_ext($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Removes one or more attribute values from the specified dn. + * Object deletions are done by the + * ldap_delete function. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $dn The distinguished name of an LDAP entity. + * @param array $entry + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @throws LdapException + * + */ +function ldap_mod_del($link_identifier, string $dn, array $entry, array $serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_mod_del($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Does the same thing as ldap_mod_replace but returns the LDAP result resource to be parsed with ldap_parse_result. + * + * @param resource $link_identifier + * @param string $dn + * @param array $entry + * @param array $serverctrls + * @return resource Returns an LDAP result identifier. + * @throws LdapException + * + */ +function ldap_mod_replace_ext($link_identifier, string $dn, array $entry, array $serverctrls = null) +{ + error_clear_last(); + $result = \ldap_mod_replace_ext($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Replaces one or more attributes from the specified dn. + * It may also add or remove attributes. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $dn The distinguished name of an LDAP entity. + * @param array $entry An associative array listing the attributes to replace. Sending an empty array as value will remove the attribute, while sending an attribute not existing yet on this entry will add it. + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @throws LdapException + * + */ +function ldap_mod_replace($link_identifier, string $dn, array $entry, array $serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_mod_replace($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Modifies an existing entry in the LDAP directory. Allows detailed + * specification of the modifications to perform. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $dn The distinguished name of an LDAP entity. + * @param array $entry An array that specifies the modifications to make. Each entry in this + * array is an associative array with two or three keys: + * attrib maps to the name of the attribute to modify, + * modtype maps to the type of modification to perform, + * and (depending on the type of modification) values + * maps to an array of attribute values relevant to the modification. + * + * Possible values for modtype include: + * + * + * LDAP_MODIFY_BATCH_ADD + * + * + * Each value specified through values is added (as + * an additional value) to the attribute named by + * attrib. + * + * + * + * + * LDAP_MODIFY_BATCH_REMOVE + * + * + * Each value specified through values is removed + * from the attribute named by attrib. Any value of + * the attribute not contained in the values array + * will remain untouched. + * + * + * + * + * LDAP_MODIFY_BATCH_REMOVE_ALL + * + * + * All values are removed from the attribute named by + * attrib. A values entry must + * not be provided. + * + * + * + * + * LDAP_MODIFY_BATCH_REPLACE + * + * + * All current values of the attribute named by + * attrib are replaced with the values specified + * through values. + * + * + * + * + * + * Each value specified through values is added (as + * an additional value) to the attribute named by + * attrib. + * + * Each value specified through values is removed + * from the attribute named by attrib. Any value of + * the attribute not contained in the values array + * will remain untouched. + * + * All values are removed from the attribute named by + * attrib. A values entry must + * not be provided. + * + * All current values of the attribute named by + * attrib are replaced with the values specified + * through values. + * + * Note that any value for attrib must be a string, any + * value for values must be an array of strings, and + * any value for modtype must be one of the + * LDAP_MODIFY_BATCH_* constants listed above. + * @param array $serverctrls Each value specified through values is added (as + * an additional value) to the attribute named by + * attrib. + * @throws LdapException + * + */ +function ldap_modify_batch($link_identifier, string $dn, array $entry, array $serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_modify_batch($link_identifier, $dn, $entry, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Retrieves the attributes in an entry. The first call to + * ldap_next_attribute is made with the + * result_entry_identifier returned from + * ldap_first_attribute. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param resource $result_entry_identifier + * @return string Returns the next attribute in an entry on success and FALSE on + * error. + * @throws LdapException + * + */ +function ldap_next_attribute($link_identifier, $result_entry_identifier): string +{ + error_clear_last(); + $result = \ldap_next_attribute($link_identifier, $result_entry_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Parse LDAP extended operation data from result object result + * + * @param resource $link An LDAP link identifier, returned by ldap_connect. + * @param resource $result An LDAP result resource, returned by ldap_exop. + * @param string|null $retdata Will be filled by the response data. + * @param string|null $retoid Will be filled by the response OID. + * @throws LdapException + * + */ +function ldap_parse_exop($link, $result, ?string &$retdata = null, ?string &$retoid = null): void +{ + error_clear_last(); + $result = \ldap_parse_exop($link, $result, $retdata, $retoid); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Parses an LDAP search result. + * + * @param resource $link An LDAP link identifier, returned by ldap_connect. + * @param resource $result An LDAP result resource, returned by ldap_list or + * ldap_search. + * @param int|null $errcode A reference to a variable that will be set to the LDAP error code in + * the result, or 0 if no error occurred. + * @param string|null $matcheddn A reference to a variable that will be set to a matched DN if one was + * recognised within the request, otherwise it will be set to NULL. + * @param string|null $errmsg A reference to a variable that will be set to the LDAP error message in + * the result, or an empty string if no error occurred. + * @param array|null $referrals A reference to a variable that will be set to an array set + * to all of the referral strings in the result, or an empty array if no + * referrals were returned. + * @param array|null $serverctrls An array of LDAP Controls which have been sent with the response. + * @throws LdapException + * + */ +function ldap_parse_result($link, $result, ?int &$errcode, ?string &$matcheddn = null, ?string &$errmsg = null, ?array &$referrals = null, ?array &$serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Performs the search for a specified filter on the + * directory with the scope LDAP_SCOPE_BASE. So it is + * equivalent to reading an entry from the directory. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $base_dn The base DN for the directory. + * @param string $filter An empty filter is not allowed. If you want to retrieve absolutely all + * information for this entry, use a filter of + * objectClass=*. If you know which entry types are + * used on the directory server, you might use an appropriate filter such + * as objectClass=inetOrgPerson. + * @param array $attributes An array of the required attributes, e.g. array("mail", "sn", "cn"). + * Note that the "dn" is always returned irrespective of which attributes + * types are requested. + * + * Using this parameter is much more efficient than the default action + * (which is to return all attributes and their associated values). + * The use of this parameter should therefore be considered good + * practice. + * @param int $attrsonly Should be set to 1 if only attribute types are wanted. If set to 0 + * both attributes types and attribute values are fetched which is the + * default behaviour. + * @param int $sizelimit Enables you to limit the count of entries fetched. Setting this to 0 + * means no limit. + * + * This parameter can NOT override server-side preset sizelimit. You can + * set it lower though. + * + * Some directory server hosts will be configured to return no more than + * a preset number of entries. If this occurs, the server will indicate + * that it has only returned a partial results set. This also occurs if + * you use this parameter to limit the count of fetched entries. + * @param int $timelimit Sets the number of seconds how long is spend on the search. Setting + * this to 0 means no limit. + * + * This parameter can NOT override server-side preset timelimit. You can + * set it lower though. + * @param int $deref Specifies how aliases should be handled during the search. It can be + * one of the following: + * + * + * + * LDAP_DEREF_NEVER - (default) aliases are never + * dereferenced. + * + * + * + * + * LDAP_DEREF_SEARCHING - aliases should be + * dereferenced during the search but not when locating the base object + * of the search. + * + * + * + * + * LDAP_DEREF_FINDING - aliases should be + * dereferenced when locating the base object but not during the search. + * + * + * + * + * LDAP_DEREF_ALWAYS - aliases should be dereferenced + * always. + * + * + * + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @return resource Returns a search result identifier. + * @throws LdapException + * + */ +function ldap_read($link_identifier, string $base_dn, string $filter, array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $serverctrls = null) +{ + error_clear_last(); + if ($serverctrls !== null) { + $result = \ldap_read($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref, $serverctrls); + } elseif ($deref !== LDAP_DEREF_NEVER) { + $result = \ldap_read($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref); + } elseif ($timelimit !== -1) { + $result = \ldap_read($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit); + } elseif ($sizelimit !== -1) { + $result = \ldap_read($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit); + } elseif ($attrsonly !== 0) { + $result = \ldap_read($link_identifier, $base_dn, $filter, $attributes, $attrsonly); + } elseif ($attributes !== null) { + $result = \ldap_read($link_identifier, $base_dn, $filter, $attributes); + } else { + $result = \ldap_read($link_identifier, $base_dn, $filter); + } + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Does the same thing as ldap_rename but returns the LDAP result resource to be parsed with ldap_parse_result. + * + * @param resource $link_identifier + * @param string $dn + * @param string $newrdn + * @param string $newparent + * @param bool $deleteoldrdn + * @param array $serverctrls + * @return resource Returns an LDAP result identifier. + * @throws LdapException + * + */ +function ldap_rename_ext($link_identifier, string $dn, string $newrdn, string $newparent, bool $deleteoldrdn, array $serverctrls = null) +{ + error_clear_last(); + $result = \ldap_rename_ext($link_identifier, $dn, $newrdn, $newparent, $deleteoldrdn, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * The entry specified by dn is renamed/moved. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $dn The distinguished name of an LDAP entity. + * @param string $newrdn The new RDN. + * @param string $newparent The new parent/superior entry. + * @param bool $deleteoldrdn If TRUE the old RDN value(s) is removed, else the old RDN value(s) + * is retained as non-distinguished values of the entry. + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @throws LdapException + * + */ +function ldap_rename($link_identifier, string $dn, string $newrdn, string $newparent, bool $deleteoldrdn, array $serverctrls = null): void +{ + error_clear_last(); + $result = \ldap_rename($link_identifier, $dn, $newrdn, $newparent, $deleteoldrdn, $serverctrls); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * + * + * @param resource $link + * @param string $binddn + * @param string $password + * @param string $sasl_mech + * @param string $sasl_realm + * @param string $sasl_authc_id + * @param string $sasl_authz_id + * @param string $props + * @throws LdapException + * + */ +function ldap_sasl_bind($link, string $binddn = null, string $password = null, string $sasl_mech = null, string $sasl_realm = null, string $sasl_authc_id = null, string $sasl_authz_id = null, string $props = null): void +{ + error_clear_last(); + $result = \ldap_sasl_bind($link, $binddn, $password, $sasl_mech, $sasl_realm, $sasl_authc_id, $sasl_authz_id, $props); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Performs the search for a specified filter on the directory with the scope + * of LDAP_SCOPE_SUBTREE. This is equivalent to searching + * the entire directory. + * + * From 4.0.5 on it's also possible to do parallel searches. To do this + * you use an array of link identifiers, rather than a single identifier, + * as the first argument. If you don't want the same base DN and the + * same filter for all the searches, you can also use an array of base DNs + * and/or an array of filters. Those arrays must be of the same size as + * the link identifier array since the first entries of the arrays are + * used for one search, the second entries are used for another, and so + * on. When doing parallel searches an array of search result + * identifiers is returned, except in case of error, then the entry + * corresponding to the search will be FALSE. This is very much like + * the value normally returned, except that a result identifier is always + * returned when a search was made. There are some rare cases where the + * normal search returns FALSE while the parallel search returns an + * identifier. + * + * @param resource|array $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param string $base_dn The base DN for the directory. + * @param string $filter The search filter can be simple or advanced, using boolean operators in + * the format described in the LDAP documentation (see the Netscape Directory SDK or + * RFC4515 for full + * information on filters). + * @param array $attributes An array of the required attributes, e.g. array("mail", "sn", "cn"). + * Note that the "dn" is always returned irrespective of which attributes + * types are requested. + * + * Using this parameter is much more efficient than the default action + * (which is to return all attributes and their associated values). + * The use of this parameter should therefore be considered good + * practice. + * @param int $attrsonly Should be set to 1 if only attribute types are wanted. If set to 0 + * both attributes types and attribute values are fetched which is the + * default behaviour. + * @param int $sizelimit Enables you to limit the count of entries fetched. Setting this to 0 + * means no limit. + * + * This parameter can NOT override server-side preset sizelimit. You can + * set it lower though. + * + * Some directory server hosts will be configured to return no more than + * a preset number of entries. If this occurs, the server will indicate + * that it has only returned a partial results set. This also occurs if + * you use this parameter to limit the count of fetched entries. + * @param int $timelimit Sets the number of seconds how long is spend on the search. Setting + * this to 0 means no limit. + * + * This parameter can NOT override server-side preset timelimit. You can + * set it lower though. + * @param int $deref Specifies how aliases should be handled during the search. It can be + * one of the following: + * + * + * + * LDAP_DEREF_NEVER - (default) aliases are never + * dereferenced. + * + * + * + * + * LDAP_DEREF_SEARCHING - aliases should be + * dereferenced during the search but not when locating the base object + * of the search. + * + * + * + * + * LDAP_DEREF_FINDING - aliases should be + * dereferenced when locating the base object but not during the search. + * + * + * + * + * LDAP_DEREF_ALWAYS - aliases should be dereferenced + * always. + * + * + * + * @param array $serverctrls Array of LDAP Controls to send with the request. + * @return resource Returns a search result identifier. + * @throws LdapException + * + */ +function ldap_search($link_identifier, string $base_dn, string $filter, array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $serverctrls = null) +{ + error_clear_last(); + if ($serverctrls !== null) { + $result = \ldap_search($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref, $serverctrls); + } elseif ($deref !== LDAP_DEREF_NEVER) { + $result = \ldap_search($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref); + } elseif ($timelimit !== -1) { + $result = \ldap_search($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit); + } elseif ($sizelimit !== -1) { + $result = \ldap_search($link_identifier, $base_dn, $filter, $attributes, $attrsonly, $sizelimit); + } elseif ($attrsonly !== 0) { + $result = \ldap_search($link_identifier, $base_dn, $filter, $attributes, $attrsonly); + } elseif ($attributes !== null) { + $result = \ldap_search($link_identifier, $base_dn, $filter, $attributes); + } else { + $result = \ldap_search($link_identifier, $base_dn, $filter); + } + if ($result === false) { + throw LdapException::createFromPhpError(); + } + return $result; +} + + +/** + * Sets the value of the specified option to be newval. + * + * @param resource|null $link_identifier An LDAP link identifier, returned by ldap_connect. + * @param int $option The parameter option can be one of: + * + * + * + * + * Option + * Type + * Available since + * + * + * + * + * LDAP_OPT_DEREF + * integer + * + * + * + * LDAP_OPT_SIZELIMIT + * integer + * + * + * + * LDAP_OPT_TIMELIMIT + * integer + * + * + * + * LDAP_OPT_NETWORK_TIMEOUT + * integer + * PHP 5.3.0 + * + * + * LDAP_OPT_PROTOCOL_VERSION + * integer + * + * + * + * LDAP_OPT_ERROR_NUMBER + * integer + * + * + * + * LDAP_OPT_REFERRALS + * bool + * + * + * + * LDAP_OPT_RESTART + * bool + * + * + * + * LDAP_OPT_HOST_NAME + * string + * + * + * + * LDAP_OPT_ERROR_STRING + * string + * + * + * + * LDAP_OPT_DIAGNOSTIC_MESSAGE + * string + * + * + * + * LDAP_OPT_MATCHED_DN + * string + * + * + * + * LDAP_OPT_SERVER_CONTROLS + * array + * + * + * + * LDAP_OPT_CLIENT_CONTROLS + * array + * + * + * + * LDAP_OPT_X_KEEPALIVE_IDLE + * int + * PHP 7.1.0 + * + * + * LDAP_OPT_X_KEEPALIVE_PROBES + * int + * PHP 7.1.0 + * + * + * LDAP_OPT_X_KEEPALIVE_INTERVAL + * int + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_CACERTDIR + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_CACERTFILE + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_CERTFILE + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_CIPHER_SUITE + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_CRLCHECK + * integer + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_CRLFILE + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_DHFILE + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_KEYFILE + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_PROTOCOL_MIN + * integer + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_RANDOM_FILE + * string + * PHP 7.1.0 + * + * + * LDAP_OPT_X_TLS_REQUIRE_CERT + * integer + * PHP 7.0.5 + * + * + * + * + * + * LDAP_OPT_SERVER_CONTROLS and + * LDAP_OPT_CLIENT_CONTROLS require a list of + * controls, this means that the value must be an array of controls. A + * control consists of an oid identifying the control, + * an optional value, and an optional flag for + * criticality. In PHP a control is given by an + * array containing an element with the key oid + * and string value, and two optional elements. The optional + * elements are key value with string value + * and key iscritical with boolean value. + * iscritical defaults to FALSE + * if not supplied. See draft-ietf-ldapext-ldap-c-api-xx.txt + * for details. See also the second example below. + * @param mixed $newval The new value for the specified option. + * @throws LdapException + * + */ +function ldap_set_option($link_identifier, int $option, $newval): void +{ + error_clear_last(); + $result = \ldap_set_option($link_identifier, $option, $newval); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} + + +/** + * Unbinds from the LDAP directory. + * + * @param resource $link_identifier An LDAP link identifier, returned by ldap_connect. + * @throws LdapException + * + */ +function ldap_unbind($link_identifier): void +{ + error_clear_last(); + $result = \ldap_unbind($link_identifier); + if ($result === false) { + throw LdapException::createFromPhpError(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/libxml.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/libxml.php new file mode 100644 index 00000000..cef784c4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/libxml.php @@ -0,0 +1,43 @@ + + * + * The above example will output: + * + * example: , this is a test + * example: , this is a test + * ]]> + * + * + * So, $out[0] contains array of strings that matched full pattern, + * and $out[1] contains array of strings enclosed by tags. + * + * + * + * + * If the pattern contains named subpatterns, $matches + * additionally contains entries for keys with the subpattern name. + * + * + * If the pattern contains duplicate named subpatterns, only the rightmost + * subpattern is stored in $matches[NAME]. + * + * + * + * ]]> + * + * The above example will output: + * + * + * [1] => bar + * ) + * ]]> + * + * + * + * + * + * + * PREG_SET_ORDER + * + * + * Orders results so that $matches[0] is an array of first set + * of matches, $matches[1] is an array of second set of matches, + * and so on. + * + * + * + * ]]> + * + * The above example will output: + * + * example: , example: + * this is a test, this is a test + * ]]> + * + * + * + * + * + * + * PREG_OFFSET_CAPTURE + * + * + * If this flag is passed, for every occurring match the appendant string + * offset (in bytes) will also be returned. Note that this changes the value of + * matches into an array of arrays where every element is an + * array consisting of the matched string at offset 0 + * and its string offset into subject at offset + * 1. + * + * + * + * ]]> + * + * The above example will output: + * + * Array + * ( + * [0] => Array + * ( + * [0] => foobarbaz + * [1] => 0 + * ) + * + * ) + * + * [1] => Array + * ( + * [0] => Array + * ( + * [0] => foo + * [1] => 0 + * ) + * + * ) + * + * [2] => Array + * ( + * [0] => Array + * ( + * [0] => bar + * [1] => 3 + * ) + * + * ) + * + * [3] => Array + * ( + * [0] => Array + * ( + * [0] => baz + * [1] => 6 + * ) + * + * ) + * + * ) + * ]]> + * + * + * + * + * + * + * PREG_UNMATCHED_AS_NULL + * + * + * If this flag is passed, unmatched subpatterns are reported as NULL; + * otherwise they are reported as an empty string. + * + * + * + * + * + * Orders results so that $matches[0] is an array of full + * pattern matches, $matches[1] is an array of strings matched by + * the first parenthesized subpattern, and so on. + * + * + * + * + * ]]> + * + * The above example will output: + * + * example: , this is a test + * example: , this is a test + * ]]> + * + * + * So, $out[0] contains array of strings that matched full pattern, + * and $out[1] contains array of strings enclosed by tags. + * + * + * + * The above example will output: + * + * So, $out[0] contains array of strings that matched full pattern, + * and $out[1] contains array of strings enclosed by tags. + * + * If the pattern contains named subpatterns, $matches + * additionally contains entries for keys with the subpattern name. + * + * If the pattern contains duplicate named subpatterns, only the rightmost + * subpattern is stored in $matches[NAME]. + * + * + * + * ]]> + * + * The above example will output: + * + * + * [1] => bar + * ) + * ]]> + * + * + * + * The above example will output: + * + * Orders results so that $matches[0] is an array of first set + * of matches, $matches[1] is an array of second set of matches, + * and so on. + * + * + * + * ]]> + * + * The above example will output: + * + * example: , example: + * this is a test, this is a test + * ]]> + * + * + * + * The above example will output: + * + * If this flag is passed, for every occurring match the appendant string + * offset (in bytes) will also be returned. Note that this changes the value of + * matches into an array of arrays where every element is an + * array consisting of the matched string at offset 0 + * and its string offset into subject at offset + * 1. + * + * + * + * ]]> + * + * The above example will output: + * + * Array + * ( + * [0] => Array + * ( + * [0] => foobarbaz + * [1] => 0 + * ) + * + * ) + * + * [1] => Array + * ( + * [0] => Array + * ( + * [0] => foo + * [1] => 0 + * ) + * + * ) + * + * [2] => Array + * ( + * [0] => Array + * ( + * [0] => bar + * [1] => 3 + * ) + * + * ) + * + * [3] => Array + * ( + * [0] => Array + * ( + * [0] => baz + * [1] => 6 + * ) + * + * ) + * + * ) + * ]]> + * + * + * + * The above example will output: + * + * If this flag is passed, unmatched subpatterns are reported as NULL; + * otherwise they are reported as an empty string. + * + * If no order flag is given, PREG_PATTERN_ORDER is + * assumed. + * @param int $offset Orders results so that $matches[0] is an array of full + * pattern matches, $matches[1] is an array of strings matched by + * the first parenthesized subpattern, and so on. + * + * + * + * + * ]]> + * + * The above example will output: + * + * example: , this is a test + * example: , this is a test + * ]]> + * + * + * So, $out[0] contains array of strings that matched full pattern, + * and $out[1] contains array of strings enclosed by tags. + * + * + * + * The above example will output: + * + * So, $out[0] contains array of strings that matched full pattern, + * and $out[1] contains array of strings enclosed by tags. + * + * If the pattern contains named subpatterns, $matches + * additionally contains entries for keys with the subpattern name. + * + * If the pattern contains duplicate named subpatterns, only the rightmost + * subpattern is stored in $matches[NAME]. + * + * + * + * ]]> + * + * The above example will output: + * + * + * [1] => bar + * ) + * ]]> + * + * + * + * The above example will output: + * @return int Returns the number of full pattern matches (which might be zero). + * @throws PcreException + * + */ +function preg_match_all(string $pattern, string $subject, array &$matches = null, int $flags = PREG_PATTERN_ORDER, int $offset = 0): int +{ + error_clear_last(); + $result = \preg_match_all($pattern, $subject, $matches, $flags, $offset); + if ($result === false) { + throw PcreException::createFromPhpError(); + } + return $result; +} + + +/** + * Searches subject for a match to the regular + * expression given in pattern. + * + * @param string $pattern The pattern to search for, as a string. + * @param string $subject The input string. + * @param array $matches If matches is provided, then it is filled with + * the results of search. $matches[0] will contain the + * text that matched the full pattern, $matches[1] + * will have the text that matched the first captured parenthesized + * subpattern, and so on. + * @param int $flags flags can be a combination of the following flags: + * + * + * PREG_OFFSET_CAPTURE + * + * + * If this flag is passed, for every occurring match the appendant string + * offset (in bytes) will also be returned. Note that this changes the value of + * matches into an array where every element is an + * array consisting of the matched string at offset 0 + * and its string offset into subject at offset + * 1. + * + * + * + * ]]> + * + * The above example will output: + * + * Array + * ( + * [0] => foobarbaz + * [1] => 0 + * ) + * + * [1] => Array + * ( + * [0] => foo + * [1] => 0 + * ) + * + * [2] => Array + * ( + * [0] => bar + * [1] => 3 + * ) + * + * [3] => Array + * ( + * [0] => baz + * [1] => 6 + * ) + * + * ) + * ]]> + * + * + * + * + * + * + * PREG_UNMATCHED_AS_NULL + * + * + * If this flag is passed, unmatched subpatterns are reported as NULL; + * otherwise they are reported as an empty string. + * + * + * + * ]]> + * + * The above example will output: + * + * + * string(2) "ac" + * [1]=> + * string(1) "a" + * [2]=> + * string(0) "" + * [3]=> + * string(1) "c" + * } + * array(4) { + * [0]=> + * string(2) "ac" + * [1]=> + * string(1) "a" + * [2]=> + * NULL + * [3]=> + * string(1) "c" + * } + * ]]> + * + * + * + * + * + * + * + * If this flag is passed, for every occurring match the appendant string + * offset (in bytes) will also be returned. Note that this changes the value of + * matches into an array where every element is an + * array consisting of the matched string at offset 0 + * and its string offset into subject at offset + * 1. + * + * + * + * ]]> + * + * The above example will output: + * + * Array + * ( + * [0] => foobarbaz + * [1] => 0 + * ) + * + * [1] => Array + * ( + * [0] => foo + * [1] => 0 + * ) + * + * [2] => Array + * ( + * [0] => bar + * [1] => 3 + * ) + * + * [3] => Array + * ( + * [0] => baz + * [1] => 6 + * ) + * + * ) + * ]]> + * + * + * + * The above example will output: + * + * If this flag is passed, unmatched subpatterns are reported as NULL; + * otherwise they are reported as an empty string. + * + * + * + * ]]> + * + * The above example will output: + * + * + * string(2) "ac" + * [1]=> + * string(1) "a" + * [2]=> + * string(0) "" + * [3]=> + * string(1) "c" + * } + * array(4) { + * [0]=> + * string(2) "ac" + * [1]=> + * string(1) "a" + * [2]=> + * NULL + * [3]=> + * string(1) "c" + * } + * ]]> + * + * + * + * The above example will output: + * @param int $offset If this flag is passed, for every occurring match the appendant string + * offset (in bytes) will also be returned. Note that this changes the value of + * matches into an array where every element is an + * array consisting of the matched string at offset 0 + * and its string offset into subject at offset + * 1. + * + * + * + * ]]> + * + * The above example will output: + * + * Array + * ( + * [0] => foobarbaz + * [1] => 0 + * ) + * + * [1] => Array + * ( + * [0] => foo + * [1] => 0 + * ) + * + * [2] => Array + * ( + * [0] => bar + * [1] => 3 + * ) + * + * [3] => Array + * ( + * [0] => baz + * [1] => 6 + * ) + * + * ) + * ]]> + * + * + * + * The above example will output: + * @return int preg_match returns 1 if the pattern + * matches given subject, 0 if it does not. + * @throws PcreException + * + */ +function preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int +{ + error_clear_last(); + $result = \preg_match($pattern, $subject, $matches, $flags, $offset); + if ($result === false) { + throw PcreException::createFromPhpError(); + } + return $result; +} + + +/** + * Split the given string by a regular expression. + * + * @param string $pattern The pattern to search for, as a string. + * @param string $subject The input string. + * @param int|null $limit If specified, then only substrings up to limit + * are returned with the rest of the string being placed in the last + * substring. A limit of -1 or 0 means "no limit". + * @param int $flags flags can be any combination of the following + * flags (combined with the | bitwise operator): + * + * + * PREG_SPLIT_NO_EMPTY + * + * + * If this flag is set, only non-empty pieces will be returned by + * preg_split. + * + * + * + * + * PREG_SPLIT_DELIM_CAPTURE + * + * + * If this flag is set, parenthesized expression in the delimiter pattern + * will be captured and returned as well. + * + * + * + * + * PREG_SPLIT_OFFSET_CAPTURE + * + * + * If this flag is set, for every occurring match the appendant string + * offset will also be returned. Note that this changes the return + * value in an array where every element is an array consisting of the + * matched string at offset 0 and its string offset + * into subject at offset 1. + * + * + * + * + * + * If this flag is set, for every occurring match the appendant string + * offset will also be returned. Note that this changes the return + * value in an array where every element is an array consisting of the + * matched string at offset 0 and its string offset + * into subject at offset 1. + * @return array Returns an array containing substrings of subject + * split along boundaries matched by pattern. + * @throws PcreException + * + */ +function preg_split(string $pattern, string $subject, ?int $limit = -1, int $flags = 0): array +{ + error_clear_last(); + $result = \preg_split($pattern, $subject, $limit, $flags); + if ($result === false) { + throw PcreException::createFromPhpError(); + } + return $result; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pdf.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pdf.php new file mode 100644 index 00000000..d039b27a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/pdf.php @@ -0,0 +1,1553 @@ + + * ]]> + * + * + * + * @param string $prompt The prompt message. + * @param callable $callback The callback function takes one parameter; the + * user input returned. + * @throws ReadlineException + * + */ +function readline_callback_handler_install(string $prompt, callable $callback): void +{ + error_clear_last(); + $result = \readline_callback_handler_install($prompt, $callback); + if ($result === false) { + throw ReadlineException::createFromPhpError(); + } +} + + +/** + * This function clears the entire command line history. + * + * @throws ReadlineException + * + */ +function readline_clear_history(): void +{ + error_clear_last(); + $result = \readline_clear_history(); + if ($result === false) { + throw ReadlineException::createFromPhpError(); + } +} + + +/** + * This function registers a completion function. This is the same kind of + * functionality you'd get if you hit your tab key while using Bash. + * + * @param callable $function You must supply the name of an existing function which accepts a + * partial command line and returns an array of possible matches. + * @throws ReadlineException + * + */ +function readline_completion_function(callable $function): void +{ + error_clear_last(); + $result = \readline_completion_function($function); + if ($result === false) { + throw ReadlineException::createFromPhpError(); + } +} + + +/** + * This function reads a command history from a file. + * + * @param string $filename Path to the filename containing the command history. + * @throws ReadlineException + * + */ +function readline_read_history(string $filename = null): void +{ + error_clear_last(); + if ($filename !== null) { + $result = \readline_read_history($filename); + } else { + $result = \readline_read_history(); + } + if ($result === false) { + throw ReadlineException::createFromPhpError(); + } +} + + +/** + * This function writes the command history to a file. + * + * @param string $filename Path to the saved file. + * @throws ReadlineException + * + */ +function readline_write_history(string $filename = null): void +{ + error_clear_last(); + if ($filename !== null) { + $result = \readline_write_history($filename); + } else { + $result = \readline_write_history(); + } + if ($result === false) { + throw ReadlineException::createFromPhpError(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/rpminfo.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/rpminfo.php new file mode 100644 index 00000000..44de1ce2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/rpminfo.php @@ -0,0 +1,21 @@ + + * + * + * @param int $length If length is given and is positive, the string + * returned will contain at most length characters + * beginning from start (depending on the length of + * string). + * + * If length is given and is negative, then that many + * characters will be omitted from the end of string + * (after the start position has been calculated when a + * start is negative). If + * start denotes the position of this truncation or + * beyond, FALSE will be returned. + * + * If length is given and is 0, + * FALSE or NULL, an empty string will be returned. + * + * If length is omitted, the substring starting from + * start until the end of the string will be + * returned. + * @return string Returns the extracted part of string;, or + * an empty string. + * @throws StringsException + * + */ +function substr(string $string, int $start, int $length = null): string +{ + error_clear_last(); + if ($length !== null) { + $result = \substr($string, $start, $length); + } else { + $result = \substr($string, $start); + } + if ($result === false) { + throw StringsException::createFromPhpError(); + } + return $result; +} + + +/** + * Operates as sprintf but accepts an array of + * arguments, rather than a variable number of arguments. + * + * @param string $format The format string is composed of zero or more directives: + * ordinary characters (excluding %) that are + * copied directly to the result and conversion + * specifications, each of which results in fetching its + * own parameter. + * + * A conversion specification follows this prototype: + * %[argnum$][flags][width][.precision]specifier. + * + * An integer followed by a dollar sign $, + * to specify which number argument to treat in the conversion. + * + * + * Flags + * + * + * + * Flag + * Description + * + * + * + * + * - + * + * Left-justify within the given field width; + * Right justification is the default + * + * + * + * + + * + * Prefix positive numbers with a plus sign + * +; Default only negative + * are prefixed with a negative sign. + * + * + * + * (space) + * + * Pads the result with spaces. + * This is the default. + * + * + * + * 0 + * + * Only left-pads numbers with zeros. + * With s specifiers this can + * also right-pad with zeros. + * + * + * + * '(char) + * + * Pads the result with the character (char). + * + * + * + * + * + * + * An integer that says how many characters (minimum) + * this conversion should result in. + * + * A period . followed by an integer + * who's meaning depends on the specifier: + * + * + * + * For e, E, + * f and F + * specifiers: this is the number of digits to be printed + * after the decimal point (by default, this is 6). + * + * + * + * + * For g and G + * specifiers: this is the maximum number of significant + * digits to be printed. + * + * + * + * + * For s specifier: it acts as a cutoff point, + * setting a maximum character limit to the string. + * + * + * + * + * + * If the period is specified without an explicit value for precision, + * 0 is assumed. + * + * + * + * + * Specifiers + * + * + * + * Specifier + * Description + * + * + * + * + * % + * + * A literal percent character. No argument is required. + * + * + * + * b + * + * The argument is treated as an integer and presented + * as a binary number. + * + * + * + * c + * + * The argument is treated as an integer and presented + * as the character with that ASCII. + * + * + * + * d + * + * The argument is treated as an integer and presented + * as a (signed) decimal number. + * + * + * + * e + * + * The argument is treated as scientific notation (e.g. 1.2e+2). + * The precision specifier stands for the number of digits after the + * decimal point since PHP 5.2.1. In earlier versions, it was taken as + * number of significant digits (one less). + * + * + * + * E + * + * Like the e specifier but uses + * uppercase letter (e.g. 1.2E+2). + * + * + * + * f + * + * The argument is treated as a float and presented + * as a floating-point number (locale aware). + * + * + * + * F + * + * The argument is treated as a float and presented + * as a floating-point number (non-locale aware). + * Available as of PHP 5.0.3. + * + * + * + * g + * + * + * General format. + * + * + * Let P equal the precision if nonzero, 6 if the precision is omitted, + * or 1 if the precision is zero. + * Then, if a conversion with style E would have an exponent of X: + * + * + * If P > X ≥ −4, the conversion is with style f and precision P − (X + 1). + * Otherwise, the conversion is with style e and precision P − 1. + * + * + * + * + * G + * + * Like the g specifier but uses + * E and f. + * + * + * + * o + * + * The argument is treated as an integer and presented + * as an octal number. + * + * + * + * s + * + * The argument is treated and presented as a string. + * + * + * + * u + * + * The argument is treated as an integer and presented + * as an unsigned decimal number. + * + * + * + * x + * + * The argument is treated as an integer and presented + * as a hexadecimal number (with lowercase letters). + * + * + * + * X + * + * The argument is treated as an integer and presented + * as a hexadecimal number (with uppercase letters). + * + * + * + * + * + * + * General format. + * + * Let P equal the precision if nonzero, 6 if the precision is omitted, + * or 1 if the precision is zero. + * Then, if a conversion with style E would have an exponent of X: + * + * If P > X ≥ −4, the conversion is with style f and precision P − (X + 1). + * Otherwise, the conversion is with style e and precision P − 1. + * + * The c type specifier ignores padding and width + * + * Attempting to use a combination of the string and width specifiers with character sets that require more than one byte per character may result in unexpected results + * + * Variables will be co-erced to a suitable type for the specifier: + * + * Type Handling + * + * + * + * Type + * Specifiers + * + * + * + * + * string + * s + * + * + * integer + * + * d, + * u, + * c, + * o, + * x, + * X, + * b + * + * + * + * double + * + * g, + * G, + * e, + * E, + * f, + * F + * + * + * + * + * + * @param array $args + * @return string Return array values as a formatted string according to + * format. + * @throws StringsException + * + */ +function vsprintf(string $format, array $args): string +{ + error_clear_last(); + $result = \vsprintf($format, $args); + if ($result === false) { + throw StringsException::createFromPhpError(); + } + return $result; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/swoole.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/swoole.php new file mode 100644 index 00000000..334d96bd --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/generated/swoole.php @@ -0,0 +1,108 @@ +format('Y-m-d H:i:s.u'), $datetime->getTimezone()); + } + + /** + * @param string $format + * @param string $time + * @param DateTimeZone|null $timezone + * @throws DatetimeException + */ + public static function createFromFormat($format, $time, $timezone = null): self + { + $datetime = parent::createFromFormat($format, $time, $timezone); + if ($datetime === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($datetime); + } + + /** + * @param DateTimeInterface $datetime2 The date to compare to. + * @param boolean $absolute [optional] Whether to return absolute difference. + * @return DateInterval The DateInterval object representing the difference between the two dates. + * @throws DatetimeException + */ + public function diff($datetime2, $absolute = false): DateInterval + { + /** @var \DateInterval|false $result */ + $result = parent::diff($datetime2, $absolute); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return $result; + } + + /** + * @param string $modify A date/time string. Valid formats are explained in Date and Time Formats. + * @return DateTime Returns the DateTime object for method chaining. + * @throws DatetimeException + */ + public function modify($modify): self + { + /** @var DateTime|false $result */ + $result = parent::modify($modify); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return $result; + } + + /** + * @param int $year + * @param int $month + * @param int $day + * @return DateTime + * @throws DatetimeException + */ + public function setDate($year, $month, $day): self + { + /** @var DateTime|false $result */ + $result = parent::setDate($year, $month, $day); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/DateTimeImmutable.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/DateTimeImmutable.php new file mode 100644 index 00000000..114ec3a3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/DateTimeImmutable.php @@ -0,0 +1,262 @@ +innerDateTime = new parent($time, $timezone); + } + + //switch between regular datetime and safe version + public static function createFromRegular(\DateTimeImmutable $datetime): self + { + $safeDatetime = new self($datetime->format('Y-m-d H:i:s.u'), $datetime->getTimezone()); //we need to also update the wrapper to not break the operators '<' and '>' + $safeDatetime->innerDateTime = $datetime; //to make sure we don't lose information because of the format(). + return $safeDatetime; + } + + //usefull if you need to switch back to regular DateTimeImmutable (for example when using DatePeriod) + public function getInnerDateTime(): \DateTimeImmutable + { + return $this->innerDateTime; + } + + ///////////////////////////////////////////////////////////////////////////// + // overload functions with false errors + + /** + * @param string $format + * @param string $time + * @param DateTimeZone|null $timezone + * @throws DatetimeException + */ + public static function createFromFormat($format, $time, $timezone = null): self + { + $datetime = parent::createFromFormat($format, $time, $timezone); + if ($datetime === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($datetime); + } + + /** + * @param string $format + * @return string + * @throws DatetimeException + */ + public function format($format): string + { + /** @var string|false $result */ + $result = $this->innerDateTime->format($format); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return $result; + } + + /** + * @param DateTimeInterface $datetime2 + * @param bool $absolute + * @return DateInterval + * @throws DatetimeException + */ + public function diff($datetime2, $absolute = false): DateInterval + { + /** @var \DateInterval|false $result */ + $result = $this->innerDateTime->diff($datetime2, $absolute); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return $result; + } + + /** + * @param string $modify + * @return DateTimeImmutable + * @throws DatetimeException + */ + public function modify($modify): self + { + /** @var \DateTimeImmutable|false $result */ + $result = $this->innerDateTime->modify($modify); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($result); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable + } + + /** + * @param int $year + * @param int $month + * @param int $day + * @return DateTimeImmutable + * @throws DatetimeException + */ + public function setDate($year, $month, $day): self + { + /** @var \DateTimeImmutable|false $result */ + $result = $this->innerDateTime->setDate($year, $month, $day); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($result); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable + } + + /** + * @param int $year + * @param int $week + * @param int $day + * @return DateTimeImmutable + * @throws DatetimeException + */ + public function setISODate($year, $week, $day = 1): self + { + /** @var \DateTimeImmutable|false $result */ + $result = $this->innerDateTime->setISODate($year, $week, $day); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($result); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable + } + + /** + * @param int $hour + * @param int $minute + * @param int $second + * @param int $microseconds + * @return DateTimeImmutable + * @throws DatetimeException + */ + public function setTime($hour, $minute, $second = 0, $microseconds = 0): self + { + /** @var \DateTimeImmutable|false $result */ + $result = $this->innerDateTime->setTime($hour, $minute, $second, $microseconds); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($result); + } + + /** + * @param int $unixtimestamp + * @return DateTimeImmutable + * @throws DatetimeException + */ + public function setTimestamp($unixtimestamp): self + { + /** @var \DateTimeImmutable|false $result */ + $result = $this->innerDateTime->setTimestamp($unixtimestamp); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($result); + } + + /** + * @param DateTimeZone $timezone + * @return DateTimeImmutable + * @throws DatetimeException + */ + public function setTimezone($timezone): self + { + /** @var \DateTimeImmutable|false $result */ + $result = $this->innerDateTime->setTimezone($timezone); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($result); + } + + /** + * @param DateInterval $interval + * @return DateTimeImmutable + * @throws DatetimeException + */ + public function sub($interval): self + { + /** @var \DateTimeImmutable|false $result */ + $result = $this->innerDateTime->sub($interval); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return self::createFromRegular($result); + } + + /** + * @throws DatetimeException + */ + public function getOffset(): int + { + /** @var int|false $result */ + $result = $this->innerDateTime->getOffset(); + if ($result === false) { + throw DatetimeException::createFromPhpError(); + } + return $result; + } + + ////////////////////////////////////////////////////////////////////////////////////////// + //overload getters to use the inner datetime immutable instead of itself + + /** + * @param DateInterval $interval + * @return DateTimeImmutable + */ + public function add($interval): self + { + return self::createFromRegular($this->innerDateTime->add($interval)); + } + + /** + * @param DateTime $dateTime + * @return DateTimeImmutable + */ + public static function createFromMutable($dateTime): self + { + return self::createFromRegular(parent::createFromMutable($dateTime)); + } + + /** + * @param mixed[] $array + * @return DateTimeImmutable + */ + public static function __set_state($array): self + { + return self::createFromRegular(parent::__set_state($array)); + } + + public function getTimezone(): DateTimeZone + { + return $this->innerDateTime->getTimezone(); + } + + public function getTimestamp(): int + { + return $this->innerDateTime->getTimestamp(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/CurlException.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/CurlException.php new file mode 100644 index 00000000..2814066b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/CurlException.php @@ -0,0 +1,15 @@ + 'PREG_INTERNAL_ERROR: Internal error', + PREG_BACKTRACK_LIMIT_ERROR => 'PREG_BACKTRACK_LIMIT_ERROR: Backtrack limit reached', + PREG_RECURSION_LIMIT_ERROR => 'PREG_RECURSION_LIMIT_ERROR: Recursion limit reached', + PREG_BAD_UTF8_ERROR => 'PREG_BAD_UTF8_ERROR: Invalid UTF8 character', + PREG_BAD_UTF8_OFFSET_ERROR => 'PREG_BAD_UTF8_OFFSET_ERROR', + PREG_JIT_STACKLIMIT_ERROR => 'PREG_JIT_STACKLIMIT_ERROR', + ]; + $errMsg = $errorMap[preg_last_error()] ?? 'Unknown PCRE error: '.preg_last_error(); + return new self($errMsg, \preg_last_error()); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/SafeExceptionInterface.php b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/SafeExceptionInterface.php new file mode 100644 index 00000000..fbea6ad2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/thecodingmachine/safe/lib/Exceptions/SafeExceptionInterface.php @@ -0,0 +1,9 @@ +services(); + + $services->set(RenameFunctionRector::class) + ->call('configure', [[ RenameFunctionRector::OLD_FUNCTION_TO_NEW_FUNCTION => [ + 'apache_getenv' => 'Safe\apache_getenv', + 'apache_get_version' => 'Safe\apache_get_version', + 'apache_request_headers' => 'Safe\apache_request_headers', + 'apache_reset_timeout' => 'Safe\apache_reset_timeout', + 'apache_response_headers' => 'Safe\apache_response_headers', + 'apache_setenv' => 'Safe\apache_setenv', + 'apcu_cache_info' => 'Safe\apcu_cache_info', + 'apcu_cas' => 'Safe\apcu_cas', + 'apcu_dec' => 'Safe\apcu_dec', + 'apcu_fetch' => 'Safe\apcu_fetch', + 'apcu_inc' => 'Safe\apcu_inc', + 'apcu_sma_info' => 'Safe\apcu_sma_info', + 'apc_fetch' => 'Safe\apc_fetch', + 'array_combine' => 'Safe\array_combine', + 'array_flip' => 'Safe\array_flip', + 'array_replace' => 'Safe\array_replace', + 'array_replace_recursive' => 'Safe\array_replace_recursive', + 'array_walk_recursive' => 'Safe\array_walk_recursive', + 'arsort' => 'Safe\arsort', + 'asort' => 'Safe\asort', + 'base64_decode' => 'Safe\base64_decode', + 'bzclose' => 'Safe\bzclose', + 'bzflush' => 'Safe\bzflush', + 'bzread' => 'Safe\bzread', + 'bzwrite' => 'Safe\bzwrite', + 'chdir' => 'Safe\chdir', + 'chgrp' => 'Safe\chgrp', + 'chmod' => 'Safe\chmod', + 'chown' => 'Safe\chown', + 'chroot' => 'Safe\chroot', + 'class_alias' => 'Safe\class_alias', + 'class_implements' => 'Safe\class_implements', + 'class_parents' => 'Safe\class_parents', + 'class_uses' => 'Safe\class_uses', + 'cli_set_process_title' => 'Safe\cli_set_process_title', + 'closelog' => 'Safe\closelog', + 'com_event_sink' => 'Safe\com_event_sink', + 'com_load_typelib' => 'Safe\com_load_typelib', + 'com_print_typeinfo' => 'Safe\com_print_typeinfo', + 'convert_uudecode' => 'Safe\convert_uudecode', + 'convert_uuencode' => 'Safe\convert_uuencode', + 'copy' => 'Safe\copy', + 'create_function' => 'Safe\create_function', + 'cubrid_free_result' => 'Safe\cubrid_free_result', + 'cubrid_get_charset' => 'Safe\cubrid_get_charset', + 'cubrid_get_client_info' => 'Safe\cubrid_get_client_info', + 'cubrid_get_db_parameter' => 'Safe\cubrid_get_db_parameter', + 'cubrid_get_server_info' => 'Safe\cubrid_get_server_info', + 'cubrid_insert_id' => 'Safe\cubrid_insert_id', + 'cubrid_lob2_new' => 'Safe\cubrid_lob2_new', + 'cubrid_lob2_size' => 'Safe\cubrid_lob2_size', + 'cubrid_lob2_size64' => 'Safe\cubrid_lob2_size64', + 'cubrid_lob2_tell' => 'Safe\cubrid_lob2_tell', + 'cubrid_lob2_tell64' => 'Safe\cubrid_lob2_tell64', + 'cubrid_set_db_parameter' => 'Safe\cubrid_set_db_parameter', + 'curl_escape' => 'Safe\curl_escape', + 'curl_exec' => 'Safe\curl_exec', + 'curl_getinfo' => 'Safe\curl_getinfo', + 'curl_init' => 'Safe\curl_init', + 'curl_multi_errno' => 'Safe\curl_multi_errno', + 'curl_multi_info_read' => 'Safe\curl_multi_info_read', + 'curl_multi_init' => 'Safe\curl_multi_init', + 'curl_setopt' => 'Safe\curl_setopt', + 'curl_share_errno' => 'Safe\curl_share_errno', + 'curl_share_setopt' => 'Safe\curl_share_setopt', + 'curl_unescape' => 'Safe\curl_unescape', + 'date' => 'Safe\date', + 'date_parse' => 'Safe\date_parse', + 'date_parse_from_format' => 'Safe\date_parse_from_format', + 'date_sunrise' => 'Safe\date_sunrise', + 'date_sunset' => 'Safe\date_sunset', + 'date_sun_info' => 'Safe\date_sun_info', + 'db2_autocommit' => 'Safe\db2_autocommit', + 'db2_bind_param' => 'Safe\db2_bind_param', + 'db2_client_info' => 'Safe\db2_client_info', + 'db2_close' => 'Safe\db2_close', + 'db2_commit' => 'Safe\db2_commit', + 'db2_execute' => 'Safe\db2_execute', + 'db2_free_result' => 'Safe\db2_free_result', + 'db2_free_stmt' => 'Safe\db2_free_stmt', + 'db2_get_option' => 'Safe\db2_get_option', + 'db2_pclose' => 'Safe\db2_pclose', + 'db2_rollback' => 'Safe\db2_rollback', + 'db2_server_info' => 'Safe\db2_server_info', + 'db2_set_option' => 'Safe\db2_set_option', + 'define' => 'Safe\define', + 'deflate_add' => 'Safe\deflate_add', + 'deflate_init' => 'Safe\deflate_init', + 'disk_free_space' => 'Safe\disk_free_space', + 'disk_total_space' => 'Safe\disk_total_space', + 'dl' => 'Safe\dl', + 'dns_get_record' => 'Safe\dns_get_record', + 'eio_busy' => 'Safe\eio_busy', + 'eio_chmod' => 'Safe\eio_chmod', + 'eio_chown' => 'Safe\eio_chown', + 'eio_close' => 'Safe\eio_close', + 'eio_custom' => 'Safe\eio_custom', + 'eio_dup2' => 'Safe\eio_dup2', + 'eio_event_loop' => 'Safe\eio_event_loop', + 'eio_fallocate' => 'Safe\eio_fallocate', + 'eio_fchmod' => 'Safe\eio_fchmod', + 'eio_fdatasync' => 'Safe\eio_fdatasync', + 'eio_fstat' => 'Safe\eio_fstat', + 'eio_fstatvfs' => 'Safe\eio_fstatvfs', + 'eio_fsync' => 'Safe\eio_fsync', + 'eio_ftruncate' => 'Safe\eio_ftruncate', + 'eio_futime' => 'Safe\eio_futime', + 'eio_grp' => 'Safe\eio_grp', + 'eio_lstat' => 'Safe\eio_lstat', + 'eio_mkdir' => 'Safe\eio_mkdir', + 'eio_mknod' => 'Safe\eio_mknod', + 'eio_nop' => 'Safe\eio_nop', + 'eio_readahead' => 'Safe\eio_readahead', + 'eio_readdir' => 'Safe\eio_readdir', + 'eio_readlink' => 'Safe\eio_readlink', + 'eio_rename' => 'Safe\eio_rename', + 'eio_rmdir' => 'Safe\eio_rmdir', + 'eio_seek' => 'Safe\eio_seek', + 'eio_sendfile' => 'Safe\eio_sendfile', + 'eio_stat' => 'Safe\eio_stat', + 'eio_statvfs' => 'Safe\eio_statvfs', + 'eio_symlink' => 'Safe\eio_symlink', + 'eio_sync' => 'Safe\eio_sync', + 'eio_syncfs' => 'Safe\eio_syncfs', + 'eio_sync_file_range' => 'Safe\eio_sync_file_range', + 'eio_truncate' => 'Safe\eio_truncate', + 'eio_unlink' => 'Safe\eio_unlink', + 'eio_utime' => 'Safe\eio_utime', + 'eio_write' => 'Safe\eio_write', + 'error_log' => 'Safe\error_log', + 'fastcgi_finish_request' => 'Safe\fastcgi_finish_request', + 'fbird_blob_cancel' => 'Safe\fbird_blob_cancel', + 'fclose' => 'Safe\fclose', + 'fflush' => 'Safe\fflush', + 'file' => 'Safe\file', + 'fileatime' => 'Safe\fileatime', + 'filectime' => 'Safe\filectime', + 'fileinode' => 'Safe\fileinode', + 'filemtime' => 'Safe\filemtime', + 'fileowner' => 'Safe\fileowner', + 'filesize' => 'Safe\filesize', + 'file_get_contents' => 'Safe\file_get_contents', + 'file_put_contents' => 'Safe\file_put_contents', + 'filter_input_array' => 'Safe\filter_input_array', + 'filter_var_array' => 'Safe\filter_var_array', + 'finfo_close' => 'Safe\finfo_close', + 'finfo_open' => 'Safe\finfo_open', + 'flock' => 'Safe\flock', + 'fopen' => 'Safe\fopen', + 'fputcsv' => 'Safe\fputcsv', + 'fread' => 'Safe\fread', + 'fsockopen' => 'Safe\fsockopen', + 'ftp_alloc' => 'Safe\ftp_alloc', + 'ftp_append' => 'Safe\ftp_append', + 'ftp_cdup' => 'Safe\ftp_cdup', + 'ftp_chdir' => 'Safe\ftp_chdir', + 'ftp_chmod' => 'Safe\ftp_chmod', + 'ftp_close' => 'Safe\ftp_close', + 'ftp_connect' => 'Safe\ftp_connect', + 'ftp_delete' => 'Safe\ftp_delete', + 'ftp_fget' => 'Safe\ftp_fget', + 'ftp_fput' => 'Safe\ftp_fput', + 'ftp_get' => 'Safe\ftp_get', + 'ftp_login' => 'Safe\ftp_login', + 'ftp_mkdir' => 'Safe\ftp_mkdir', + 'ftp_mlsd' => 'Safe\ftp_mlsd', + 'ftp_nlist' => 'Safe\ftp_nlist', + 'ftp_pasv' => 'Safe\ftp_pasv', + 'ftp_put' => 'Safe\ftp_put', + 'ftp_pwd' => 'Safe\ftp_pwd', + 'ftp_rename' => 'Safe\ftp_rename', + 'ftp_rmdir' => 'Safe\ftp_rmdir', + 'ftp_site' => 'Safe\ftp_site', + 'ftp_ssl_connect' => 'Safe\ftp_ssl_connect', + 'ftp_systype' => 'Safe\ftp_systype', + 'ftruncate' => 'Safe\ftruncate', + 'fwrite' => 'Safe\fwrite', + 'getallheaders' => 'Safe\getallheaders', + 'getcwd' => 'Safe\getcwd', + 'gethostname' => 'Safe\gethostname', + 'getimagesize' => 'Safe\getimagesize', + 'getlastmod' => 'Safe\getlastmod', + 'getmygid' => 'Safe\getmygid', + 'getmyinode' => 'Safe\getmyinode', + 'getmypid' => 'Safe\getmypid', + 'getmyuid' => 'Safe\getmyuid', + 'getopt' => 'Safe\getopt', + 'getprotobyname' => 'Safe\getprotobyname', + 'getprotobynumber' => 'Safe\getprotobynumber', + 'get_headers' => 'Safe\get_headers', + 'glob' => 'Safe\glob', + 'gmdate' => 'Safe\gmdate', + 'gmp_binomial' => 'Safe\gmp_binomial', + 'gmp_export' => 'Safe\gmp_export', + 'gmp_import' => 'Safe\gmp_import', + 'gmp_random_seed' => 'Safe\gmp_random_seed', + 'gnupg_adddecryptkey' => 'Safe\gnupg_adddecryptkey', + 'gnupg_addencryptkey' => 'Safe\gnupg_addencryptkey', + 'gnupg_addsignkey' => 'Safe\gnupg_addsignkey', + 'gnupg_cleardecryptkeys' => 'Safe\gnupg_cleardecryptkeys', + 'gnupg_clearencryptkeys' => 'Safe\gnupg_clearencryptkeys', + 'gnupg_clearsignkeys' => 'Safe\gnupg_clearsignkeys', + 'gnupg_setarmor' => 'Safe\gnupg_setarmor', + 'gnupg_setsignmode' => 'Safe\gnupg_setsignmode', + 'gzclose' => 'Safe\gzclose', + 'gzcompress' => 'Safe\gzcompress', + 'gzdecode' => 'Safe\gzdecode', + 'gzdeflate' => 'Safe\gzdeflate', + 'gzencode' => 'Safe\gzencode', + 'gzgets' => 'Safe\gzgets', + 'gzgetss' => 'Safe\gzgetss', + 'gzinflate' => 'Safe\gzinflate', + 'gzpassthru' => 'Safe\gzpassthru', + 'gzrewind' => 'Safe\gzrewind', + 'gzuncompress' => 'Safe\gzuncompress', + 'hash_hkdf' => 'Safe\hash_hkdf', + 'hash_update_file' => 'Safe\hash_update_file', + 'header_register_callback' => 'Safe\header_register_callback', + 'hex2bin' => 'Safe\hex2bin', + 'highlight_file' => 'Safe\highlight_file', + 'highlight_string' => 'Safe\highlight_string', + 'ibase_add_user' => 'Safe\ibase_add_user', + 'ibase_backup' => 'Safe\ibase_backup', + 'ibase_blob_cancel' => 'Safe\ibase_blob_cancel', + 'ibase_blob_create' => 'Safe\ibase_blob_create', + 'ibase_blob_get' => 'Safe\ibase_blob_get', + 'ibase_close' => 'Safe\ibase_close', + 'ibase_commit' => 'Safe\ibase_commit', + 'ibase_commit_ret' => 'Safe\ibase_commit_ret', + 'ibase_connect' => 'Safe\ibase_connect', + 'ibase_delete_user' => 'Safe\ibase_delete_user', + 'ibase_drop_db' => 'Safe\ibase_drop_db', + 'ibase_free_event_handler' => 'Safe\ibase_free_event_handler', + 'ibase_free_query' => 'Safe\ibase_free_query', + 'ibase_free_result' => 'Safe\ibase_free_result', + 'ibase_maintain_db' => 'Safe\ibase_maintain_db', + 'ibase_modify_user' => 'Safe\ibase_modify_user', + 'ibase_name_result' => 'Safe\ibase_name_result', + 'ibase_pconnect' => 'Safe\ibase_pconnect', + 'ibase_restore' => 'Safe\ibase_restore', + 'ibase_rollback' => 'Safe\ibase_rollback', + 'ibase_rollback_ret' => 'Safe\ibase_rollback_ret', + 'ibase_service_attach' => 'Safe\ibase_service_attach', + 'ibase_service_detach' => 'Safe\ibase_service_detach', + 'iconv' => 'Safe\iconv', + 'iconv_get_encoding' => 'Safe\iconv_get_encoding', + 'iconv_set_encoding' => 'Safe\iconv_set_encoding', + 'image2wbmp' => 'Safe\image2wbmp', + 'imageaffine' => 'Safe\imageaffine', + 'imageaffinematrixconcat' => 'Safe\imageaffinematrixconcat', + 'imageaffinematrixget' => 'Safe\imageaffinematrixget', + 'imagealphablending' => 'Safe\imagealphablending', + 'imageantialias' => 'Safe\imageantialias', + 'imagearc' => 'Safe\imagearc', + 'imagebmp' => 'Safe\imagebmp', + 'imagechar' => 'Safe\imagechar', + 'imagecharup' => 'Safe\imagecharup', + 'imagecolorat' => 'Safe\imagecolorat', + 'imagecolordeallocate' => 'Safe\imagecolordeallocate', + 'imagecolormatch' => 'Safe\imagecolormatch', + 'imageconvolution' => 'Safe\imageconvolution', + 'imagecopy' => 'Safe\imagecopy', + 'imagecopymerge' => 'Safe\imagecopymerge', + 'imagecopymergegray' => 'Safe\imagecopymergegray', + 'imagecopyresampled' => 'Safe\imagecopyresampled', + 'imagecopyresized' => 'Safe\imagecopyresized', + 'imagecreate' => 'Safe\imagecreate', + 'imagecreatefrombmp' => 'Safe\imagecreatefrombmp', + 'imagecreatefromgd' => 'Safe\imagecreatefromgd', + 'imagecreatefromgd2' => 'Safe\imagecreatefromgd2', + 'imagecreatefromgd2part' => 'Safe\imagecreatefromgd2part', + 'imagecreatefromgif' => 'Safe\imagecreatefromgif', + 'imagecreatefromjpeg' => 'Safe\imagecreatefromjpeg', + 'imagecreatefrompng' => 'Safe\imagecreatefrompng', + 'imagecreatefromwbmp' => 'Safe\imagecreatefromwbmp', + 'imagecreatefromwebp' => 'Safe\imagecreatefromwebp', + 'imagecreatefromxbm' => 'Safe\imagecreatefromxbm', + 'imagecreatefromxpm' => 'Safe\imagecreatefromxpm', + 'imagecreatetruecolor' => 'Safe\imagecreatetruecolor', + 'imagecrop' => 'Safe\imagecrop', + 'imagecropauto' => 'Safe\imagecropauto', + 'imagedashedline' => 'Safe\imagedashedline', + 'imagedestroy' => 'Safe\imagedestroy', + 'imageellipse' => 'Safe\imageellipse', + 'imagefill' => 'Safe\imagefill', + 'imagefilledarc' => 'Safe\imagefilledarc', + 'imagefilledellipse' => 'Safe\imagefilledellipse', + 'imagefilledpolygon' => 'Safe\imagefilledpolygon', + 'imagefilledrectangle' => 'Safe\imagefilledrectangle', + 'imagefilltoborder' => 'Safe\imagefilltoborder', + 'imagefilter' => 'Safe\imagefilter', + 'imageflip' => 'Safe\imageflip', + 'imagegammacorrect' => 'Safe\imagegammacorrect', + 'imagegd' => 'Safe\imagegd', + 'imagegd2' => 'Safe\imagegd2', + 'imagegif' => 'Safe\imagegif', + 'imagegrabscreen' => 'Safe\imagegrabscreen', + 'imagegrabwindow' => 'Safe\imagegrabwindow', + 'imagejpeg' => 'Safe\imagejpeg', + 'imagelayereffect' => 'Safe\imagelayereffect', + 'imageline' => 'Safe\imageline', + 'imageloadfont' => 'Safe\imageloadfont', + 'imageopenpolygon' => 'Safe\imageopenpolygon', + 'imagepng' => 'Safe\imagepng', + 'imagepolygon' => 'Safe\imagepolygon', + 'imagerectangle' => 'Safe\imagerectangle', + 'imagerotate' => 'Safe\imagerotate', + 'imagesavealpha' => 'Safe\imagesavealpha', + 'imagescale' => 'Safe\imagescale', + 'imagesetbrush' => 'Safe\imagesetbrush', + 'imagesetclip' => 'Safe\imagesetclip', + 'imagesetinterpolation' => 'Safe\imagesetinterpolation', + 'imagesetpixel' => 'Safe\imagesetpixel', + 'imagesetstyle' => 'Safe\imagesetstyle', + 'imagesetthickness' => 'Safe\imagesetthickness', + 'imagesettile' => 'Safe\imagesettile', + 'imagestring' => 'Safe\imagestring', + 'imagestringup' => 'Safe\imagestringup', + 'imagesx' => 'Safe\imagesx', + 'imagesy' => 'Safe\imagesy', + 'imagetruecolortopalette' => 'Safe\imagetruecolortopalette', + 'imagettfbbox' => 'Safe\imagettfbbox', + 'imagettftext' => 'Safe\imagettftext', + 'imagewbmp' => 'Safe\imagewbmp', + 'imagewebp' => 'Safe\imagewebp', + 'imagexbm' => 'Safe\imagexbm', + 'imap_append' => 'Safe\imap_append', + 'imap_check' => 'Safe\imap_check', + 'imap_clearflag_full' => 'Safe\imap_clearflag_full', + 'imap_close' => 'Safe\imap_close', + 'imap_createmailbox' => 'Safe\imap_createmailbox', + 'imap_deletemailbox' => 'Safe\imap_deletemailbox', + 'imap_fetchstructure' => 'Safe\imap_fetchstructure', + 'imap_gc' => 'Safe\imap_gc', + 'imap_headerinfo' => 'Safe\imap_headerinfo', + 'imap_mail' => 'Safe\imap_mail', + 'imap_mailboxmsginfo' => 'Safe\imap_mailboxmsginfo', + 'imap_mail_compose' => 'Safe\imap_mail_compose', + 'imap_mail_copy' => 'Safe\imap_mail_copy', + 'imap_mail_move' => 'Safe\imap_mail_move', + 'imap_mutf7_to_utf8' => 'Safe\imap_mutf7_to_utf8', + 'imap_num_msg' => 'Safe\imap_num_msg', + 'imap_open' => 'Safe\imap_open', + 'imap_renamemailbox' => 'Safe\imap_renamemailbox', + 'imap_savebody' => 'Safe\imap_savebody', + 'imap_setacl' => 'Safe\imap_setacl', + 'imap_setflag_full' => 'Safe\imap_setflag_full', + 'imap_set_quota' => 'Safe\imap_set_quota', + 'imap_sort' => 'Safe\imap_sort', + 'imap_subscribe' => 'Safe\imap_subscribe', + 'imap_thread' => 'Safe\imap_thread', + 'imap_timeout' => 'Safe\imap_timeout', + 'imap_undelete' => 'Safe\imap_undelete', + 'imap_unsubscribe' => 'Safe\imap_unsubscribe', + 'imap_utf8_to_mutf7' => 'Safe\imap_utf8_to_mutf7', + 'inet_ntop' => 'Safe\inet_ntop', + 'inflate_add' => 'Safe\inflate_add', + 'inflate_get_read_len' => 'Safe\inflate_get_read_len', + 'inflate_get_status' => 'Safe\inflate_get_status', + 'inflate_init' => 'Safe\inflate_init', + 'ingres_autocommit' => 'Safe\ingres_autocommit', + 'ingres_close' => 'Safe\ingres_close', + 'ingres_commit' => 'Safe\ingres_commit', + 'ingres_connect' => 'Safe\ingres_connect', + 'ingres_execute' => 'Safe\ingres_execute', + 'ingres_field_name' => 'Safe\ingres_field_name', + 'ingres_field_type' => 'Safe\ingres_field_type', + 'ingres_free_result' => 'Safe\ingres_free_result', + 'ingres_pconnect' => 'Safe\ingres_pconnect', + 'ingres_result_seek' => 'Safe\ingres_result_seek', + 'ingres_rollback' => 'Safe\ingres_rollback', + 'ingres_set_environment' => 'Safe\ingres_set_environment', + 'ini_get' => 'Safe\ini_get', + 'ini_set' => 'Safe\ini_set', + 'inotify_init' => 'Safe\inotify_init', + 'inotify_rm_watch' => 'Safe\inotify_rm_watch', + 'iptcembed' => 'Safe\iptcembed', + 'iptcparse' => 'Safe\iptcparse', + 'jdtounix' => 'Safe\jdtounix', + 'jpeg2wbmp' => 'Safe\jpeg2wbmp', + 'json_decode' => 'Safe\json_decode', + 'json_encode' => 'Safe\json_encode', + 'json_last_error_msg' => 'Safe\json_last_error_msg', + 'krsort' => 'Safe\krsort', + 'ksort' => 'Safe\ksort', + 'lchgrp' => 'Safe\lchgrp', + 'lchown' => 'Safe\lchown', + 'ldap_add' => 'Safe\ldap_add', + 'ldap_add_ext' => 'Safe\ldap_add_ext', + 'ldap_bind' => 'Safe\ldap_bind', + 'ldap_bind_ext' => 'Safe\ldap_bind_ext', + 'ldap_control_paged_result' => 'Safe\ldap_control_paged_result', + 'ldap_control_paged_result_response' => 'Safe\ldap_control_paged_result_response', + 'ldap_count_entries' => 'Safe\ldap_count_entries', + 'ldap_delete' => 'Safe\ldap_delete', + 'ldap_delete_ext' => 'Safe\ldap_delete_ext', + 'ldap_exop' => 'Safe\ldap_exop', + 'ldap_exop_passwd' => 'Safe\ldap_exop_passwd', + 'ldap_exop_whoami' => 'Safe\ldap_exop_whoami', + 'ldap_explode_dn' => 'Safe\ldap_explode_dn', + 'ldap_first_attribute' => 'Safe\ldap_first_attribute', + 'ldap_first_entry' => 'Safe\ldap_first_entry', + 'ldap_free_result' => 'Safe\ldap_free_result', + 'ldap_get_attributes' => 'Safe\ldap_get_attributes', + 'ldap_get_dn' => 'Safe\ldap_get_dn', + 'ldap_get_entries' => 'Safe\ldap_get_entries', + 'ldap_get_option' => 'Safe\ldap_get_option', + 'ldap_get_values' => 'Safe\ldap_get_values', + 'ldap_get_values_len' => 'Safe\ldap_get_values_len', + 'ldap_list' => 'Safe\ldap_list', + 'ldap_modify_batch' => 'Safe\ldap_modify_batch', + 'ldap_mod_add' => 'Safe\ldap_mod_add', + 'ldap_mod_add_ext' => 'Safe\ldap_mod_add_ext', + 'ldap_mod_del' => 'Safe\ldap_mod_del', + 'ldap_mod_del_ext' => 'Safe\ldap_mod_del_ext', + 'ldap_mod_replace' => 'Safe\ldap_mod_replace', + 'ldap_mod_replace_ext' => 'Safe\ldap_mod_replace_ext', + 'ldap_next_attribute' => 'Safe\ldap_next_attribute', + 'ldap_parse_exop' => 'Safe\ldap_parse_exop', + 'ldap_parse_result' => 'Safe\ldap_parse_result', + 'ldap_read' => 'Safe\ldap_read', + 'ldap_rename' => 'Safe\ldap_rename', + 'ldap_rename_ext' => 'Safe\ldap_rename_ext', + 'ldap_sasl_bind' => 'Safe\ldap_sasl_bind', + 'ldap_search' => 'Safe\ldap_search', + 'ldap_set_option' => 'Safe\ldap_set_option', + 'ldap_unbind' => 'Safe\ldap_unbind', + 'libxml_get_last_error' => 'Safe\libxml_get_last_error', + 'libxml_set_external_entity_loader' => 'Safe\libxml_set_external_entity_loader', + 'link' => 'Safe\link', + 'lzf_compress' => 'Safe\lzf_compress', + 'lzf_decompress' => 'Safe\lzf_decompress', + 'mailparse_msg_extract_part_file' => 'Safe\mailparse_msg_extract_part_file', + 'mailparse_msg_free' => 'Safe\mailparse_msg_free', + 'mailparse_msg_parse' => 'Safe\mailparse_msg_parse', + 'mailparse_msg_parse_file' => 'Safe\mailparse_msg_parse_file', + 'mailparse_stream_encode' => 'Safe\mailparse_stream_encode', + 'mb_chr' => 'Safe\mb_chr', + 'mb_detect_order' => 'Safe\mb_detect_order', + 'mb_encoding_aliases' => 'Safe\mb_encoding_aliases', + 'mb_eregi_replace' => 'Safe\mb_eregi_replace', + 'mb_ereg_replace' => 'Safe\mb_ereg_replace', + 'mb_ereg_replace_callback' => 'Safe\mb_ereg_replace_callback', + 'mb_ereg_search_getregs' => 'Safe\mb_ereg_search_getregs', + 'mb_ereg_search_init' => 'Safe\mb_ereg_search_init', + 'mb_ereg_search_regs' => 'Safe\mb_ereg_search_regs', + 'mb_ereg_search_setpos' => 'Safe\mb_ereg_search_setpos', + 'mb_http_output' => 'Safe\mb_http_output', + 'mb_internal_encoding' => 'Safe\mb_internal_encoding', + 'mb_ord' => 'Safe\mb_ord', + 'mb_parse_str' => 'Safe\mb_parse_str', + 'mb_regex_encoding' => 'Safe\mb_regex_encoding', + 'mb_send_mail' => 'Safe\mb_send_mail', + 'mb_split' => 'Safe\mb_split', + 'mb_str_split' => 'Safe\mb_str_split', + 'md5_file' => 'Safe\md5_file', + 'metaphone' => 'Safe\metaphone', + 'mime_content_type' => 'Safe\mime_content_type', + 'mkdir' => 'Safe\mkdir', + 'mktime' => 'Safe\mktime', + 'msg_queue_exists' => 'Safe\msg_queue_exists', + 'msg_receive' => 'Safe\msg_receive', + 'msg_remove_queue' => 'Safe\msg_remove_queue', + 'msg_send' => 'Safe\msg_send', + 'msg_set_queue' => 'Safe\msg_set_queue', + 'msql_affected_rows' => 'Safe\msql_affected_rows', + 'msql_close' => 'Safe\msql_close', + 'msql_connect' => 'Safe\msql_connect', + 'msql_create_db' => 'Safe\msql_create_db', + 'msql_data_seek' => 'Safe\msql_data_seek', + 'msql_db_query' => 'Safe\msql_db_query', + 'msql_drop_db' => 'Safe\msql_drop_db', + 'msql_field_len' => 'Safe\msql_field_len', + 'msql_field_name' => 'Safe\msql_field_name', + 'msql_field_seek' => 'Safe\msql_field_seek', + 'msql_field_table' => 'Safe\msql_field_table', + 'msql_field_type' => 'Safe\msql_field_type', + 'msql_free_result' => 'Safe\msql_free_result', + 'msql_pconnect' => 'Safe\msql_pconnect', + 'msql_query' => 'Safe\msql_query', + 'msql_select_db' => 'Safe\msql_select_db', + 'mysqli_get_cache_stats' => 'Safe\mysqli_get_cache_stats', + 'mysqli_get_client_stats' => 'Safe\mysqli_get_client_stats', + 'mysqlnd_ms_dump_servers' => 'Safe\mysqlnd_ms_dump_servers', + 'mysqlnd_ms_fabric_select_global' => 'Safe\mysqlnd_ms_fabric_select_global', + 'mysqlnd_ms_fabric_select_shard' => 'Safe\mysqlnd_ms_fabric_select_shard', + 'mysqlnd_ms_get_last_used_connection' => 'Safe\mysqlnd_ms_get_last_used_connection', + 'mysqlnd_qc_clear_cache' => 'Safe\mysqlnd_qc_clear_cache', + 'mysqlnd_qc_set_is_select' => 'Safe\mysqlnd_qc_set_is_select', + 'mysqlnd_qc_set_storage_handler' => 'Safe\mysqlnd_qc_set_storage_handler', + 'mysql_close' => 'Safe\mysql_close', + 'mysql_connect' => 'Safe\mysql_connect', + 'mysql_create_db' => 'Safe\mysql_create_db', + 'mysql_data_seek' => 'Safe\mysql_data_seek', + 'mysql_db_name' => 'Safe\mysql_db_name', + 'mysql_db_query' => 'Safe\mysql_db_query', + 'mysql_drop_db' => 'Safe\mysql_drop_db', + 'mysql_fetch_lengths' => 'Safe\mysql_fetch_lengths', + 'mysql_field_flags' => 'Safe\mysql_field_flags', + 'mysql_field_len' => 'Safe\mysql_field_len', + 'mysql_field_name' => 'Safe\mysql_field_name', + 'mysql_field_seek' => 'Safe\mysql_field_seek', + 'mysql_free_result' => 'Safe\mysql_free_result', + 'mysql_get_host_info' => 'Safe\mysql_get_host_info', + 'mysql_get_proto_info' => 'Safe\mysql_get_proto_info', + 'mysql_get_server_info' => 'Safe\mysql_get_server_info', + 'mysql_info' => 'Safe\mysql_info', + 'mysql_list_dbs' => 'Safe\mysql_list_dbs', + 'mysql_list_fields' => 'Safe\mysql_list_fields', + 'mysql_list_processes' => 'Safe\mysql_list_processes', + 'mysql_list_tables' => 'Safe\mysql_list_tables', + 'mysql_num_fields' => 'Safe\mysql_num_fields', + 'mysql_num_rows' => 'Safe\mysql_num_rows', + 'mysql_query' => 'Safe\mysql_query', + 'mysql_real_escape_string' => 'Safe\mysql_real_escape_string', + 'mysql_result' => 'Safe\mysql_result', + 'mysql_select_db' => 'Safe\mysql_select_db', + 'mysql_set_charset' => 'Safe\mysql_set_charset', + 'mysql_tablename' => 'Safe\mysql_tablename', + 'mysql_thread_id' => 'Safe\mysql_thread_id', + 'mysql_unbuffered_query' => 'Safe\mysql_unbuffered_query', + 'natcasesort' => 'Safe\natcasesort', + 'natsort' => 'Safe\natsort', + 'ob_end_clean' => 'Safe\ob_end_clean', + 'ob_end_flush' => 'Safe\ob_end_flush', + 'oci_bind_array_by_name' => 'Safe\oci_bind_array_by_name', + 'oci_bind_by_name' => 'Safe\oci_bind_by_name', + 'oci_cancel' => 'Safe\oci_cancel', + 'oci_close' => 'Safe\oci_close', + 'oci_commit' => 'Safe\oci_commit', + 'oci_connect' => 'Safe\oci_connect', + 'oci_define_by_name' => 'Safe\oci_define_by_name', + 'oci_execute' => 'Safe\oci_execute', + 'oci_fetch_all' => 'Safe\oci_fetch_all', + 'oci_field_name' => 'Safe\oci_field_name', + 'oci_field_precision' => 'Safe\oci_field_precision', + 'oci_field_scale' => 'Safe\oci_field_scale', + 'oci_field_size' => 'Safe\oci_field_size', + 'oci_field_type' => 'Safe\oci_field_type', + 'oci_field_type_raw' => 'Safe\oci_field_type_raw', + 'oci_free_descriptor' => 'Safe\oci_free_descriptor', + 'oci_free_statement' => 'Safe\oci_free_statement', + 'oci_new_collection' => 'Safe\oci_new_collection', + 'oci_new_connect' => 'Safe\oci_new_connect', + 'oci_new_cursor' => 'Safe\oci_new_cursor', + 'oci_new_descriptor' => 'Safe\oci_new_descriptor', + 'oci_num_fields' => 'Safe\oci_num_fields', + 'oci_num_rows' => 'Safe\oci_num_rows', + 'oci_parse' => 'Safe\oci_parse', + 'oci_pconnect' => 'Safe\oci_pconnect', + 'oci_result' => 'Safe\oci_result', + 'oci_rollback' => 'Safe\oci_rollback', + 'oci_server_version' => 'Safe\oci_server_version', + 'oci_set_action' => 'Safe\oci_set_action', + 'oci_set_call_timeout' => 'Safe\oci_set_call_timeout', + 'oci_set_client_identifier' => 'Safe\oci_set_client_identifier', + 'oci_set_client_info' => 'Safe\oci_set_client_info', + 'oci_set_db_operation' => 'Safe\oci_set_db_operation', + 'oci_set_edition' => 'Safe\oci_set_edition', + 'oci_set_module_name' => 'Safe\oci_set_module_name', + 'oci_set_prefetch' => 'Safe\oci_set_prefetch', + 'oci_statement_type' => 'Safe\oci_statement_type', + 'oci_unregister_taf_callback' => 'Safe\oci_unregister_taf_callback', + 'odbc_autocommit' => 'Safe\odbc_autocommit', + 'odbc_binmode' => 'Safe\odbc_binmode', + 'odbc_columnprivileges' => 'Safe\odbc_columnprivileges', + 'odbc_columns' => 'Safe\odbc_columns', + 'odbc_commit' => 'Safe\odbc_commit', + 'odbc_data_source' => 'Safe\odbc_data_source', + 'odbc_exec' => 'Safe\odbc_exec', + 'odbc_execute' => 'Safe\odbc_execute', + 'odbc_fetch_into' => 'Safe\odbc_fetch_into', + 'odbc_field_len' => 'Safe\odbc_field_len', + 'odbc_field_name' => 'Safe\odbc_field_name', + 'odbc_field_num' => 'Safe\odbc_field_num', + 'odbc_field_scale' => 'Safe\odbc_field_scale', + 'odbc_field_type' => 'Safe\odbc_field_type', + 'odbc_foreignkeys' => 'Safe\odbc_foreignkeys', + 'odbc_gettypeinfo' => 'Safe\odbc_gettypeinfo', + 'odbc_longreadlen' => 'Safe\odbc_longreadlen', + 'odbc_prepare' => 'Safe\odbc_prepare', + 'odbc_primarykeys' => 'Safe\odbc_primarykeys', + 'odbc_result' => 'Safe\odbc_result', + 'odbc_result_all' => 'Safe\odbc_result_all', + 'odbc_rollback' => 'Safe\odbc_rollback', + 'odbc_setoption' => 'Safe\odbc_setoption', + 'odbc_specialcolumns' => 'Safe\odbc_specialcolumns', + 'odbc_statistics' => 'Safe\odbc_statistics', + 'odbc_tableprivileges' => 'Safe\odbc_tableprivileges', + 'odbc_tables' => 'Safe\odbc_tables', + 'opcache_compile_file' => 'Safe\opcache_compile_file', + 'opcache_get_status' => 'Safe\opcache_get_status', + 'opendir' => 'Safe\opendir', + 'openlog' => 'Safe\openlog', + 'openssl_cipher_iv_length' => 'Safe\openssl_cipher_iv_length', + 'openssl_csr_export' => 'Safe\openssl_csr_export', + 'openssl_csr_export_to_file' => 'Safe\openssl_csr_export_to_file', + 'openssl_csr_get_subject' => 'Safe\openssl_csr_get_subject', + 'openssl_csr_new' => 'Safe\openssl_csr_new', + 'openssl_csr_sign' => 'Safe\openssl_csr_sign', + 'openssl_decrypt' => 'Safe\openssl_decrypt', + 'openssl_dh_compute_key' => 'Safe\openssl_dh_compute_key', + 'openssl_digest' => 'Safe\openssl_digest', + 'openssl_encrypt' => 'Safe\openssl_encrypt', + 'openssl_open' => 'Safe\openssl_open', + 'openssl_pbkdf2' => 'Safe\openssl_pbkdf2', + 'openssl_pkcs7_decrypt' => 'Safe\openssl_pkcs7_decrypt', + 'openssl_pkcs7_encrypt' => 'Safe\openssl_pkcs7_encrypt', + 'openssl_pkcs7_read' => 'Safe\openssl_pkcs7_read', + 'openssl_pkcs7_sign' => 'Safe\openssl_pkcs7_sign', + 'openssl_pkcs12_export' => 'Safe\openssl_pkcs12_export', + 'openssl_pkcs12_export_to_file' => 'Safe\openssl_pkcs12_export_to_file', + 'openssl_pkcs12_read' => 'Safe\openssl_pkcs12_read', + 'openssl_pkey_export' => 'Safe\openssl_pkey_export', + 'openssl_pkey_export_to_file' => 'Safe\openssl_pkey_export_to_file', + 'openssl_pkey_get_private' => 'Safe\openssl_pkey_get_private', + 'openssl_pkey_get_public' => 'Safe\openssl_pkey_get_public', + 'openssl_pkey_new' => 'Safe\openssl_pkey_new', + 'openssl_private_decrypt' => 'Safe\openssl_private_decrypt', + 'openssl_private_encrypt' => 'Safe\openssl_private_encrypt', + 'openssl_public_decrypt' => 'Safe\openssl_public_decrypt', + 'openssl_public_encrypt' => 'Safe\openssl_public_encrypt', + 'openssl_random_pseudo_bytes' => 'Safe\openssl_random_pseudo_bytes', + 'openssl_seal' => 'Safe\openssl_seal', + 'openssl_sign' => 'Safe\openssl_sign', + 'openssl_x509_export' => 'Safe\openssl_x509_export', + 'openssl_x509_export_to_file' => 'Safe\openssl_x509_export_to_file', + 'openssl_x509_fingerprint' => 'Safe\openssl_x509_fingerprint', + 'openssl_x509_read' => 'Safe\openssl_x509_read', + 'output_add_rewrite_var' => 'Safe\output_add_rewrite_var', + 'output_reset_rewrite_vars' => 'Safe\output_reset_rewrite_vars', + 'pack' => 'Safe\pack', + 'parse_ini_file' => 'Safe\parse_ini_file', + 'parse_ini_string' => 'Safe\parse_ini_string', + 'parse_url' => 'Safe\parse_url', + 'password_hash' => 'Safe\password_hash', + 'pcntl_exec' => 'Safe\pcntl_exec', + 'pcntl_getpriority' => 'Safe\pcntl_getpriority', + 'pcntl_setpriority' => 'Safe\pcntl_setpriority', + 'pcntl_signal_dispatch' => 'Safe\pcntl_signal_dispatch', + 'pcntl_sigprocmask' => 'Safe\pcntl_sigprocmask', + 'pcntl_strerror' => 'Safe\pcntl_strerror', + 'PDF_activate_item' => 'Safe\PDF_activate_item', + 'PDF_add_locallink' => 'Safe\PDF_add_locallink', + 'PDF_add_nameddest' => 'Safe\PDF_add_nameddest', + 'PDF_add_note' => 'Safe\PDF_add_note', + 'PDF_add_pdflink' => 'Safe\PDF_add_pdflink', + 'PDF_add_thumbnail' => 'Safe\PDF_add_thumbnail', + 'PDF_add_weblink' => 'Safe\PDF_add_weblink', + 'PDF_attach_file' => 'Safe\PDF_attach_file', + 'PDF_begin_layer' => 'Safe\PDF_begin_layer', + 'PDF_begin_page' => 'Safe\PDF_begin_page', + 'PDF_begin_page_ext' => 'Safe\PDF_begin_page_ext', + 'PDF_circle' => 'Safe\PDF_circle', + 'PDF_clip' => 'Safe\PDF_clip', + 'PDF_close' => 'Safe\PDF_close', + 'PDF_closepath' => 'Safe\PDF_closepath', + 'PDF_closepath_fill_stroke' => 'Safe\PDF_closepath_fill_stroke', + 'PDF_closepath_stroke' => 'Safe\PDF_closepath_stroke', + 'PDF_close_pdi' => 'Safe\PDF_close_pdi', + 'PDF_close_pdi_page' => 'Safe\PDF_close_pdi_page', + 'PDF_concat' => 'Safe\PDF_concat', + 'PDF_continue_text' => 'Safe\PDF_continue_text', + 'PDF_curveto' => 'Safe\PDF_curveto', + 'PDF_delete' => 'Safe\PDF_delete', + 'PDF_end_layer' => 'Safe\PDF_end_layer', + 'PDF_end_page' => 'Safe\PDF_end_page', + 'PDF_end_page_ext' => 'Safe\PDF_end_page_ext', + 'PDF_end_pattern' => 'Safe\PDF_end_pattern', + 'PDF_end_template' => 'Safe\PDF_end_template', + 'PDF_fill' => 'Safe\PDF_fill', + 'PDF_fill_stroke' => 'Safe\PDF_fill_stroke', + 'PDF_fit_image' => 'Safe\PDF_fit_image', + 'PDF_fit_pdi_page' => 'Safe\PDF_fit_pdi_page', + 'PDF_fit_textline' => 'Safe\PDF_fit_textline', + 'PDF_initgraphics' => 'Safe\PDF_initgraphics', + 'PDF_lineto' => 'Safe\PDF_lineto', + 'PDF_makespotcolor' => 'Safe\PDF_makespotcolor', + 'PDF_moveto' => 'Safe\PDF_moveto', + 'PDF_open_file' => 'Safe\PDF_open_file', + 'PDF_place_image' => 'Safe\PDF_place_image', + 'PDF_place_pdi_page' => 'Safe\PDF_place_pdi_page', + 'PDF_rect' => 'Safe\PDF_rect', + 'PDF_restore' => 'Safe\PDF_restore', + 'PDF_rotate' => 'Safe\PDF_rotate', + 'PDF_save' => 'Safe\PDF_save', + 'PDF_scale' => 'Safe\PDF_scale', + 'PDF_setcolor' => 'Safe\PDF_setcolor', + 'PDF_setdash' => 'Safe\PDF_setdash', + 'PDF_setdashpattern' => 'Safe\PDF_setdashpattern', + 'PDF_setflat' => 'Safe\PDF_setflat', + 'PDF_setfont' => 'Safe\PDF_setfont', + 'PDF_setgray' => 'Safe\PDF_setgray', + 'PDF_setgray_fill' => 'Safe\PDF_setgray_fill', + 'PDF_setgray_stroke' => 'Safe\PDF_setgray_stroke', + 'PDF_setlinejoin' => 'Safe\PDF_setlinejoin', + 'PDF_setlinewidth' => 'Safe\PDF_setlinewidth', + 'PDF_setmatrix' => 'Safe\PDF_setmatrix', + 'PDF_setmiterlimit' => 'Safe\PDF_setmiterlimit', + 'PDF_setrgbcolor' => 'Safe\PDF_setrgbcolor', + 'PDF_setrgbcolor_fill' => 'Safe\PDF_setrgbcolor_fill', + 'PDF_setrgbcolor_stroke' => 'Safe\PDF_setrgbcolor_stroke', + 'PDF_set_border_color' => 'Safe\PDF_set_border_color', + 'PDF_set_border_dash' => 'Safe\PDF_set_border_dash', + 'PDF_set_border_style' => 'Safe\PDF_set_border_style', + 'PDF_set_info' => 'Safe\PDF_set_info', + 'PDF_set_layer_dependency' => 'Safe\PDF_set_layer_dependency', + 'PDF_set_parameter' => 'Safe\PDF_set_parameter', + 'PDF_set_text_pos' => 'Safe\PDF_set_text_pos', + 'PDF_set_value' => 'Safe\PDF_set_value', + 'PDF_show' => 'Safe\PDF_show', + 'PDF_show_xy' => 'Safe\PDF_show_xy', + 'PDF_skew' => 'Safe\PDF_skew', + 'PDF_stroke' => 'Safe\PDF_stroke', + 'pg_cancel_query' => 'Safe\pg_cancel_query', + 'pg_client_encoding' => 'Safe\pg_client_encoding', + 'pg_close' => 'Safe\pg_close', + 'pg_connect' => 'Safe\pg_connect', + 'pg_connection_reset' => 'Safe\pg_connection_reset', + 'pg_convert' => 'Safe\pg_convert', + 'pg_copy_from' => 'Safe\pg_copy_from', + 'pg_copy_to' => 'Safe\pg_copy_to', + 'pg_dbname' => 'Safe\pg_dbname', + 'pg_delete' => 'Safe\pg_delete', + 'pg_end_copy' => 'Safe\pg_end_copy', + 'pg_execute' => 'Safe\pg_execute', + 'pg_field_name' => 'Safe\pg_field_name', + 'pg_field_table' => 'Safe\pg_field_table', + 'pg_field_type' => 'Safe\pg_field_type', + 'pg_flush' => 'Safe\pg_flush', + 'pg_free_result' => 'Safe\pg_free_result', + 'pg_host' => 'Safe\pg_host', + 'pg_insert' => 'Safe\pg_insert', + 'pg_last_error' => 'Safe\pg_last_error', + 'pg_last_notice' => 'Safe\pg_last_notice', + 'pg_last_oid' => 'Safe\pg_last_oid', + 'pg_lo_close' => 'Safe\pg_lo_close', + 'pg_lo_export' => 'Safe\pg_lo_export', + 'pg_lo_import' => 'Safe\pg_lo_import', + 'pg_lo_open' => 'Safe\pg_lo_open', + 'pg_lo_read' => 'Safe\pg_lo_read', + 'pg_lo_read_all' => 'Safe\pg_lo_read_all', + 'pg_lo_seek' => 'Safe\pg_lo_seek', + 'pg_lo_truncate' => 'Safe\pg_lo_truncate', + 'pg_lo_unlink' => 'Safe\pg_lo_unlink', + 'pg_lo_write' => 'Safe\pg_lo_write', + 'pg_meta_data' => 'Safe\pg_meta_data', + 'pg_options' => 'Safe\pg_options', + 'pg_parameter_status' => 'Safe\pg_parameter_status', + 'pg_pconnect' => 'Safe\pg_pconnect', + 'pg_ping' => 'Safe\pg_ping', + 'pg_port' => 'Safe\pg_port', + 'pg_prepare' => 'Safe\pg_prepare', + 'pg_put_line' => 'Safe\pg_put_line', + 'pg_query' => 'Safe\pg_query', + 'pg_query_params' => 'Safe\pg_query_params', + 'pg_result_error_field' => 'Safe\pg_result_error_field', + 'pg_result_seek' => 'Safe\pg_result_seek', + 'pg_select' => 'Safe\pg_select', + 'pg_send_execute' => 'Safe\pg_send_execute', + 'pg_send_prepare' => 'Safe\pg_send_prepare', + 'pg_send_query' => 'Safe\pg_send_query', + 'pg_send_query_params' => 'Safe\pg_send_query_params', + 'pg_socket' => 'Safe\pg_socket', + 'pg_trace' => 'Safe\pg_trace', + 'pg_tty' => 'Safe\pg_tty', + 'pg_update' => 'Safe\pg_update', + 'pg_version' => 'Safe\pg_version', + 'phpcredits' => 'Safe\phpcredits', + 'phpinfo' => 'Safe\phpinfo', + 'png2wbmp' => 'Safe\png2wbmp', + 'posix_access' => 'Safe\posix_access', + 'posix_getgrnam' => 'Safe\posix_getgrnam', + 'posix_getpgid' => 'Safe\posix_getpgid', + 'posix_initgroups' => 'Safe\posix_initgroups', + 'posix_kill' => 'Safe\posix_kill', + 'posix_mkfifo' => 'Safe\posix_mkfifo', + 'posix_mknod' => 'Safe\posix_mknod', + 'posix_setegid' => 'Safe\posix_setegid', + 'posix_seteuid' => 'Safe\posix_seteuid', + 'posix_setgid' => 'Safe\posix_setgid', + 'posix_setpgid' => 'Safe\posix_setpgid', + 'posix_setrlimit' => 'Safe\posix_setrlimit', + 'posix_setuid' => 'Safe\posix_setuid', + 'preg_match' => 'Safe\preg_match', + 'preg_match_all' => 'Safe\preg_match_all', + 'preg_replace' => 'Safe\preg_replace', + 'preg_split' => 'Safe\preg_split', + 'proc_get_status' => 'Safe\proc_get_status', + 'proc_nice' => 'Safe\proc_nice', + 'pspell_add_to_personal' => 'Safe\pspell_add_to_personal', + 'pspell_add_to_session' => 'Safe\pspell_add_to_session', + 'pspell_clear_session' => 'Safe\pspell_clear_session', + 'pspell_config_create' => 'Safe\pspell_config_create', + 'pspell_config_data_dir' => 'Safe\pspell_config_data_dir', + 'pspell_config_dict_dir' => 'Safe\pspell_config_dict_dir', + 'pspell_config_ignore' => 'Safe\pspell_config_ignore', + 'pspell_config_mode' => 'Safe\pspell_config_mode', + 'pspell_config_personal' => 'Safe\pspell_config_personal', + 'pspell_config_repl' => 'Safe\pspell_config_repl', + 'pspell_config_runtogether' => 'Safe\pspell_config_runtogether', + 'pspell_config_save_repl' => 'Safe\pspell_config_save_repl', + 'pspell_new' => 'Safe\pspell_new', + 'pspell_new_config' => 'Safe\pspell_new_config', + 'pspell_save_wordlist' => 'Safe\pspell_save_wordlist', + 'pspell_store_replacement' => 'Safe\pspell_store_replacement', + 'ps_add_launchlink' => 'Safe\ps_add_launchlink', + 'ps_add_locallink' => 'Safe\ps_add_locallink', + 'ps_add_note' => 'Safe\ps_add_note', + 'ps_add_pdflink' => 'Safe\ps_add_pdflink', + 'ps_add_weblink' => 'Safe\ps_add_weblink', + 'ps_arc' => 'Safe\ps_arc', + 'ps_arcn' => 'Safe\ps_arcn', + 'ps_begin_page' => 'Safe\ps_begin_page', + 'ps_begin_pattern' => 'Safe\ps_begin_pattern', + 'ps_begin_template' => 'Safe\ps_begin_template', + 'ps_circle' => 'Safe\ps_circle', + 'ps_clip' => 'Safe\ps_clip', + 'ps_close' => 'Safe\ps_close', + 'ps_closepath' => 'Safe\ps_closepath', + 'ps_closepath_stroke' => 'Safe\ps_closepath_stroke', + 'ps_close_image' => 'Safe\ps_close_image', + 'ps_continue_text' => 'Safe\ps_continue_text', + 'ps_curveto' => 'Safe\ps_curveto', + 'ps_delete' => 'Safe\ps_delete', + 'ps_end_page' => 'Safe\ps_end_page', + 'ps_end_pattern' => 'Safe\ps_end_pattern', + 'ps_end_template' => 'Safe\ps_end_template', + 'ps_fill' => 'Safe\ps_fill', + 'ps_fill_stroke' => 'Safe\ps_fill_stroke', + 'ps_get_parameter' => 'Safe\ps_get_parameter', + 'ps_hyphenate' => 'Safe\ps_hyphenate', + 'ps_include_file' => 'Safe\ps_include_file', + 'ps_lineto' => 'Safe\ps_lineto', + 'ps_moveto' => 'Safe\ps_moveto', + 'ps_new' => 'Safe\ps_new', + 'ps_open_file' => 'Safe\ps_open_file', + 'ps_place_image' => 'Safe\ps_place_image', + 'ps_rect' => 'Safe\ps_rect', + 'ps_restore' => 'Safe\ps_restore', + 'ps_rotate' => 'Safe\ps_rotate', + 'ps_save' => 'Safe\ps_save', + 'ps_scale' => 'Safe\ps_scale', + 'ps_setcolor' => 'Safe\ps_setcolor', + 'ps_setdash' => 'Safe\ps_setdash', + 'ps_setflat' => 'Safe\ps_setflat', + 'ps_setfont' => 'Safe\ps_setfont', + 'ps_setgray' => 'Safe\ps_setgray', + 'ps_setlinecap' => 'Safe\ps_setlinecap', + 'ps_setlinejoin' => 'Safe\ps_setlinejoin', + 'ps_setlinewidth' => 'Safe\ps_setlinewidth', + 'ps_setmiterlimit' => 'Safe\ps_setmiterlimit', + 'ps_setoverprintmode' => 'Safe\ps_setoverprintmode', + 'ps_setpolydash' => 'Safe\ps_setpolydash', + 'ps_set_border_color' => 'Safe\ps_set_border_color', + 'ps_set_border_dash' => 'Safe\ps_set_border_dash', + 'ps_set_border_style' => 'Safe\ps_set_border_style', + 'ps_set_info' => 'Safe\ps_set_info', + 'ps_set_parameter' => 'Safe\ps_set_parameter', + 'ps_set_text_pos' => 'Safe\ps_set_text_pos', + 'ps_set_value' => 'Safe\ps_set_value', + 'ps_shading' => 'Safe\ps_shading', + 'ps_shading_pattern' => 'Safe\ps_shading_pattern', + 'ps_shfill' => 'Safe\ps_shfill', + 'ps_show' => 'Safe\ps_show', + 'ps_show2' => 'Safe\ps_show2', + 'ps_show_xy' => 'Safe\ps_show_xy', + 'ps_show_xy2' => 'Safe\ps_show_xy2', + 'ps_stroke' => 'Safe\ps_stroke', + 'ps_symbol' => 'Safe\ps_symbol', + 'ps_translate' => 'Safe\ps_translate', + 'putenv' => 'Safe\putenv', + 'readfile' => 'Safe\readfile', + 'readgzfile' => 'Safe\readgzfile', + 'readline_add_history' => 'Safe\readline_add_history', + 'readline_callback_handler_install' => 'Safe\readline_callback_handler_install', + 'readline_clear_history' => 'Safe\readline_clear_history', + 'readline_completion_function' => 'Safe\readline_completion_function', + 'readline_read_history' => 'Safe\readline_read_history', + 'readline_write_history' => 'Safe\readline_write_history', + 'readlink' => 'Safe\readlink', + 'realpath' => 'Safe\realpath', + 'register_tick_function' => 'Safe\register_tick_function', + 'rename' => 'Safe\rename', + 'rewind' => 'Safe\rewind', + 'rewinddir' => 'Safe\rewinddir', + 'rmdir' => 'Safe\rmdir', + 'rpmaddtag' => 'Safe\rpmaddtag', + 'rrd_create' => 'Safe\rrd_create', + 'rsort' => 'Safe\rsort', + 'sapi_windows_cp_conv' => 'Safe\sapi_windows_cp_conv', + 'sapi_windows_cp_set' => 'Safe\sapi_windows_cp_set', + 'sapi_windows_generate_ctrl_event' => 'Safe\sapi_windows_generate_ctrl_event', + 'sapi_windows_vt100_support' => 'Safe\sapi_windows_vt100_support', + 'scandir' => 'Safe\scandir', + 'sem_acquire' => 'Safe\sem_acquire', + 'sem_get' => 'Safe\sem_get', + 'sem_release' => 'Safe\sem_release', + 'sem_remove' => 'Safe\sem_remove', + 'session_abort' => 'Safe\session_abort', + 'session_decode' => 'Safe\session_decode', + 'session_destroy' => 'Safe\session_destroy', + 'session_regenerate_id' => 'Safe\session_regenerate_id', + 'session_reset' => 'Safe\session_reset', + 'session_unset' => 'Safe\session_unset', + 'session_write_close' => 'Safe\session_write_close', + 'settype' => 'Safe\settype', + 'set_include_path' => 'Safe\set_include_path', + 'set_time_limit' => 'Safe\set_time_limit', + 'sha1_file' => 'Safe\sha1_file', + 'shmop_delete' => 'Safe\shmop_delete', + 'shmop_read' => 'Safe\shmop_read', + 'shmop_write' => 'Safe\shmop_write', + 'shm_put_var' => 'Safe\shm_put_var', + 'shm_remove' => 'Safe\shm_remove', + 'shm_remove_var' => 'Safe\shm_remove_var', + 'shuffle' => 'Safe\shuffle', + 'simplexml_import_dom' => 'Safe\simplexml_import_dom', + 'simplexml_load_file' => 'Safe\simplexml_load_file', + 'simplexml_load_string' => 'Safe\simplexml_load_string', + 'sleep' => 'Safe\sleep', + 'socket_accept' => 'Safe\socket_accept', + 'socket_addrinfo_bind' => 'Safe\socket_addrinfo_bind', + 'socket_addrinfo_connect' => 'Safe\socket_addrinfo_connect', + 'socket_bind' => 'Safe\socket_bind', + 'socket_connect' => 'Safe\socket_connect', + 'socket_create' => 'Safe\socket_create', + 'socket_create_listen' => 'Safe\socket_create_listen', + 'socket_create_pair' => 'Safe\socket_create_pair', + 'socket_export_stream' => 'Safe\socket_export_stream', + 'socket_getpeername' => 'Safe\socket_getpeername', + 'socket_getsockname' => 'Safe\socket_getsockname', + 'socket_get_option' => 'Safe\socket_get_option', + 'socket_import_stream' => 'Safe\socket_import_stream', + 'socket_listen' => 'Safe\socket_listen', + 'socket_read' => 'Safe\socket_read', + 'socket_send' => 'Safe\socket_send', + 'socket_sendmsg' => 'Safe\socket_sendmsg', + 'socket_sendto' => 'Safe\socket_sendto', + 'socket_set_block' => 'Safe\socket_set_block', + 'socket_set_nonblock' => 'Safe\socket_set_nonblock', + 'socket_set_option' => 'Safe\socket_set_option', + 'socket_shutdown' => 'Safe\socket_shutdown', + 'socket_write' => 'Safe\socket_write', + 'socket_wsaprotocol_info_export' => 'Safe\socket_wsaprotocol_info_export', + 'socket_wsaprotocol_info_import' => 'Safe\socket_wsaprotocol_info_import', + 'socket_wsaprotocol_info_release' => 'Safe\socket_wsaprotocol_info_release', + 'sodium_crypto_pwhash' => 'Safe\sodium_crypto_pwhash', + 'sodium_crypto_pwhash_str' => 'Safe\sodium_crypto_pwhash_str', + 'solr_get_version' => 'Safe\solr_get_version', + 'sort' => 'Safe\sort', + 'soundex' => 'Safe\soundex', + 'spl_autoload_register' => 'Safe\spl_autoload_register', + 'spl_autoload_unregister' => 'Safe\spl_autoload_unregister', + 'sprintf' => 'Safe\sprintf', + 'sqlsrv_begin_transaction' => 'Safe\sqlsrv_begin_transaction', + 'sqlsrv_cancel' => 'Safe\sqlsrv_cancel', + 'sqlsrv_client_info' => 'Safe\sqlsrv_client_info', + 'sqlsrv_close' => 'Safe\sqlsrv_close', + 'sqlsrv_commit' => 'Safe\sqlsrv_commit', + 'sqlsrv_configure' => 'Safe\sqlsrv_configure', + 'sqlsrv_execute' => 'Safe\sqlsrv_execute', + 'sqlsrv_free_stmt' => 'Safe\sqlsrv_free_stmt', + 'sqlsrv_get_field' => 'Safe\sqlsrv_get_field', + 'sqlsrv_next_result' => 'Safe\sqlsrv_next_result', + 'sqlsrv_num_fields' => 'Safe\sqlsrv_num_fields', + 'sqlsrv_num_rows' => 'Safe\sqlsrv_num_rows', + 'sqlsrv_prepare' => 'Safe\sqlsrv_prepare', + 'sqlsrv_query' => 'Safe\sqlsrv_query', + 'sqlsrv_rollback' => 'Safe\sqlsrv_rollback', + 'ssdeep_fuzzy_compare' => 'Safe\ssdeep_fuzzy_compare', + 'ssdeep_fuzzy_hash' => 'Safe\ssdeep_fuzzy_hash', + 'ssdeep_fuzzy_hash_filename' => 'Safe\ssdeep_fuzzy_hash_filename', + 'ssh2_auth_agent' => 'Safe\ssh2_auth_agent', + 'ssh2_auth_hostbased_file' => 'Safe\ssh2_auth_hostbased_file', + 'ssh2_auth_password' => 'Safe\ssh2_auth_password', + 'ssh2_auth_pubkey_file' => 'Safe\ssh2_auth_pubkey_file', + 'ssh2_connect' => 'Safe\ssh2_connect', + 'ssh2_disconnect' => 'Safe\ssh2_disconnect', + 'ssh2_exec' => 'Safe\ssh2_exec', + 'ssh2_publickey_add' => 'Safe\ssh2_publickey_add', + 'ssh2_publickey_init' => 'Safe\ssh2_publickey_init', + 'ssh2_publickey_remove' => 'Safe\ssh2_publickey_remove', + 'ssh2_scp_recv' => 'Safe\ssh2_scp_recv', + 'ssh2_scp_send' => 'Safe\ssh2_scp_send', + 'ssh2_sftp' => 'Safe\ssh2_sftp', + 'ssh2_sftp_chmod' => 'Safe\ssh2_sftp_chmod', + 'ssh2_sftp_mkdir' => 'Safe\ssh2_sftp_mkdir', + 'ssh2_sftp_rename' => 'Safe\ssh2_sftp_rename', + 'ssh2_sftp_rmdir' => 'Safe\ssh2_sftp_rmdir', + 'ssh2_sftp_symlink' => 'Safe\ssh2_sftp_symlink', + 'ssh2_sftp_unlink' => 'Safe\ssh2_sftp_unlink', + 'stream_context_set_params' => 'Safe\stream_context_set_params', + 'stream_copy_to_stream' => 'Safe\stream_copy_to_stream', + 'stream_filter_append' => 'Safe\stream_filter_append', + 'stream_filter_prepend' => 'Safe\stream_filter_prepend', + 'stream_filter_register' => 'Safe\stream_filter_register', + 'stream_filter_remove' => 'Safe\stream_filter_remove', + 'stream_get_contents' => 'Safe\stream_get_contents', + 'stream_isatty' => 'Safe\stream_isatty', + 'stream_resolve_include_path' => 'Safe\stream_resolve_include_path', + 'stream_set_blocking' => 'Safe\stream_set_blocking', + 'stream_set_timeout' => 'Safe\stream_set_timeout', + 'stream_socket_accept' => 'Safe\stream_socket_accept', + 'stream_socket_client' => 'Safe\stream_socket_client', + 'stream_socket_pair' => 'Safe\stream_socket_pair', + 'stream_socket_server' => 'Safe\stream_socket_server', + 'stream_socket_shutdown' => 'Safe\stream_socket_shutdown', + 'stream_supports_lock' => 'Safe\stream_supports_lock', + 'stream_wrapper_register' => 'Safe\stream_wrapper_register', + 'stream_wrapper_restore' => 'Safe\stream_wrapper_restore', + 'stream_wrapper_unregister' => 'Safe\stream_wrapper_unregister', + 'strptime' => 'Safe\strptime', + 'strtotime' => 'Safe\strtotime', + 'substr' => 'Safe\substr', + 'swoole_async_write' => 'Safe\swoole_async_write', + 'swoole_async_writefile' => 'Safe\swoole_async_writefile', + 'swoole_event_defer' => 'Safe\swoole_event_defer', + 'swoole_event_del' => 'Safe\swoole_event_del', + 'swoole_event_write' => 'Safe\swoole_event_write', + 'symlink' => 'Safe\symlink', + 'syslog' => 'Safe\syslog', + 'system' => 'Safe\system', + 'tempnam' => 'Safe\tempnam', + 'timezone_name_from_abbr' => 'Safe\timezone_name_from_abbr', + 'time_nanosleep' => 'Safe\time_nanosleep', + 'time_sleep_until' => 'Safe\time_sleep_until', + 'tmpfile' => 'Safe\tmpfile', + 'touch' => 'Safe\touch', + 'uasort' => 'Safe\uasort', + 'uksort' => 'Safe\uksort', + 'unlink' => 'Safe\unlink', + 'unpack' => 'Safe\unpack', + 'uopz_extend' => 'Safe\uopz_extend', + 'uopz_implement' => 'Safe\uopz_implement', + 'usort' => 'Safe\usort', + 'virtual' => 'Safe\virtual', + 'vsprintf' => 'Safe\vsprintf', + 'xdiff_file_bdiff' => 'Safe\xdiff_file_bdiff', + 'xdiff_file_bpatch' => 'Safe\xdiff_file_bpatch', + 'xdiff_file_diff' => 'Safe\xdiff_file_diff', + 'xdiff_file_diff_binary' => 'Safe\xdiff_file_diff_binary', + 'xdiff_file_patch_binary' => 'Safe\xdiff_file_patch_binary', + 'xdiff_file_rabdiff' => 'Safe\xdiff_file_rabdiff', + 'xdiff_string_bpatch' => 'Safe\xdiff_string_bpatch', + 'xdiff_string_patch' => 'Safe\xdiff_string_patch', + 'xdiff_string_patch_binary' => 'Safe\xdiff_string_patch_binary', + 'xmlrpc_set_type' => 'Safe\xmlrpc_set_type', + 'xml_parser_create' => 'Safe\xml_parser_create', + 'xml_parser_create_ns' => 'Safe\xml_parser_create_ns', + 'xml_set_object' => 'Safe\xml_set_object', + 'yaml_parse' => 'Safe\yaml_parse', + 'yaml_parse_file' => 'Safe\yaml_parse_file', + 'yaml_parse_url' => 'Safe\yaml_parse_url', + 'yaz_ccl_parse' => 'Safe\yaz_ccl_parse', + 'yaz_close' => 'Safe\yaz_close', + 'yaz_connect' => 'Safe\yaz_connect', + 'yaz_database' => 'Safe\yaz_database', + 'yaz_element' => 'Safe\yaz_element', + 'yaz_present' => 'Safe\yaz_present', + 'yaz_search' => 'Safe\yaz_search', + 'yaz_wait' => 'Safe\yaz_wait', + 'zip_entry_close' => 'Safe\zip_entry_close', + 'zip_entry_open' => 'Safe\zip_entry_open', + 'zip_entry_read' => 'Safe\zip_entry_read', + 'zlib_decode' => 'Safe\zlib_decode', +]]]); +}; diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/LICENSE b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/LICENSE new file mode 100644 index 00000000..25cfdd66 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/composer.json b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/composer.json new file mode 100644 index 00000000..34d0f1ee --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/composer.json @@ -0,0 +1,31 @@ +{ + "name": "web-auth/cose-lib", + "type": "library", + "license": "MIT", + "description": "CBOR Object Signing and Encryption (COSE) For PHP", + "keywords": ["COSE", "RFC8152"], + "homepage": "https://github.com/web-auth", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/cose/contributors" + } + ], + "require": { + "php": ">=7.2", + "ext-json": "*", + "ext-openssl": "*", + "ext-mbstring": "*", + "fgrosse/phpasn1": "^2.1", + "beberlei/assert": "^3.2" + }, + "autoload": { + "psr-4": { + "Cose\\": "src/" + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Algorithm.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Algorithm.php new file mode 100644 index 00000000..c79e4057 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Algorithm.php @@ -0,0 +1,19 @@ +checKey($key); + $signature = hash_hmac($this->getHashAlgorithm(), $data, $key->get(-1), true); + + return mb_substr($signature, 0, intdiv($this->getSignatureLength(), 8), '8bit'); + } + + public function verify(string $data, Key $key, string $signature): bool + { + return hash_equals($this->hash($data, $key), $signature); + } + + abstract protected function getHashAlgorithm(): string; + + abstract protected function getSignatureLength(): int; + + private function checKey(Key $key): void + { + Assertion::eq($key->type(), 4, 'Invalid key. Must be of type symmetric'); + Assertion::true($key->has(-1), 'Invalid key. The value of the key is missing'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/Mac.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/Mac.php new file mode 100644 index 00000000..c4051cb0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Mac/Mac.php @@ -0,0 +1,24 @@ +algorithms[$identifier] = $algorithm; + } + + public function list(): iterable + { + yield from array_keys($this->algorithms); + } + + /** + * @return Algorithm[] + */ + public function all(): iterable + { + yield from $this->algorithms; + } + + public function has(int $identifier): bool + { + return array_key_exists($identifier, $this->algorithms); + } + + public function get(int $identifier): Algorithm + { + Assertion::true($this->has($identifier), 'Unsupported algorithm'); + + return $this->algorithms[$identifier]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/ManagerFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/ManagerFactory.php new file mode 100644 index 00000000..c3fb032a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/ManagerFactory.php @@ -0,0 +1,50 @@ +algorithms[$alias] = $algorithm; + } + + public function list(): iterable + { + yield from array_keys($this->algorithms); + } + + public function all(): iterable + { + yield from array_keys($this->algorithms); + } + + public function create(array $aliases): Manager + { + $manager = new Manager(); + foreach ($aliases as $alias) { + Assertion::keyExists($this->algorithms, $alias, sprintf('The algorithm with alias "%s" is not supported', $alias)); + $manager->add($this->algorithms[$alias]); + } + + return $manager; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php new file mode 100644 index 00000000..6bac0061 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php @@ -0,0 +1,53 @@ +handleKey($key); + openssl_sign($data, $signature, $key->asPEM(), $this->getHashAlgorithm()); + + return ECSignature::fromAsn1($signature, $this->getSignaturePartLength()); + } + + public function verify(string $data, Key $key, string $signature): bool + { + $key = $this->handleKey($key); + $publicKey = $key->toPublic(); + $signature = ECSignature::toAsn1($signature, $this->getSignaturePartLength()); + + return 1 === openssl_verify($data, $signature, $publicKey->asPEM(), $this->getHashAlgorithm()); + } + + abstract protected function getCurve(): int; + + abstract protected function getHashAlgorithm(): int; + + abstract protected function getSignaturePartLength(): int; + + private function handleKey(Key $key): Ec2Key + { + $key = new Ec2Key($key->getData()); + Assertion::eq($key->curve(), $this->getCurve(), 'This key cannot be used with this algorithm'); + + return $key; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php new file mode 100644 index 00000000..c4690e91 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php @@ -0,0 +1,144 @@ + self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : ''; + + $bin = hex2bin( + self::ASN1_SEQUENCE + .$lengthPrefix.dechex($totalLength) + .self::ASN1_INTEGER.dechex($lengthR).$pointR + .self::ASN1_INTEGER.dechex($lengthS).$pointS + ); + if (false === $bin) { + throw new InvalidArgumentException('Unable to convert into ASN.1'); + } + + return $bin; + } + + public static function fromAsn1(string $signature, int $length): string + { + $message = bin2hex($signature); + $position = 0; + + if (self::ASN1_SEQUENCE !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { + throw new InvalidArgumentException('Invalid data. Should start with a sequence.'); + } + + // @phpstan-ignore-next-line + if (self::ASN1_LENGTH_2BYTES === self::readAsn1Content($message, $position, self::BYTE_SIZE)) { + $position += self::BYTE_SIZE; + } + + $pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); + $pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); + + $bin = hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT).str_pad($pointS, $length, '0', STR_PAD_LEFT)); + if (false === $bin) { + throw new InvalidArgumentException('Unable to convert from ASN.1'); + } + + return $bin; + } + + private static function octetLength(string $data): int + { + return intdiv(mb_strlen($data, '8bit'), self::BYTE_SIZE); + } + + private static function preparePositiveInteger(string $data): string + { + if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) { + return self::ASN1_NEGATIVE_INTEGER.$data; + } + + while ( + self::ASN1_NEGATIVE_INTEGER === mb_substr($data, 0, self::BYTE_SIZE, '8bit') + && mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT + ) { + $data = mb_substr($data, 2, null, '8bit'); + } + + return $data; + } + + private static function readAsn1Content(string $message, int &$position, int $length): string + { + $content = mb_substr($message, $position, $length, '8bit'); + $position += $length; + + return $content; + } + + private static function readAsn1Integer(string $message, int &$position): string + { + if (self::ASN1_INTEGER !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { + throw new InvalidArgumentException('Invalid data. Should contain an integer.'); + } + + $length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE)); + + return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE); + } + + private static function retrievePositiveInteger(string $data): string + { + while ( + self::ASN1_NEGATIVE_INTEGER === mb_substr($data, 0, self::BYTE_SIZE, '8bit') + && mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT + ) { + $data = mb_substr($data, 2, null, '8bit'); + } + + return $data; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php new file mode 100644 index 00000000..5726ee4d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php @@ -0,0 +1,41 @@ +handleKey($key); + Assertion::true($key->isPrivate(), 'The key is not private'); + + $x = $key->x(); + $d = $key->d(); + $secret = $d.$x; + + switch ($key->curve()) { + case OkpKey::CURVE_ED25519: + return sodium_crypto_sign_detached($data, $secret); + default: + throw new InvalidArgumentException('Unsupported curve'); + } + } + + public function verify(string $data, Key $key, string $signature): bool + { + $key = $this->handleKey($key); + + switch ($key->curve()) { + case OkpKey::CURVE_ED25519: + return sodium_crypto_sign_verify_detached($signature, $data, $key->x()); + default: + throw new InvalidArgumentException('Unsupported curve'); + } + } + + public static function identifier(): int + { + return Algorithms::COSE_ALGORITHM_EdDSA; + } + + private function handleKey(Key $key): OkpKey + { + return new OkpKey($key->getData()); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php new file mode 100644 index 00000000..40bbeb0e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php @@ -0,0 +1,31 @@ +handleKey($key); + $modulusLength = mb_strlen($key->n(), '8bit'); + + $em = $this->encodeEMSAPSS($data, 8 * $modulusLength - 1, $this->getHashAlgorithm()); + $message = BigInteger::createFromBinaryString($em); + $signature = $this->exponentiate($key, $message); + + return $this->convertIntegerToOctetString($signature, $modulusLength); + } + + public function verify(string $data, Key $key, string $signature): bool + { + $key = $this->handleKey($key); + $modulusLength = mb_strlen($key->n(), '8bit'); + + if (mb_strlen($signature, '8bit') !== $modulusLength) { + throw new InvalidArgumentException('Invalid modulus length'); + } + $s2 = BigInteger::createFromBinaryString($signature); + $m2 = $this->exponentiate($key, $s2); + $em = $this->convertIntegerToOctetString($m2, $modulusLength); + $modBits = 8 * $modulusLength; + + return $this->verifyEMSAPSS($data, $em, $modBits - 1, $this->getHashAlgorithm()); + } + + /** + * Exponentiate with or without Chinese Remainder Theorem. + * Operation with primes 'p' and 'q' is appox. 2x faster. + */ + public function exponentiate(RsaKey $key, BigInteger $c): BigInteger + { + if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare(BigInteger::createFromBinaryString($key->n())) > 0) { + throw new RuntimeException(); + } + if ($key->isPublic() || !$key->hasPrimes() || !$key->hasExponents() || !$key->hasCoefficient()) { + return $c->modPow(BigInteger::createFromBinaryString($key->e()), BigInteger::createFromBinaryString($key->n())); + } + + [$p, $q] = $key->primes(); + [$dP, $dQ] = $key->exponents(); + $qInv = BigInteger::createFromBinaryString($key->QInv()); + + $m1 = $c->modPow($dP, $p); + $m2 = $c->modPow($dQ, $q); + $h = $qInv->multiply($m1->subtract($m2)->add($p))->mod($p); + + return $m2->add($h->multiply($q)); + } + + abstract protected function getHashAlgorithm(): Hash; + + private function handleKey(Key $key): RsaKey + { + return new RsaKey($key->getData()); + } + + private function convertIntegerToOctetString(BigInteger $x, int $xLen): string + { + $x = $x->toBytes(); + if (mb_strlen($x, '8bit') > $xLen) { + throw new RuntimeException('Unable to convert the integer'); + } + + return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); + } + + /** + * MGF1. + */ + private function getMGF1(string $mgfSeed, int $maskLen, Hash $mgfHash): string + { + $t = ''; + $count = ceil($maskLen / $mgfHash->getLength()); + for ($i = 0; $i < $count; ++$i) { + $c = pack('N', $i); + $t .= $mgfHash->hash($mgfSeed.$c); + } + + return mb_substr($t, 0, $maskLen, '8bit'); + } + + /** + * EMSA-PSS-ENCODE. + */ + private function encodeEMSAPSS(string $message, int $modulusLength, Hash $hash): string + { + $emLen = ($modulusLength + 1) >> 3; + $sLen = $hash->getLength(); + $mHash = $hash->hash($message); + if ($emLen <= $hash->getLength() + $sLen + 2) { + throw new RuntimeException(); + } + $salt = random_bytes($sLen); + $m2 = "\0\0\0\0\0\0\0\0".$mHash.$salt; + $h = $hash->hash($m2); + $ps = str_repeat(chr(0), $emLen - $sLen - $hash->getLength() - 2); + $db = $ps.chr(1).$salt; + $dbMask = $this->getMGF1($h, $emLen - $hash->getLength() - 1, $hash); + $maskedDB = $db ^ $dbMask; + $maskedDB[0] = ~chr(0xFF << ($modulusLength & 7)) & $maskedDB[0]; + + return $maskedDB.$h.chr(0xBC); + } + + /** + * EMSA-PSS-VERIFY. + */ + private function verifyEMSAPSS(string $m, string $em, int $emBits, Hash $hash): bool + { + $emLen = ($emBits + 1) >> 3; + $sLen = $hash->getLength(); + $mHash = $hash->hash($m); + if ($emLen < $hash->getLength() + $sLen + 2) { + throw new InvalidArgumentException(); + } + if ($em[mb_strlen($em, '8bit') - 1] !== chr(0xBC)) { + throw new InvalidArgumentException(); + } + $maskedDB = mb_substr($em, 0, -$hash->getLength() - 1, '8bit'); + $h = mb_substr($em, -$hash->getLength() - 1, $hash->getLength(), '8bit'); + $temp = chr(0xFF << ($emBits & 7)); + if ((~$maskedDB[0] & $temp) !== $temp) { + throw new InvalidArgumentException(); + } + $dbMask = $this->getMGF1($h, $emLen - $hash->getLength() - 1, $hash/*MGF*/); + $db = $maskedDB ^ $dbMask; + $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; + $temp = $emLen - $hash->getLength() - $sLen - 2; + if (mb_substr($db, 0, $temp, '8bit') !== str_repeat(chr(0), $temp)) { + throw new InvalidArgumentException(); + } + if (1 !== ord($db[$temp])) { + throw new InvalidArgumentException(); + } + $salt = mb_substr($db, $temp + 1, null, '8bit'); // should be $sLen long + $m2 = "\0\0\0\0\0\0\0\0".$mHash.$salt; + $h2 = $hash->hash($m2); + + return hash_equals($h, $h2); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php new file mode 100644 index 00000000..61b0400e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php @@ -0,0 +1,29 @@ +handleKey($key); + Assertion::true($key->isPrivate(), 'The key is not private'); + + if (false === openssl_sign($data, $signature, $key->asPem(), $this->getHashAlgorithm())) { + throw new InvalidArgumentException('Unable to sign the data'); + } + + return $signature; + } + + public function verify(string $data, Key $key, string $signature): bool + { + $key = $this->handleKey($key); + + return 1 === openssl_verify($data, $signature, $key->asPem(), $this->getHashAlgorithm()); + } + + abstract protected function getHashAlgorithm(): int; + + private function handleKey(Key $key): RsaKey + { + return new RsaKey($key->getData()); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/Signature.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/Signature.php new file mode 100644 index 00000000..9bf9c64f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Algorithm/Signature/Signature.php @@ -0,0 +1,24 @@ + OPENSSL_ALGO_SHA256, + self::COSE_ALGORITHM_ES384 => OPENSSL_ALGO_SHA384, + self::COSE_ALGORITHM_ES512 => OPENSSL_ALGO_SHA512, + self::COSE_ALGORITHM_RS256 => OPENSSL_ALGO_SHA256, + self::COSE_ALGORITHM_RS384 => OPENSSL_ALGO_SHA384, + self::COSE_ALGORITHM_RS512 => OPENSSL_ALGO_SHA512, + self::COSE_ALGORITHM_RS1 => OPENSSL_ALGO_SHA1, + ]; + + public const COSE_HASH_MAP = [ + self::COSE_ALGORITHM_ES256K => 'sha256', + self::COSE_ALGORITHM_ES256 => 'sha256', + self::COSE_ALGORITHM_ES384 => 'sha384', + self::COSE_ALGORITHM_ES512 => 'sha512', + self::COSE_ALGORITHM_RS256 => 'sha256', + self::COSE_ALGORITHM_RS384 => 'sha384', + self::COSE_ALGORITHM_RS512 => 'sha512', + self::COSE_ALGORITHM_PS256 => 'sha256', + self::COSE_ALGORITHM_PS384 => 'sha384', + self::COSE_ALGORITHM_PS512 => 'sha512', + self::COSE_ALGORITHM_RS1 => 'sha1', + ]; + + /** + * @throws AssertionFailedException + */ + public static function getOpensslAlgorithmFor(int $algorithmIdentifier): int + { + Assertion::keyExists(self::COSE_ALGORITHM_MAP, $algorithmIdentifier, 'The specified algorithm identifier is not supported'); + + return self::COSE_ALGORITHM_MAP[$algorithmIdentifier]; + } + + /** + * @throws AssertionFailedException + */ + public static function getHashAlgorithmFor(int $algorithmIdentifier): string + { + Assertion::keyExists(self::COSE_HASH_MAP, $algorithmIdentifier, 'The specified algorithm identifier is not supported'); + + return self::COSE_HASH_MAP[$algorithmIdentifier]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/BigInteger.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/BigInteger.php new file mode 100644 index 00000000..a7c59eb5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/BigInteger.php @@ -0,0 +1,154 @@ +value = $value; + } + + public static function createFromBinaryString(string $value): self + { + $res = unpack('H*', $value); + if (false === $res) { + throw new InvalidArgumentException('Unable to convert the data from binary'); + } + $data = current($res); + + return new self(BrickBigInteger::fromBase($data, 16)); + } + + public static function createFromDecimal(int $value): self + { + return new self(BrickBigInteger::of($value)); + } + + /** + * Converts a BigInteger to a binary string. + */ + public function toBytes(): string + { + if ($this->value->isEqualTo(BrickBigInteger::zero())) { + return ''; + } + + $temp = $this->value->toBase(16); + $temp = 0 !== (mb_strlen($temp, '8bit') & 1) ? '0'.$temp : $temp; + $temp = hex2bin($temp); + if (false === $temp) { + throw new InvalidArgumentException('Unable to convert the data into binary'); + } + + return ltrim($temp, chr(0)); + } + + /** + * Adds two BigIntegers. + * + * @param BigInteger $y + * + * @return BigInteger + */ + public function add(self $y): self + { + $value = $this->value->plus($y->value); + + return new self($value); + } + + /** + * Subtracts two BigIntegers. + * + * @param BigInteger $y + * + * @return BigInteger + */ + public function subtract(self $y): self + { + $value = $this->value->minus($y->value); + + return new self($value); + } + + /** + * Multiplies two BigIntegers. + * + * @param BigInteger $x + * + * @return BigInteger + */ + public function multiply(self $x): self + { + $value = $this->value->multipliedBy($x->value); + + return new self($value); + } + + /** + * Performs modular exponentiation. + * + * @param BigInteger $e + * @param BigInteger $n + * + * @return BigInteger + */ + public function modPow(self $e, self $n): self + { + $value = $this->value->modPow($e->value, $n->value); + + return new self($value); + } + + /** + * Performs modular exponentiation. + * + * @param BigInteger $d + * + * @return BigInteger + */ + public function mod(self $d): self + { + $value = $this->value->mod($d->value); + + return new self($value); + } + + /** + * Compares two numbers. + * + * @param BigInteger $y + */ + public function compare(self $y): int + { + return $this->value->compareTo($y->value); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Hash.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Hash.php new file mode 100644 index 00000000..2f3722cc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Hash.php @@ -0,0 +1,103 @@ +hash = $hash; + $this->length = $length; + $this->t = $t; + } + + /** + * @return Hash + */ + public static function sha1(): self + { + return new self('sha1', 20, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14"); + } + + /** + * @return Hash + */ + public static function sha256(): self + { + return new self('sha256', 32, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"); + } + + /** + * @return Hash + */ + public static function sha384(): self + { + return new self('sha384', 48, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30"); + } + + /** + * @return Hash + */ + public static function sha512(): self + { + return new self('sha512', 64, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40"); + } + + public function getLength(): int + { + return $this->length; + } + + /** + * Compute the HMAC. + */ + public function hash(string $text): string + { + return hash($this->hash, $text, true); + } + + public function name(): string + { + return $this->hash; + } + + public function t(): string + { + return $this->t; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Ec2Key.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Ec2Key.php new file mode 100644 index 00000000..b4a48eca --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Ec2Key.php @@ -0,0 +1,145 @@ + '1.2.840.10045.3.1.7', // NIST P-256 / secp256r1 + self::CURVE_P256K => '1.3.132.0.10', // NIST P-256K / secp256k1 + self::CURVE_P384 => '1.3.132.0.34', // NIST P-384 / secp384r1 + self::CURVE_P521 => '1.3.132.0.35', // NIST P-521 / secp521r1 + ]; + + private const CURVE_KEY_LENGTH = [ + self::CURVE_P256 => 32, + self::CURVE_P256K => 32, + self::CURVE_P384 => 48, + self::CURVE_P521 => 66, + ]; + + public function __construct(array $data) + { + parent::__construct($data); + Assertion::eq($data[self::TYPE], self::TYPE_EC2, 'Invalid EC2 key. The key type does not correspond to an EC2 key'); + Assertion::keyExists($data, self::DATA_CURVE, 'Invalid EC2 key. The curve is missing'); + Assertion::keyExists($data, self::DATA_X, 'Invalid EC2 key. The x coordinate is missing'); + Assertion::keyExists($data, self::DATA_Y, 'Invalid EC2 key. The y coordinate is missing'); + Assertion::length($data[self::DATA_X], self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]], 'Invalid length for x coordinate', null, '8bit'); + Assertion::length($data[self::DATA_Y], self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]], 'Invalid length for y coordinate', null, '8bit'); + Assertion::inArray((int) $data[self::DATA_CURVE], self::SUPPORTED_CURVES, 'The curve is not supported'); + } + + public function toPublic(): self + { + $data = $this->getData(); + unset($data[self::DATA_D]); + + return new self($data); + } + + public function x(): string + { + return $this->get(self::DATA_X); + } + + public function y(): string + { + return $this->get(self::DATA_Y); + } + + public function isPrivate(): bool + { + return array_key_exists(self::DATA_D, $this->getData()); + } + + public function d(): string + { + Assertion::true($this->isPrivate(), 'The key is not private'); + + return $this->get(self::DATA_D); + } + + public function curve(): int + { + return (int) $this->get(self::DATA_CURVE); + } + + public function asPEM(): string + { + if ($this->isPrivate()) { + $der = new Sequence( + new Integer(1), + new OctetString(bin2hex($this->d())), + new ExplicitlyTaggedObject(0, new ObjectIdentifier($this->getCurveOid())), + new ExplicitlyTaggedObject(1, new BitString(bin2hex($this->getUncompressedCoordinates()))) + ); + + return $this->pem('EC PRIVATE KEY', $der->getBinary()); + } + + $der = new Sequence( + new Sequence( + new ObjectIdentifier('1.2.840.10045.2.1'), + new ObjectIdentifier($this->getCurveOid()) + ), + new BitString(bin2hex($this->getUncompressedCoordinates())) + ); + + return $this->pem('PUBLIC KEY', $der->getBinary()); + } + + public function getUncompressedCoordinates(): string + { + return "\x04".$this->x().$this->y(); + } + + private function getCurveOid(): string + { + return self::NAMED_CURVE_OID[$this->curve()]; + } + + private function pem(string $type, string $der): string + { + return sprintf("-----BEGIN %s-----\n", mb_strtoupper($type)). + chunk_split(base64_encode($der), 64, "\n"). + sprintf("-----END %s-----\n", mb_strtoupper($type)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Key.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Key.php new file mode 100644 index 00000000..afb9c52c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/Key.php @@ -0,0 +1,91 @@ +data = $data; + } + + public static function createFromData(array $data): self + { + Assertion::keyExists($data, self::TYPE, 'Invalid key: the type is not defined'); + switch ($data[self::TYPE]) { + case 1: + return new OkpKey($data); + case 2: + return new Ec2Key($data); + case 3: + return new RsaKey($data); + case 4: + return new SymmetricKey($data); + default: + return new self($data); + } + } + + /** + * @return int|string + */ + public function type() + { + return $this->data[self::TYPE]; + } + + public function alg(): int + { + return (int) $this->get(self::ALG); + } + + public function getData(): array + { + return $this->data; + } + + public function has(int $key): bool + { + return array_key_exists($key, $this->data); + } + + /** + * @return mixed + */ + public function get(int $key) + { + Assertion::keyExists($this->data, $key, sprintf('The key has no data at index %d', $key)); + + return $this->data[$key]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/OkpKey.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/OkpKey.php new file mode 100644 index 00000000..2baabd4f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/OkpKey.php @@ -0,0 +1,67 @@ +get(self::DATA_X); + } + + public function isPrivate(): bool + { + return array_key_exists(self::DATA_D, $this->getData()); + } + + public function d(): string + { + Assertion::true($this->isPrivate(), 'The key is not private'); + + return $this->get(self::DATA_D); + } + + public function curve(): int + { + return (int) $this->get(self::DATA_CURVE); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/RsaKey.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/RsaKey.php new file mode 100644 index 00000000..96371f7f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/RsaKey.php @@ -0,0 +1,207 @@ +get(self::DATA_N); + } + + public function e(): string + { + return $this->get(self::DATA_E); + } + + public function d(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_D); + } + + public function p(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_P); + } + + public function q(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_Q); + } + + public function dP(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_DP); + } + + public function dQ(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_DQ); + } + + public function QInv(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_QI); + } + + public function other(): array + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_OTHER); + } + + public function rI(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_RI); + } + + public function dI(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_DI); + } + + public function tI(): string + { + Assertion::true($this->isPrivate(), 'The key is not private.'); + + return $this->get(self::DATA_TI); + } + + public function hasPrimes(): bool + { + return $this->has(self::DATA_P) && $this->has(self::DATA_Q); + } + + public function primes(): array + { + return [ + $this->p(), + $this->q(), + ]; + } + + public function hasExponents(): bool + { + return $this->has(self::DATA_DP) && $this->has(self::DATA_DQ); + } + + public function exponents(): array + { + return [ + $this->dP(), + $this->dQ(), + ]; + } + + public function hasCoefficient(): bool + { + return $this->has(self::DATA_QI); + } + + public function isPublic(): bool + { + return !$this->isPrivate(); + } + + public function isPrivate(): bool + { + return array_key_exists(self::DATA_D, $this->getData()); + } + + public function asPem(): string + { + Assertion::false($this->isPrivate(), 'Unsupported for private keys.'); + $bitSring = new Sequence( + new Integer($this->fromBase64ToInteger($this->n())), + new Integer($this->fromBase64ToInteger($this->e())) + ); + + $der = new Sequence( + new Sequence( + new ObjectIdentifier('1.2.840.113549.1.1.1'), + new NullObject() + ), + new BitString(bin2hex($bitSring->getBinary())) + ); + + return $this->pem('PUBLIC KEY', $der->getBinary()); + } + + private function fromBase64ToInteger(string $value): string + { + $data = unpack('H*', $value); + if (false === $data) { + throw new InvalidArgumentException('Unable to convert to an integer'); + } + + $hex = current($data); + + return BigInteger::fromBase($hex, 16)->toBase(10); + } + + private function pem(string $type, string $der): string + { + return sprintf("-----BEGIN %s-----\n", mb_strtoupper($type)). + chunk_split(base64_encode($der), 64, "\n"). + sprintf("-----END %s-----\n", mb_strtoupper($type)); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/SymmetricKey.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/SymmetricKey.php new file mode 100644 index 00000000..1e63562d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Key/SymmetricKey.php @@ -0,0 +1,33 @@ +get(self::DATA_K); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Verifier.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Verifier.php new file mode 100644 index 00000000..d300be8e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/cose-lib/src/Verifier.php @@ -0,0 +1,18 @@ +=7.2", + "ext-json": "*", + "beberlei/assert": "^3.2", + "league/uri": "^6.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/log": "^1.1" + }, + "suggest": { + "psr/log-implementation": "Recommended to receive logs from the library" + }, + "autoload": { + "psr-4": { + "Webauthn\\MetadataService\\": "src/" + } + }, + "suggest": { + "web-token/jwt-key-mgmt": "Mandatory for fetching Metadata Statement from distant sources", + "web-token/jwt-signature-algorithm-ecdsa": "Mandatory for fetching Metadata Statement from distant sources" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AbstractDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AbstractDescriptor.php new file mode 100644 index 00000000..06dba720 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AbstractDescriptor.php @@ -0,0 +1,49 @@ +maxRetries = $maxRetries; + $this->blockSlowdown = $blockSlowdown; + } + + public function getMaxRetries(): ?int + { + return $this->maxRetries; + } + + public function getBlockSlowdown(): ?int + { + return $this->blockSlowdown; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AuthenticatorStatus.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AuthenticatorStatus.php new file mode 100644 index 00000000..a6873c8b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/AuthenticatorStatus.php @@ -0,0 +1,58 @@ +FRR = $FRR; + $this->FAR = $FAR; + $this->EER = $EER; + $this->FAAR = $FAAR; + $this->maxReferenceDataSets = $maxReferenceDataSets; + parent::__construct($maxRetries, $blockSlowdown); + } + + public function getFAR(): ?float + { + return $this->FAR; + } + + public function getFRR(): ?float + { + return $this->FRR; + } + + public function getEER(): ?float + { + return $this->EER; + } + + public function getFAAR(): ?float + { + return $this->FAAR; + } + + public function getMaxReferenceDataSets(): ?int + { + return $this->maxReferenceDataSets; + } + + public static function createFromArray(array $data): self + { + return new self( + $data['FAR'] ?? null, + $data['FRR'] ?? null, + $data['EER'] ?? null, + $data['FAAR'] ?? null, + $data['maxReferenceDataSets'] ?? null, + $data['maxRetries'] ?? null, + $data['blockSlowdown'] ?? null + ); + } + + public function jsonSerialize(): array + { + $data = [ + 'FAR' => $this->FAR, + 'FRR' => $this->FRR, + 'EER' => $this->EER, + 'FAAR' => $this->FAAR, + 'maxReferenceDataSets' => $this->maxReferenceDataSets, + 'maxRetries' => $this->getMaxRetries(), + 'blockSlowdown' => $this->getBlockSlowdown(), + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/BiometricStatusReport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/BiometricStatusReport.php new file mode 100644 index 00000000..dae9c974 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/BiometricStatusReport.php @@ -0,0 +1,118 @@ +certLevel; + } + + public function getModality(): int + { + return $this->modality; + } + + public function getEffectiveDate(): ?string + { + return $this->effectiveDate; + } + + public function getCertificationDescriptor(): ?string + { + return $this->certificationDescriptor; + } + + public function getCertificateNumber(): ?string + { + return $this->certificateNumber; + } + + public function getCertificationPolicyVersion(): ?string + { + return $this->certificationPolicyVersion; + } + + public function getCertificationRequirementsVersion(): ?string + { + return $this->certificationRequirementsVersion; + } + + public static function createFromArray(array $data): self + { + $object = new self(); + $object->certLevel = $data['certLevel'] ?? null; + $object->modality = $data['modality'] ?? null; + $object->effectiveDate = $data['effectiveDate'] ?? null; + $object->certificationDescriptor = $data['certificationDescriptor'] ?? null; + $object->certificateNumber = $data['certificateNumber'] ?? null; + $object->certificationPolicyVersion = $data['certificationPolicyVersion'] ?? null; + $object->certificationRequirementsVersion = $data['certificationRequirementsVersion'] ?? null; + + return $object; + } + + public function jsonSerialize(): array + { + $data = [ + 'certLevel' => $this->certLevel, + 'modality' => $this->modality, + 'effectiveDate' => $this->effectiveDate, + 'certificationDescriptor' => $this->certificationDescriptor, + 'certificateNumber' => $this->certificateNumber, + 'certificationPolicyVersion' => $this->certificationPolicyVersion, + 'certificationRequirementsVersion' => $this->certificationRequirementsVersion, + ]; + + return array_filter($data, static function ($var): bool {return null !== $var; }); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/CodeAccuracyDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/CodeAccuracyDescriptor.php new file mode 100644 index 00000000..1ef25fa7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/CodeAccuracyDescriptor.php @@ -0,0 +1,73 @@ +base = $base; + $this->minLength = $minLength; + parent::__construct($maxRetries, $blockSlowdown); + } + + public function getBase(): int + { + return $this->base; + } + + public function getMinLength(): int + { + return $this->minLength; + } + + public static function createFromArray(array $data): self + { + Assertion::keyExists($data, 'base', Utils::logicException('The parameter "base" is missing')); + Assertion::keyExists($data, 'minLength', Utils::logicException('The parameter "minLength" is missing')); + + return new self( + $data['base'], + $data['minLength'], + $data['maxRetries'] ?? null, + $data['blockSlowdown'] ?? null + ); + } + + public function jsonSerialize(): array + { + $data = [ + 'base' => $this->base, + 'minLength' => $this->minLength, + 'maxRetries' => $this->getMaxRetries(), + 'blockSlowdown' => $this->getBlockSlowdown(), + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DisplayPNGCharacteristicsDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DisplayPNGCharacteristicsDescriptor.php new file mode 100644 index 00000000..deb9e6b2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DisplayPNGCharacteristicsDescriptor.php @@ -0,0 +1,172 @@ +width = $width; + $this->height = $height; + $this->bitDepth = $bitDepth; + $this->colorType = $colorType; + $this->compression = $compression; + $this->filter = $filter; + $this->interlace = $interlace; + } + + public function addPalette(RgbPaletteEntry $rgbPaletteEntry): self + { + $this->plte[] = $rgbPaletteEntry; + + return $this; + } + + public function getWidth(): int + { + return $this->width; + } + + public function getHeight(): int + { + return $this->height; + } + + public function getBitDepth(): int + { + return $this->bitDepth; + } + + public function getColorType(): int + { + return $this->colorType; + } + + public function getCompression(): int + { + return $this->compression; + } + + public function getFilter(): int + { + return $this->filter; + } + + public function getInterlace(): int + { + return $this->interlace; + } + + /** + * @return RgbPaletteEntry[] + */ + public function getPlte(): array + { + return $this->plte; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + foreach (['width', 'compression', 'height', 'bitDepth', 'colorType', 'compression', 'filter', 'interlace'] as $key) { + Assertion::keyExists($data, $key, sprintf('Invalid data. The key "%s" is missing', $key)); + } + $object = new self( + $data['width'], + $data['height'], + $data['bitDepth'], + $data['colorType'], + $data['compression'], + $data['filter'], + $data['interlace'] + ); + if (isset($data['plte'])) { + $plte = $data['plte']; + Assertion::isArray($plte, Utils::logicException('Invalid "plte" parameter')); + foreach ($plte as $item) { + $object->addPalette(RgbPaletteEntry::createFromArray($item)); + } + } + + return $object; + } + + public function jsonSerialize(): array + { + $data = [ + 'width' => $this->width, + 'height' => $this->height, + 'bitDepth' => $this->bitDepth, + 'colorType' => $this->colorType, + 'compression' => $this->compression, + 'filter' => $this->filter, + 'interlace' => $this->interlace, + 'plte' => $this->plte, + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DistantSingleMetadata.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DistantSingleMetadata.php new file mode 100644 index 00000000..b7c2991e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/DistantSingleMetadata.php @@ -0,0 +1,82 @@ +uri = $uri; + $this->isBase64Encoded = $isBase64Encoded; + $this->httpClient = $httpClient; + $this->requestFactory = $requestFactory; + $this->additionalHeaders = $additionalHeaders; + } + + public function getMetadataStatement(): MetadataStatement + { + $payload = $this->fetch(); + $json = $this->isBase64Encoded ? Base64Url::decode($payload) : $payload; + $data = json_decode($json, true); + + return MetadataStatement::createFromArray($data); + } + + private function fetch(): string + { + $request = $this->requestFactory->createRequest('GET', $this->uri); + foreach ($this->additionalHeaders as $k => $v) { + $request = $request->withHeader($k, $v); + } + $response = $this->httpClient->sendRequest($request); + Assertion::eq(200, $response->getStatusCode(), sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); + $content = $response->getBody()->getContents(); + Assertion::notEmpty($content, 'Unable to contact the server. The response has no content'); + + return $content; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/EcdaaTrustAnchor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/EcdaaTrustAnchor.php new file mode 100644 index 00000000..97a68553 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/EcdaaTrustAnchor.php @@ -0,0 +1,123 @@ +X = $X; + $this->Y = $Y; + $this->c = $c; + $this->sx = $sx; + $this->sy = $sy; + $this->G1Curve = $G1Curve; + } + + public function getX(): string + { + return $this->X; + } + + public function getY(): string + { + return $this->Y; + } + + public function getC(): string + { + return $this->c; + } + + public function getSx(): string + { + return $this->sx; + } + + public function getSy(): string + { + return $this->sy; + } + + public function getG1Curve(): string + { + return $this->G1Curve; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + foreach (['X', 'Y', 'c', 'sx', 'sy', 'G1Curve'] as $key) { + Assertion::keyExists($data, $key, sprintf('Invalid data. The key "%s" is missing', $key)); + } + + return new self( + Base64Url::decode($data['X']), + Base64Url::decode($data['Y']), + Base64Url::decode($data['c']), + Base64Url::decode($data['sx']), + Base64Url::decode($data['sy']), + $data['G1Curve'] + ); + } + + public function jsonSerialize(): array + { + $data = [ + 'X' => Base64Url::encode($this->X), + 'Y' => Base64Url::encode($this->Y), + 'c' => Base64Url::encode($this->c), + 'sx' => Base64Url::encode($this->sx), + 'sy' => Base64Url::encode($this->sy), + 'G1Curve' => $this->G1Curve, + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/ExtensionDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/ExtensionDescriptor.php new file mode 100644 index 00000000..3a520304 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/ExtensionDescriptor.php @@ -0,0 +1,106 @@ +id = $id; + $this->tag = $tag; + $this->data = $data; + $this->fail_if_unknown = $fail_if_unknown; + } + + public function getId(): string + { + return $this->id; + } + + public function getTag(): ?int + { + return $this->tag; + } + + public function getData(): ?string + { + return $this->data; + } + + public function isFailIfUnknown(): bool + { + return $this->fail_if_unknown; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + Assertion::keyExists($data, 'id', Utils::logicException('Invalid data. The parameter "id" is missing')); + Assertion::string($data['id'], Utils::logicException('Invalid data. The parameter "id" shall be a string')); + Assertion::keyExists($data, 'fail_if_unknown', Utils::logicException('Invalid data. The parameter "fail_if_unknown" is missing')); + Assertion::boolean($data['fail_if_unknown'], Utils::logicException('Invalid data. The parameter "fail_if_unknown" shall be a boolean')); + if (array_key_exists('tag', $data)) { + Assertion::integer($data['tag'], Utils::logicException('Invalid data. The parameter "tag" shall be a positive integer')); + } + if (array_key_exists('data', $data)) { + Assertion::string($data['data'], Utils::logicException('Invalid data. The parameter "data" shall be a string')); + } + + return new self( + $data['id'], + $data['tag'] ?? null, + $data['data'] ?? null, + $data['fail_if_unknown'] + ); + } + + public function jsonSerialize(): array + { + $result = [ + 'id' => $this->id, + 'tag' => $this->tag, + 'data' => $this->data, + 'fail_if_unknown' => $this->fail_if_unknown, + ]; + + return Utils::filterNullValues($result); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataService.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataService.php new file mode 100644 index 00000000..2912e098 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataService.php @@ -0,0 +1,283 @@ +serviceUri = $serviceUri; + $this->httpClient = $httpClient; + $this->requestFactory = $requestFactory; + $this->additionalQueryStringValues = $additionalQueryStringValues; + $this->additionalHeaders = $additionalHeaders; + $this->logger = $logger ?? new NullLogger(); + } + + public function addQueryStringValues(array $additionalQueryStringValues): self + { + $this->additionalQueryStringValues = $additionalQueryStringValues; + + return $this; + } + + public function addHeaders(array $additionalHeaders): self + { + $this->additionalHeaders = $additionalHeaders; + + return $this; + } + + public function setLogger(LoggerInterface $logger): self + { + $this->logger = $logger; + + return $this; + } + + public function has(string $aaguid): bool + { + try { + $toc = $this->fetchMetadataTOCPayload(); + } catch (Throwable $e) { + return false; + } + foreach ($toc->getEntries() as $entry) { + if ($entry->getAaguid() === $aaguid && null !== $entry->getUrl()) { + return true; + } + } + + return false; + } + + public function get(string $aaguid): MetadataStatement + { + $toc = $this->fetchMetadataTOCPayload(); + foreach ($toc->getEntries() as $entry) { + if ($entry->getAaguid() === $aaguid && null !== $entry->getUrl()) { + $mds = $this->fetchMetadataStatementFor($entry); + $mds + ->setStatusReports($entry->getStatusReports()) + ->setRootCertificates($toc->getRootCertificates()) + ; + + return $mds; + } + } + + throw new InvalidArgumentException(sprintf('The Metadata Statement with AAGUID "%s" is missing', $aaguid)); + } + + /** + * @deprecated This method is deprecated since v3.3 and will be removed in v4.0 + */ + public function getMetadataStatementFor(MetadataTOCPayloadEntry $entry, string $hashingFunction = 'sha256'): MetadataStatement + { + return $this->fetchMetadataStatementFor($entry, $hashingFunction); + } + + public function fetchMetadataStatementFor(MetadataTOCPayloadEntry $entry, string $hashingFunction = 'sha256'): MetadataStatement + { + $this->logger->info('Trying to get the metadata statement for a given entry', ['entry' => $entry]); + try { + $hash = $entry->getHash(); + $url = $entry->getUrl(); + if (null === $hash || null === $url) { + throw new LogicException('The Metadata Statement has not been published'); + } + $uri = $this->buildUri($url); + $result = $this->fetchMetadataStatement($uri, true, $hash, $hashingFunction); + $this->logger->info('The metadata statement exists'); + $this->logger->debug('Metadata Statement', ['mds' => $result]); + + return $result; + } catch (Throwable $throwable) { + $this->logger->error('An error occurred', [ + 'exception' => $throwable, + ]); + throw $throwable; + } + } + + /** + * @deprecated This method is deprecated since v3.3 and will be removed in v4.0 + */ + public function getMetadataTOCPayload(): MetadataTOCPayload + { + return $this->fetchMetadataTOCPayload(); + } + + private function fetchMetadataTOCPayload(): MetadataTOCPayload + { + $this->logger->info('Trying to get the metadata service TOC payload'); + try { + $uri = $this->buildUri($this->serviceUri); + $toc = $this->fetchTableOfContent($uri); + $this->logger->info('The TOC payload has been received'); + $this->logger->debug('TOC payload', ['toc' => $toc]); + + return $toc; + } catch (Throwable $throwable) { + $this->logger->error('An error occurred', [ + 'exception' => $throwable, + ]); + throw $throwable; + } + } + + private function buildUri(string $uri): string + { + $parsedUri = UriString::parse($uri); + $queryString = $parsedUri['query']; + $query = []; + if (null !== $queryString) { + parse_str($queryString, $query); + } + foreach ($this->additionalQueryStringValues as $k => $v) { + if (!isset($query[$k])) { + $query[$k] = $v; + continue; + } + if (!is_array($query[$k])) { + $query[$k] = [$query[$k], $v]; + continue; + } + $query[$k][] = $v; + } + $parsedUri['query'] = 0 === count($query) ? null : http_build_query($query, '', '&', PHP_QUERY_RFC3986); + + return UriString::build($parsedUri); + } + + private function fetchTableOfContent(string $uri): MetadataTOCPayload + { + $content = $this->fetch($uri); + $rootCertificates = []; + $payload = $this->getJwsPayload($content, $rootCertificates); + $data = json_decode($payload, true); + + $toc = MetadataTOCPayload::createFromArray($data); + $toc->setRootCertificates($rootCertificates); + + return $toc; + } + + private function fetchMetadataStatement(string $uri, bool $isBase64UrlEncoded, string $hash = '', string $hashingFunction = 'sha256'): MetadataStatement + { + $payload = $this->fetch($uri); + if ('' !== $hash) { + Assertion::true(hash_equals($hash, hash($hashingFunction, $payload, true)), 'The hash cannot be verified. The metadata statement shall be rejected'); + } + $json = $isBase64UrlEncoded ? Base64Url::decode($payload) : $payload; + $data = json_decode($json, true); + + return MetadataStatement::createFromArray($data); + } + + private function fetch(string $uri): string + { + $request = $this->requestFactory->createRequest('GET', $uri); + foreach ($this->additionalHeaders as $k => $v) { + $request = $request->withHeader($k, $v); + } + $response = $this->httpClient->sendRequest($request); + Assertion::eq(200, $response->getStatusCode(), sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); + $content = $response->getBody()->getContents(); + Assertion::notEmpty($content, 'Unable to contact the server. The response has no content'); + + return $content; + } + + private function getJwsPayload(string $token, array &$rootCertificates): string + { + $jws = (new CompactSerializer())->unserialize($token); + Assertion::eq(1, $jws->countSignatures(), 'Invalid response from the metadata service. Only one signature shall be present.'); + $signature = $jws->getSignature(0); + $payload = $jws->getPayload(); + Assertion::notEmpty($payload, 'Invalid response from the metadata service. The token payload is empty.'); + $header = $signature->getProtectedHeader(); + Assertion::keyExists($header, 'alg', 'The "alg" parameter is missing.'); + Assertion::eq($header['alg'], 'ES256', 'The expected "alg" parameter value should be "ES256".'); + Assertion::keyExists($header, 'x5c', 'The "x5c" parameter is missing.'); + Assertion::isArray($header['x5c'], 'The "x5c" parameter should be an array.'); + $key = JWKFactory::createFromX5C($header['x5c']); + $rootCertificates = array_map(static function (string $x509): string { + return CertificateToolbox::fixPEMStructure($x509); + }, $header['x5c']); + $algorithm = new ES256(); + $isValid = $algorithm->verify($key, $signature->getEncodedProtectedHeader().'.'.$jws->getEncodedPayload(), $signature->getSignature()); + Assertion::true($isValid, 'Invalid response from the metadata service. The token signature is invalid.'); + + return $jws->getPayload(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatement.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatement.php new file mode 100644 index 00000000..5b915bf6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatement.php @@ -0,0 +1,602 @@ + + */ + private $statusReports = []; + + /** + * @var string[] + */ + private $rootCertificates = []; + + public static function createFromString(string $statement): self + { + $data = json_decode($statement, true); + Assertion::isArray($data, 'Invalid Metadata Statement'); + + return self::createFromArray($data); + } + + public function getLegalHeader(): ?string + { + return $this->legalHeader; + } + + public function getAaid(): ?string + { + return $this->aaid; + } + + public function getAaguid(): ?string + { + return $this->aaguid; + } + + /** + * @return string[] + */ + public function getAttestationCertificateKeyIdentifiers(): array + { + return $this->attestationCertificateKeyIdentifiers; + } + + public function getDescription(): string + { + return $this->description; + } + + /** + * @return string[] + */ + public function getAlternativeDescriptions(): array + { + return $this->alternativeDescriptions; + } + + public function getAuthenticatorVersion(): int + { + return $this->authenticatorVersion; + } + + public function getProtocolFamily(): string + { + return $this->protocolFamily; + } + + /** + * @return Version[] + */ + public function getUpv(): array + { + return $this->upv; + } + + public function getAssertionScheme(): ?string + { + return $this->assertionScheme; + } + + public function getAuthenticationAlgorithm(): ?int + { + return $this->authenticationAlgorithm; + } + + /** + * @return int[] + */ + public function getAuthenticationAlgorithms(): array + { + return $this->authenticationAlgorithms; + } + + public function getPublicKeyAlgAndEncoding(): ?int + { + return $this->publicKeyAlgAndEncoding; + } + + /** + * @return int[] + */ + public function getPublicKeyAlgAndEncodings(): array + { + return $this->publicKeyAlgAndEncodings; + } + + /** + * @return int[] + */ + public function getAttestationTypes(): array + { + return $this->attestationTypes; + } + + /** + * @return VerificationMethodANDCombinations[] + */ + public function getUserVerificationDetails(): array + { + return $this->userVerificationDetails; + } + + public function getKeyProtection(): int + { + return $this->keyProtection; + } + + public function isKeyRestricted(): ?bool + { + return (bool) $this->isKeyRestricted; + } + + public function isFreshUserVerificationRequired(): ?bool + { + return (bool) $this->isFreshUserVerificationRequired; + } + + public function getMatcherProtection(): int + { + return $this->matcherProtection; + } + + public function getCryptoStrength(): ?int + { + return $this->cryptoStrength; + } + + public function getOperatingEnv(): ?string + { + return $this->operatingEnv; + } + + public function getAttachmentHint(): int + { + return $this->attachmentHint; + } + + public function isSecondFactorOnly(): ?bool + { + return (bool) $this->isSecondFactorOnly; + } + + public function getTcDisplay(): int + { + return $this->tcDisplay; + } + + public function getTcDisplayContentType(): ?string + { + return $this->tcDisplayContentType; + } + + /** + * @return DisplayPNGCharacteristicsDescriptor[] + */ + public function getTcDisplayPNGCharacteristics(): array + { + return $this->tcDisplayPNGCharacteristics; + } + + /** + * @return string[] + */ + public function getAttestationRootCertificates(): array + { + return $this->attestationRootCertificates; + } + + /** + * @return EcdaaTrustAnchor[] + */ + public function getEcdaaTrustAnchors(): array + { + return $this->ecdaaTrustAnchors; + } + + public function getIcon(): ?string + { + return $this->icon; + } + + /** + * @return ExtensionDescriptor[] + */ + public function getSupportedExtensions(): array + { + return $this->supportedExtensions; + } + + public static function createFromArray(array $data): self + { + $object = new self(); + foreach (['description', 'protocolFamily'] as $key) { + if (!isset($data[$key])) { + throw new InvalidArgumentException(sprintf('The parameter "%s" is missing', $key)); + } + } + $object->legalHeader = $data['legalHeader'] ?? null; + $object->aaid = $data['aaid'] ?? null; + $object->aaguid = $data['aaguid'] ?? null; + $object->attestationCertificateKeyIdentifiers = $data['attestationCertificateKeyIdentifiers'] ?? []; + $object->description = $data['description']; + $object->alternativeDescriptions = $data['alternativeDescriptions'] ?? []; + $object->authenticatorVersion = $data['authenticatorVersion'] ?? 0; + $object->protocolFamily = $data['protocolFamily']; + if (isset($data['upv'])) { + $upv = $data['upv']; + Assertion::isArray($upv, 'Invalid Metadata Statement'); + foreach ($upv as $value) { + Assertion::isArray($value, 'Invalid Metadata Statement'); + $object->upv[] = Version::createFromArray($value); + } + } + $object->assertionScheme = $data['assertionScheme'] ?? null; + $object->authenticationAlgorithm = $data['authenticationAlgorithm'] ?? null; + $object->authenticationAlgorithms = $data['authenticationAlgorithms'] ?? []; + $object->publicKeyAlgAndEncoding = $data['publicKeyAlgAndEncoding'] ?? null; + $object->publicKeyAlgAndEncodings = $data['publicKeyAlgAndEncodings'] ?? []; + $object->attestationTypes = $data['attestationTypes'] ?? []; + if (isset($data['userVerificationDetails'])) { + $userVerificationDetails = $data['userVerificationDetails']; + Assertion::isArray($userVerificationDetails, 'Invalid Metadata Statement'); + foreach ($userVerificationDetails as $value) { + Assertion::isArray($value, 'Invalid Metadata Statement'); + $object->userVerificationDetails[] = VerificationMethodANDCombinations::createFromArray($value); + } + } + $object->keyProtection = $data['keyProtection'] ?? 0; + $object->isKeyRestricted = $data['isKeyRestricted'] ?? null; + $object->isFreshUserVerificationRequired = $data['isFreshUserVerificationRequired'] ?? null; + $object->matcherProtection = $data['matcherProtection'] ?? 0; + $object->cryptoStrength = $data['cryptoStrength'] ?? null; + $object->operatingEnv = $data['operatingEnv'] ?? null; + $object->attachmentHint = $data['attachmentHint'] ?? 0; + $object->isSecondFactorOnly = $data['isSecondFactorOnly'] ?? null; + $object->tcDisplay = $data['tcDisplay'] ?? 0; + $object->tcDisplayContentType = $data['tcDisplayContentType'] ?? null; + if (isset($data['tcDisplayPNGCharacteristics'])) { + $tcDisplayPNGCharacteristics = $data['tcDisplayPNGCharacteristics']; + Assertion::isArray($tcDisplayPNGCharacteristics, 'Invalid Metadata Statement'); + foreach ($tcDisplayPNGCharacteristics as $tcDisplayPNGCharacteristic) { + Assertion::isArray($tcDisplayPNGCharacteristic, 'Invalid Metadata Statement'); + $object->tcDisplayPNGCharacteristics[] = DisplayPNGCharacteristicsDescriptor::createFromArray($tcDisplayPNGCharacteristic); + } + } + $object->attestationRootCertificates = $data['attestationRootCertificates'] ?? []; + $object->ecdaaTrustAnchors = $data['ecdaaTrustAnchors'] ?? []; + $object->icon = $data['icon'] ?? null; + if (isset($data['supportedExtensions'])) { + $supportedExtensions = $data['supportedExtensions']; + Assertion::isArray($supportedExtensions, 'Invalid Metadata Statement'); + foreach ($supportedExtensions as $supportedExtension) { + Assertion::isArray($supportedExtension, 'Invalid Metadata Statement'); + $object->supportedExtensions[] = ExtensionDescriptor::createFromArray($supportedExtension); + } + } + $object->rootCertificates = $data['rootCertificates'] ?? []; + if (isset($data['statusReports'])) { + $reports = $data['statusReports']; + Assertion::isArray($reports, 'Invalid Metadata Statement'); + foreach ($reports as $report) { + Assertion::isArray($report, 'Invalid Metadata Statement'); + $object->statusReports[] = StatusReport::createFromArray($report); + } + } + + return $object; + } + + public function jsonSerialize(): array + { + $data = [ + 'legalHeader' => $this->legalHeader, + 'aaid' => $this->aaid, + 'aaguid' => $this->aaguid, + 'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, + 'description' => $this->description, + 'alternativeDescriptions' => $this->alternativeDescriptions, + 'authenticatorVersion' => $this->authenticatorVersion, + 'protocolFamily' => $this->protocolFamily, + 'upv' => $this->upv, + 'assertionScheme' => $this->assertionScheme, + 'authenticationAlgorithm' => $this->authenticationAlgorithm, + 'authenticationAlgorithms' => $this->authenticationAlgorithms, + 'publicKeyAlgAndEncoding' => $this->publicKeyAlgAndEncoding, + 'publicKeyAlgAndEncodings' => $this->publicKeyAlgAndEncodings, + 'attestationTypes' => $this->attestationTypes, + 'userVerificationDetails' => $this->userVerificationDetails, + 'keyProtection' => $this->keyProtection, + 'isKeyRestricted' => $this->isKeyRestricted, + 'isFreshUserVerificationRequired' => $this->isFreshUserVerificationRequired, + 'matcherProtection' => $this->matcherProtection, + 'cryptoStrength' => $this->cryptoStrength, + 'operatingEnv' => $this->operatingEnv, + 'attachmentHint' => $this->attachmentHint, + 'isSecondFactorOnly' => $this->isSecondFactorOnly, + 'tcDisplay' => $this->tcDisplay, + 'tcDisplayContentType' => $this->tcDisplayContentType, + 'tcDisplayPNGCharacteristics' => array_map(static function (DisplayPNGCharacteristicsDescriptor $object): array { + return $object->jsonSerialize(); + }, $this->tcDisplayPNGCharacteristics), + 'attestationRootCertificates' => $this->attestationRootCertificates, + 'ecdaaTrustAnchors' => array_map(static function (EcdaaTrustAnchor $object): array { + return $object->jsonSerialize(); + }, $this->ecdaaTrustAnchors), + 'icon' => $this->icon, + 'supportedExtensions' => array_map(static function (ExtensionDescriptor $object): array { + return $object->jsonSerialize(); + }, $this->supportedExtensions), + 'rootCertificates' => $this->rootCertificates, + 'statusReports' => $this->statusReports, + ]; + + return Utils::filterNullValues($data); + } + + /** + * @return StatusReport[] + */ + public function getStatusReports(): array + { + return $this->statusReports; + } + + /** + * @param StatusReport[] $statusReports + */ + public function setStatusReports(array $statusReports): self + { + $this->statusReports = $statusReports; + + return $this; + } + + /** + * @return string[] + */ + public function getRootCertificates(): array + { + return $this->rootCertificates; + } + + /** + * @param string[] $rootCertificates + */ + public function setRootCertificates(array $rootCertificates): self + { + $this->rootCertificates = $rootCertificates; + + return $this; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementFetcher.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementFetcher.php new file mode 100644 index 00000000..b8ab6379 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementFetcher.php @@ -0,0 +1,85 @@ +createRequest('GET', $uri); + foreach ($additionalHeaders as $k => $v) { + $request = $request->withHeader($k, $v); + } + $response = $client->sendRequest($request); + Assertion::eq(200, $response->getStatusCode(), sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); + $content = $response->getBody()->getContents(); + Assertion::notEmpty($content, 'Unable to contact the server. The response has no content'); + + return $content; + } + + private static function getJwsPayload(string $token): string + { + $jws = (new CompactSerializer())->unserialize($token); + Assertion::eq(1, $jws->countSignatures(), 'Invalid response from the metadata service. Only one signature shall be present.'); + $signature = $jws->getSignature(0); + $payload = $jws->getPayload(); + Assertion::notEmpty($payload, 'Invalid response from the metadata service. The token payload is empty.'); + $header = $signature->getProtectedHeader(); + Assertion::keyExists($header, 'alg', 'The "alg" parameter is missing.'); + Assertion::eq($header['alg'], 'ES256', 'The expected "alg" parameter value should be "ES256".'); + Assertion::keyExists($header, 'x5c', 'The "x5c" parameter is missing.'); + Assertion::isArray($header['x5c'], 'The "x5c" parameter should be an array.'); + $key = JWKFactory::createFromX5C($header['x5c']); + $algorithm = new ES256(); + $isValid = $algorithm->verify($key, $signature->getEncodedProtectedHeader().'.'.$jws->getEncodedPayload(), $signature->getSignature()); + Assertion::true($isValid, 'Invalid response from the metadata service. The token signature is invalid.'); + + return $jws->getPayload(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementRepository.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementRepository.php new file mode 100644 index 00000000..c1bd6913 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataStatementRepository.php @@ -0,0 +1,26 @@ +no = $no; + $this->nextUpdate = $nextUpdate; + $this->legalHeader = $legalHeader; + } + + public function addEntry(MetadataTOCPayloadEntry $entry): self + { + $this->entries[] = $entry; + + return $this; + } + + public function getLegalHeader(): ?string + { + return $this->legalHeader; + } + + public function getNo(): int + { + return $this->no; + } + + public function getNextUpdate(): string + { + return $this->nextUpdate; + } + + /** + * @return MetadataTOCPayloadEntry[] + */ + public function getEntries(): array + { + return $this->entries; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + foreach (['no', 'nextUpdate', 'entries'] as $key) { + Assertion::keyExists($data, $key, Utils::logicException(sprintf('Invalid data. The parameter "%s" is missing', $key))); + } + Assertion::integer($data['no'], Utils::logicException('Invalid data. The parameter "no" shall be an integer')); + Assertion::string($data['nextUpdate'], Utils::logicException('Invalid data. The parameter "nextUpdate" shall be a string')); + Assertion::isArray($data['entries'], Utils::logicException('Invalid data. The parameter "entries" shall be a n array of entries')); + if (array_key_exists('legalHeader', $data)) { + Assertion::string($data['legalHeader'], Utils::logicException('Invalid data. The parameter "legalHeader" shall be a string')); + } + $object = new self( + $data['no'], + $data['nextUpdate'], + $data['legalHeader'] ?? null + ); + foreach ($data['entries'] as $k => $entry) { + $object->addEntry(MetadataTOCPayloadEntry::createFromArray($entry)); + } + $object->rootCertificates = $data['rootCertificates'] ?? []; + + return $object; + } + + public function jsonSerialize(): array + { + $data = [ + 'legalHeader' => $this->legalHeader, + 'nextUpdate' => $this->nextUpdate, + 'no' => $this->no, + 'entries' => array_map(static function (MetadataTOCPayloadEntry $object): array { + return $object->jsonSerialize(); + }, $this->entries), + 'rootCertificates' => $this->rootCertificates, + ]; + + return Utils::filterNullValues($data); + } + + /** + * @return string[] + */ + public function getRootCertificates(): array + { + return $this->rootCertificates; + } + + /** + * @param string[] $rootCertificates + */ + public function setRootCertificates(array $rootCertificates): self + { + $this->rootCertificates = $rootCertificates; + + return $this; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataTOCPayloadEntry.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataTOCPayloadEntry.php new file mode 100644 index 00000000..16b1a311 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/MetadataTOCPayloadEntry.php @@ -0,0 +1,188 @@ +aaid = $aaid; + $this->aaguid = $aaguid; + $this->attestationCertificateKeyIdentifiers = $attestationCertificateKeyIdentifiers; + $this->hash = Base64Url::decode($hash); + $this->url = $url; + $this->timeOfLastStatusChange = $timeOfLastStatusChange; + $this->rogueListURL = $rogueListURL; + $this->rogueListHash = $rogueListHash; + } + + public function getAaid(): ?string + { + return $this->aaid; + } + + public function getAaguid(): ?string + { + return $this->aaguid; + } + + public function getAttestationCertificateKeyIdentifiers(): array + { + return $this->attestationCertificateKeyIdentifiers; + } + + public function getHash(): ?string + { + return $this->hash; + } + + public function getUrl(): ?string + { + return $this->url; + } + + public function addStatusReports(StatusReport $statusReport): self + { + $this->statusReports[] = $statusReport; + + return $this; + } + + /** + * @return StatusReport[] + */ + public function getStatusReports(): array + { + return $this->statusReports; + } + + public function getTimeOfLastStatusChange(): string + { + return $this->timeOfLastStatusChange; + } + + public function getRogueListURL(): string + { + return $this->rogueListURL; + } + + public function getRogueListHash(): string + { + return $this->rogueListHash; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + Assertion::keyExists($data, 'timeOfLastStatusChange', Utils::logicException('Invalid data. The parameter "timeOfLastStatusChange" is missing')); + Assertion::keyExists($data, 'statusReports', Utils::logicException('Invalid data. The parameter "statusReports" is missing')); + Assertion::isArray($data['statusReports'], Utils::logicException('Invalid data. The parameter "statusReports" shall be an array of StatusReport objects')); + $object = new self( + $data['aaid'] ?? null, + $data['aaguid'] ?? null, + $data['attestationCertificateKeyIdentifiers'] ?? [], + $data['hash'] ?? null, + $data['url'] ?? null, + $data['timeOfLastStatusChange'], + $data['rogueListURL'] ?? null, + $data['rogueListHash'] ?? null + ); + foreach ($data['statusReports'] as $statusReport) { + $object->addStatusReports(StatusReport::createFromArray($statusReport)); + } + + return $object; + } + + public function jsonSerialize(): array + { + $data = [ + 'aaid' => $this->aaid, + 'aaguid' => $this->aaguid, + 'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, + 'hash' => Base64Url::encode($this->hash), + 'url' => $this->url, + 'statusReports' => array_map(static function (StatusReport $object): array { + return $object->jsonSerialize(); + }, $this->statusReports), + 'timeOfLastStatusChange' => $this->timeOfLastStatusChange, + 'rogueListURL' => $this->rogueListURL, + 'rogueListHash' => $this->rogueListHash, + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/PatternAccuracyDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/PatternAccuracyDescriptor.php new file mode 100644 index 00000000..6f401b8f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/PatternAccuracyDescriptor.php @@ -0,0 +1,66 @@ +minComplexity = $minComplexity; + parent::__construct($maxRetries, $blockSlowdown); + } + + public function getMinComplexity(): int + { + return $this->minComplexity; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + Assertion::keyExists($data, 'minComplexity', Utils::logicException('The key "minComplexity" is missing')); + foreach (['minComplexity', 'maxRetries', 'blockSlowdown'] as $key) { + if (array_key_exists($key, $data)) { + Assertion::integer($data[$key], Utils::logicException(sprintf('Invalid data. The value of "%s" must be a positive integer', $key))); + } + } + + return new self( + $data['minComplexity'], + $data['maxRetries'] ?? null, + $data['blockSlowdown'] ?? null + ); + } + + public function jsonSerialize(): array + { + $data = [ + 'minComplexity' => $this->minComplexity, + 'maxRetries' => $this->getMaxRetries(), + 'blockSlowdown' => $this->getBlockSlowdown(), + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RgbPaletteEntry.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RgbPaletteEntry.php new file mode 100644 index 00000000..d5eb5867 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RgbPaletteEntry.php @@ -0,0 +1,84 @@ +r = $r; + $this->g = $g; + $this->b = $b; + } + + public function getR(): int + { + return $this->r; + } + + public function getG(): int + { + return $this->g; + } + + public function getB(): int + { + return $this->b; + } + + public static function createFromArray(array $data): self + { + foreach (['r', 'g', 'b'] as $key) { + Assertion::keyExists($data, $key, sprintf('The key "%s" is missing', $key)); + Assertion::integer($data[$key], sprintf('The key "%s" is invalid', $key)); + } + + return new self( + $data['r'], + $data['g'], + $data['b'] + ); + } + + public function jsonSerialize(): array + { + return [ + 'r' => $this->r, + 'g' => $this->g, + 'b' => $this->b, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RogueListEntry.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RogueListEntry.php new file mode 100644 index 00000000..83c1d447 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/RogueListEntry.php @@ -0,0 +1,67 @@ +sk = $sk; + $this->date = $date; + } + + public function getSk(): string + { + return $this->sk; + } + + public function getDate(): ?string + { + return $this->date; + } + + public static function createFromArray(array $data): self + { + Assertion::keyExists($data, 'sk', 'The key "sk" is missing'); + Assertion::string($data['sk'], 'The key "sk" is invalid'); + Assertion::keyExists($data, 'date', 'The key "date" is missing'); + Assertion::string($data['date'], 'The key "date" is invalid'); + + return new self( + $data['sk'], + $data['date'] + ); + } + + public function jsonSerialize(): array + { + return [ + 'sk' => $this->sk, + 'date' => $this->date, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/SingleMetadata.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/SingleMetadata.php new file mode 100644 index 00000000..f3e3cd4c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/SingleMetadata.php @@ -0,0 +1,53 @@ +data = $data; + $this->isBase64Encoded = $isBase64Encoded; + } + + public function getMetadataStatement(): MetadataStatement + { + if (null === $this->statement) { + $json = $this->data; + if ($this->isBase64Encoded) { + $json = base64_decode($this->data, true); + } + $statement = json_decode($json, true); + $this->statement = MetadataStatement::createFromArray($statement); + } + + return $this->statement; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/StatusReport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/StatusReport.php new file mode 100644 index 00000000..60166384 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/StatusReport.php @@ -0,0 +1,166 @@ +status = $status; + $this->effectiveDate = $effectiveDate; + $this->certificate = $certificate; + $this->url = $url; + $this->certificationDescriptor = $certificationDescriptor; + $this->certificateNumber = $certificateNumber; + $this->certificationPolicyVersion = $certificationPolicyVersion; + $this->certificationRequirementsVersion = $certificationRequirementsVersion; + } + + public function isCompromised(): bool + { + return in_array($this->status, [ + AuthenticatorStatus::ATTESTATION_KEY_COMPROMISE, + AuthenticatorStatus::USER_KEY_PHYSICAL_COMPROMISE, + AuthenticatorStatus::USER_KEY_REMOTE_COMPROMISE, + AuthenticatorStatus::USER_VERIFICATION_BYPASS, + ], true); + } + + public function getStatus(): string + { + return $this->status; + } + + public function getEffectiveDate(): ?string + { + return $this->effectiveDate; + } + + public function getCertificate(): ?string + { + return $this->certificate; + } + + public function getUrl(): ?string + { + return $this->url; + } + + public function getCertificationDescriptor(): ?string + { + return $this->certificationDescriptor; + } + + public function getCertificateNumber(): ?string + { + return $this->certificateNumber; + } + + public function getCertificationPolicyVersion(): ?string + { + return $this->certificationPolicyVersion; + } + + public function getCertificationRequirementsVersion(): ?string + { + return $this->certificationRequirementsVersion; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + Assertion::keyExists($data, 'status', Utils::logicException('The key "status" is missing')); + foreach (['effectiveDate', 'certificate', 'url', 'certificationDescriptor', 'certificateNumber', 'certificationPolicyVersion', 'certificationRequirementsVersion'] as $key) { + if (isset($data[$key])) { + Assertion::nullOrString($data[$key], Utils::logicException(sprintf('The value of the key "%s" is invalid', $key))); + } + } + + return new self( + $data['status'], + $data['effectiveDate'] ?? null, + $data['certificate'] ?? null, + $data['url'] ?? null, + $data['certificationDescriptor'] ?? null, + $data['certificateNumber'] ?? null, + $data['certificationPolicyVersion'] ?? null, + $data['certificationRequirementsVersion'] ?? null + ); + } + + public function jsonSerialize(): array + { + $data = [ + 'status' => $this->status, + 'effectiveDate' => $this->effectiveDate, + 'certificate' => $this->certificate, + 'url' => $this->url, + 'certificationDescriptor' => $this->certificationDescriptor, + 'certificateNumber' => $this->certificateNumber, + 'certificationPolicyVersion' => $this->certificationPolicyVersion, + 'certificationRequirementsVersion' => $this->certificationRequirementsVersion, + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Utils.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Utils.php new file mode 100644 index 00000000..469475a8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Utils.php @@ -0,0 +1,35 @@ +verificationMethods[] = $verificationMethodDescriptor; + + return $this; + } + + /** + * @return VerificationMethodDescriptor[] + */ + public function getVerificationMethods(): array + { + return $this->verificationMethods; + } + + public static function createFromArray(array $data): self + { + $object = new self(); + + foreach ($data as $datum) { + Assertion::isArray($datum, Utils::logicException('Invalid data')); + $object->addVerificationMethodDescriptor(VerificationMethodDescriptor::createFromArray($datum)); + } + + return $object; + } + + public function jsonSerialize(): array + { + return array_map(static function (VerificationMethodDescriptor $object): array { + return $object->jsonSerialize(); + }, $this->verificationMethods); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/VerificationMethodDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/VerificationMethodDescriptor.php new file mode 100644 index 00000000..0105900d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/VerificationMethodDescriptor.php @@ -0,0 +1,168 @@ +userVerification = $userVerification; + $this->caDesc = $caDesc; + $this->baDesc = $baDesc; + $this->paDesc = $paDesc; + } + + public function getUserVerification(): int + { + return $this->userVerification; + } + + public function userPresence(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_PRESENCE); + } + + public function fingerprint(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_FINGERPRINT); + } + + public function passcode(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_PASSCODE); + } + + public function voicePrint(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_VOICEPRINT); + } + + public function facePrint(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_FACEPRINT); + } + + public function location(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_LOCATION); + } + + public function eyePrint(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_EYEPRINT); + } + + public function pattern(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_PATTERN); + } + + public function handprint(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_HANDPRINT); + } + + public function none(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_NONE); + } + + public function all(): bool + { + return 0 !== ($this->userVerification & self::USER_VERIFY_ALL); + } + + public function getCaDesc(): ?CodeAccuracyDescriptor + { + return $this->caDesc; + } + + public function getBaDesc(): ?BiometricAccuracyDescriptor + { + return $this->baDesc; + } + + public function getPaDesc(): ?PatternAccuracyDescriptor + { + return $this->paDesc; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + Assertion::keyExists($data, 'userVerification', Utils::logicException('The parameter "userVerification" is missing')); + Assertion::integer($data['userVerification'], Utils::logicException('The parameter "userVerification" is invalid')); + foreach (['caDesc', 'baDesc', 'paDesc'] as $key) { + if (isset($data[$key])) { + Assertion::isArray($data[$key], Utils::logicException(sprintf('Invalid parameter "%s"', $key))); + } + } + + return new self( + $data['userVerification'], + isset($data['caDesc']) ? CodeAccuracyDescriptor::createFromArray($data['caDesc']) : null, + isset($data['baDesc']) ? BiometricAccuracyDescriptor::createFromArray($data['baDesc']) : null, + isset($data['paDesc']) ? PatternAccuracyDescriptor::createFromArray($data['paDesc']) : null + ); + } + + public function jsonSerialize(): array + { + $data = [ + 'userVerification' => $this->userVerification, + 'caDesc' => null === $this->caDesc ? null : $this->caDesc->jsonSerialize(), + 'baDesc' => null === $this->baDesc ? null : $this->baDesc->jsonSerialize(), + 'paDesc' => null === $this->paDesc ? null : $this->paDesc->jsonSerialize(), + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Version.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Version.php new file mode 100644 index 00000000..53efda8a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/metadata-service/src/Version.php @@ -0,0 +1,80 @@ +major = $major; + $this->minor = $minor; + } + + public function getMajor(): ?int + { + return $this->major; + } + + public function getMinor(): ?int + { + return $this->minor; + } + + public static function createFromArray(array $data): self + { + $data = Utils::filterNullValues($data); + foreach (['major', 'minor'] as $key) { + if (array_key_exists($key, $data)) { + Assertion::integer($data[$key], sprintf('Invalid value for key "%s"', $key)); + } + } + + return new self( + $data['major'] ?? null, + $data['minor'] ?? null + ); + } + + public function jsonSerialize(): array + { + $data = [ + 'major' => $this->major, + 'minor' => $this->minor, + ]; + + return Utils::filterNullValues($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/LICENSE b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/LICENSE new file mode 100644 index 00000000..25cfdd66 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/composer.json b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/composer.json new file mode 100644 index 00000000..72ff1da9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/composer.json @@ -0,0 +1,49 @@ +{ + "name": "web-auth/webauthn-lib", + "type": "library", + "license": "MIT", + "description": "FIDO2/Webauthn Support For PHP", + "keywords": ["FIDO", "FIDO2", "webauthn"], + "homepage": "https://github.com/web-auth", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/webauthn-library/contributors" + } + ], + "require": { + "php": ">=7.2", + "ext-json": "*", + "ext-openssl": "*", + "ext-mbstring": "*", + "beberlei/assert": "^3.2", + "fgrosse/phpasn1": "^2.1", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "psr/log": "^1.1", + "ramsey/uuid": "^3.8|^4.0", + "spomky-labs/base64url": "^2.0", + "spomky-labs/cbor-php": "^1.0|^2.0", + "symfony/process": "^3.0|^4.0|^5.0", + "thecodingmachine/safe": "^1.1", + "web-auth/cose-lib": "self.version", + "web-auth/metadata-service": "self.version" + }, + "autoload": { + "psr-4": { + "Webauthn\\": "src/" + } + }, + "suggest": { + "psr/log-implementation": "Recommended to receive logs from the library", + "web-token/jwt-key-mgmt": "Mandatory for the AndroidSafetyNet Attestation Statement support", + "web-token/jwt-signature-algorithm-rsa": "Mandatory for the AndroidSafetyNet Attestation Statement support", + "web-token/jwt-signature-algorithm-ecdsa": "Recommended for the AndroidSafetyNet Attestation Statement support", + "web-token/jwt-signature-algorithm-eddsa": "Recommended for the AndroidSafetyNet Attestation Statement support" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php new file mode 100644 index 00000000..308bd955 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php @@ -0,0 +1,147 @@ +decoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + } + + public function name(): string + { + return 'android-key'; + } + + /** + * @param mixed[] $attestation + */ + public function load(array $attestation): AttestationStatement + { + Assertion::keyExists($attestation, 'attStmt', 'Invalid attestation object'); + foreach (['sig', 'x5c', 'alg'] as $key) { + Assertion::keyExists($attestation['attStmt'], $key, sprintf('The attestation statement value "%s" is missing.', $key)); + } + $certificates = $attestation['attStmt']['x5c']; + Assertion::isArray($certificates, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + Assertion::greaterThan(count($certificates), 0, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + Assertion::allString($certificates, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + $certificates = CertificateToolbox::convertAllDERToPEM($certificates); + + return AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], new CertificateTrustPath($certificates)); + } + + public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + $trustPath = $attestationStatement->getTrustPath(); + Assertion::isInstanceOf($trustPath, CertificateTrustPath::class, 'Invalid trust path'); + + $certificates = $trustPath->getCertificates(); + + //Decode leaf attestation certificate + $leaf = $certificates[0]; + $this->checkCertificateAndGetPublicKey($leaf, $clientDataJSONHash, $authenticatorData); + + $signedData = $authenticatorData->getAuthData().$clientDataJSONHash; + $alg = $attestationStatement->get('alg'); + + return 1 === openssl_verify($signedData, $attestationStatement->get('sig'), $leaf, Algorithms::getOpensslAlgorithmFor((int) $alg)); + } + + private function checkCertificateAndGetPublicKey(string $certificate, string $clientDataHash, AuthenticatorData $authenticatorData): void + { + $resource = openssl_pkey_get_public($certificate); + $details = openssl_pkey_get_details($resource); + Assertion::isArray($details, 'Unable to read the certificate'); + + //Check that authData publicKey matches the public key in the attestation certificate + $attestedCredentialData = $authenticatorData->getAttestedCredentialData(); + Assertion::notNull($attestedCredentialData, 'No attested credential data found'); + $publicKeyData = $attestedCredentialData->getCredentialPublicKey(); + Assertion::notNull($publicKeyData, 'No attested public key found'); + $publicDataStream = new StringStream($publicKeyData); + $coseKey = $this->decoder->decode($publicDataStream)->getNormalizedData(false); + Assertion::true($publicDataStream->isEOF(), 'Invalid public key data. Presence of extra bytes.'); + $publicDataStream->close(); + $publicKey = Key::createFromData($coseKey); + + Assertion::true(($publicKey instanceof Ec2Key) || ($publicKey instanceof RsaKey), 'Unsupported key type'); + Assertion::eq($publicKey->asPEM(), $details['key'], 'Invalid key'); + + /*---------------------------*/ + $certDetails = openssl_x509_parse($certificate); + + //Find Android KeyStore Extension with OID “1.3.6.1.4.1.11129.2.1.17” in certificate extensions + Assertion::isArray($certDetails, 'The certificate is not valid'); + Assertion::keyExists($certDetails, 'extensions', 'The certificate has no extension'); + Assertion::isArray($certDetails['extensions'], 'The certificate has no extension'); + Assertion::keyExists($certDetails['extensions'], '1.3.6.1.4.1.11129.2.1.17', 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is missing'); + $extension = $certDetails['extensions']['1.3.6.1.4.1.11129.2.1.17']; + $extensionAsAsn1 = ASNObject::fromBinary($extension); + Assertion::isInstanceOf($extensionAsAsn1, Sequence::class, 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); + $objects = $extensionAsAsn1->getChildren(); + + //Check that attestationChallenge is set to the clientDataHash. + Assertion::keyExists($objects, 4, 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); + Assertion::isInstanceOf($objects[4], OctetString::class, 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); + Assertion::eq($clientDataHash, hex2bin(($objects[4])->getContent()), 'The client data hash is not valid'); + + //Check that both teeEnforced and softwareEnforced structures don’t contain allApplications(600) tag. + Assertion::keyExists($objects, 6, 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); + $softwareEnforcedFlags = $objects[6]; + Assertion::isInstanceOf($softwareEnforcedFlags, Sequence::class, 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); + $this->checkAbsenceOfAllApplicationsTag($softwareEnforcedFlags); + + Assertion::keyExists($objects, 7, 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); + $teeEnforcedFlags = $objects[6]; + Assertion::isInstanceOf($teeEnforcedFlags, Sequence::class, 'The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); + $this->checkAbsenceOfAllApplicationsTag($teeEnforcedFlags); + } + + private function checkAbsenceOfAllApplicationsTag(Sequence $sequence): void + { + foreach ($sequence->getChildren() as $tag) { + Assertion::isInstanceOf($tag, ExplicitlyTaggedObject::class, 'Invalid tag'); + /* @var ExplicitlyTaggedObject $tag */ + Assertion::notEq(600, (int) $tag->getTag(), 'Forbidden tag 600 found'); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php new file mode 100644 index 00000000..29286ba7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php @@ -0,0 +1,292 @@ +jwsSerializer = new CompactSerializer(); + $this->initJwsVerifier(); + + //To be removed in 4.0 + $this->leeway = $leeway ?? 0; + $this->maxAge = $maxAge ?? 60000; + $this->apiKey = $apiKey; + $this->client = $client; + $this->requestFactory = $requestFactory; + } + + public function enableApiVerification(ClientInterface $client, string $apiKey, RequestFactoryInterface $requestFactory): self + { + $this->apiKey = $apiKey; + $this->client = $client; + $this->requestFactory = $requestFactory; + + return $this; + } + + public function setMaxAge(int $maxAge): self + { + $this->maxAge = $maxAge; + + return $this; + } + + public function setLeeway(int $leeway): self + { + $this->leeway = $leeway; + + return $this; + } + + public function name(): string + { + return 'android-safetynet'; + } + + /** + * @param mixed[] $attestation + */ + public function load(array $attestation): AttestationStatement + { + Assertion::keyExists($attestation, 'attStmt', 'Invalid attestation object'); + foreach (['ver', 'response'] as $key) { + Assertion::keyExists($attestation['attStmt'], $key, sprintf('The attestation statement value "%s" is missing.', $key)); + Assertion::notEmpty($attestation['attStmt'][$key], sprintf('The attestation statement value "%s" is empty.', $key)); + } + $jws = $this->jwsSerializer->unserialize($attestation['attStmt']['response']); + $jwsHeader = $jws->getSignature(0)->getProtectedHeader(); + Assertion::keyExists($jwsHeader, 'x5c', 'The response in the attestation statement must contain a "x5c" header.'); + Assertion::notEmpty($jwsHeader['x5c'], 'The "x5c" parameter in the attestation statement response must contain at least one certificate.'); + $certificates = $this->convertCertificatesToPem($jwsHeader['x5c']); + $attestation['attStmt']['jws'] = $jws; + + return AttestationStatement::createBasic( + $this->name(), + $attestation['attStmt'], + new CertificateTrustPath($certificates) + ); + } + + public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + $trustPath = $attestationStatement->getTrustPath(); + Assertion::isInstanceOf($trustPath, CertificateTrustPath::class, 'Invalid trust path'); + $certificates = $trustPath->getCertificates(); + $firstCertificate = current($certificates); + Assertion::string($firstCertificate, 'No certificate'); + + $parsedCertificate = openssl_x509_parse($firstCertificate); + Assertion::isArray($parsedCertificate, 'Invalid attestation object'); + Assertion::keyExists($parsedCertificate, 'subject', 'Invalid attestation object'); + Assertion::keyExists($parsedCertificate['subject'], 'CN', 'Invalid attestation object'); + Assertion::eq($parsedCertificate['subject']['CN'], 'attest.android.com', 'Invalid attestation object'); + + /** @var JWS $jws */ + $jws = $attestationStatement->get('jws'); + $payload = $jws->getPayload(); + $this->validatePayload($payload, $clientDataJSONHash, $authenticatorData); + + //Check the signature + $this->validateSignature($jws, $trustPath); + + //Check against Google service + $this->validateUsingGoogleApi($attestationStatement); + + return true; + } + + private function validatePayload(?string $payload, string $clientDataJSONHash, AuthenticatorData $authenticatorData): void + { + Assertion::notNull($payload, 'Invalid attestation object'); + $payload = JsonConverter::decode($payload); + Assertion::isArray($payload, 'Invalid attestation object'); + Assertion::keyExists($payload, 'nonce', 'Invalid attestation object. "nonce" is missing.'); + Assertion::eq($payload['nonce'], base64_encode(hash('sha256', $authenticatorData->getAuthData().$clientDataJSONHash, true)), 'Invalid attestation object. Invalid nonce'); + Assertion::keyExists($payload, 'ctsProfileMatch', 'Invalid attestation object. "ctsProfileMatch" is missing.'); + Assertion::true($payload['ctsProfileMatch'], 'Invalid attestation object. "ctsProfileMatch" value is false.'); + Assertion::keyExists($payload, 'timestampMs', 'Invalid attestation object. Timestamp is missing.'); + Assertion::integer($payload['timestampMs'], 'Invalid attestation object. Timestamp shall be an integer.'); + $currentTime = time() * 1000; + Assertion::lessOrEqualThan($payload['timestampMs'], $currentTime + $this->leeway, sprintf('Invalid attestation object. Issued in the future. Current time: %d. Response time: %d', $currentTime, $payload['timestampMs'])); + Assertion::lessOrEqualThan($currentTime - $payload['timestampMs'], $this->maxAge, sprintf('Invalid attestation object. Too old. Current time: %d. Response time: %d', $currentTime, $payload['timestampMs'])); + } + + private function validateSignature(JWS $jws, CertificateTrustPath $trustPath): void + { + $jwk = JWKFactory::createFromCertificate($trustPath->getCertificates()[0]); + $isValid = $this->jwsVerifier->verifyWithKey($jws, $jwk, 0); + Assertion::true($isValid, 'Invalid response signature'); + } + + private function validateUsingGoogleApi(AttestationStatement $attestationStatement): void + { + if (null === $this->client || null === $this->apiKey || null === $this->requestFactory) { + return; + } + $uri = sprintf('https://www.googleapis.com/androidcheck/v1/attestations/verify?key=%s', urlencode($this->apiKey)); + $requestBody = sprintf('{"signedAttestation":"%s"}', $attestationStatement->get('response')); + $request = $this->requestFactory->createRequest('POST', $uri); + $request = $request->withHeader('content-type', 'application/json'); + $request->getBody()->write($requestBody); + + $response = $this->client->sendRequest($request); + $this->checkGoogleApiResponse($response); + $responseBody = $this->getResponseBody($response); + $responseBodyJson = json_decode($responseBody, true); + Assertion::keyExists($responseBodyJson, 'isValidSignature', 'Invalid response.'); + Assertion::boolean($responseBodyJson['isValidSignature'], 'Invalid response.'); + Assertion::true($responseBodyJson['isValidSignature'], 'Invalid response.'); + } + + private function getResponseBody(ResponseInterface $response): string + { + $responseBody = ''; + $response->getBody()->rewind(); + while (true) { + $tmp = $response->getBody()->read(1024); + if ('' === $tmp) { + break; + } + $responseBody .= $tmp; + } + + return $responseBody; + } + + private function checkGoogleApiResponse(ResponseInterface $response): void + { + Assertion::eq(200, $response->getStatusCode(), 'Request did not succeeded'); + Assertion::true($response->hasHeader('content-type'), 'Unrecognized response'); + + foreach ($response->getHeader('content-type') as $header) { + if (0 === mb_strpos($header, 'application/json')) { + return; + } + } + + throw new InvalidArgumentException('Unrecognized response'); + } + + /** + * @param string[] $certificates + * + * @return string[] + */ + private function convertCertificatesToPem(array $certificates): array + { + foreach ($certificates as $k => $v) { + $certificates[$k] = CertificateToolbox::fixPEMStructure($v); + } + + return $certificates; + } + + private function initJwsVerifier(): void + { + $algorithmClasses = [ + Algorithm\RS256::class, Algorithm\RS384::class, Algorithm\RS512::class, + Algorithm\PS256::class, Algorithm\PS384::class, Algorithm\PS512::class, + Algorithm\ES256::class, Algorithm\ES384::class, Algorithm\ES512::class, + Algorithm\EdDSA::class, + ]; + /* @var AlgorithmInterface[] $algorithms */ + $algorithms = []; + foreach ($algorithmClasses as $algorithm) { + if (class_exists($algorithm)) { + /* @var AlgorithmInterface $algorithm */ + $algorithms[] = new $algorithm(); + } + } + $algorithmManager = new AlgorithmManager($algorithms); + $this->jwsVerifier = new JWSVerifier($algorithmManager); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php new file mode 100644 index 00000000..53ee6480 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php @@ -0,0 +1,119 @@ +decoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + } + + public function name(): string + { + return 'apple'; + } + + /** + * @param mixed[] $attestation + */ + public function load(array $attestation): AttestationStatement + { + Assertion::keyExists($attestation, 'attStmt', 'Invalid attestation object'); + foreach (['x5c'] as $key) { + Assertion::keyExists($attestation['attStmt'], $key, sprintf('The attestation statement value "%s" is missing.', $key)); + } + $certificates = $attestation['attStmt']['x5c']; + Assertion::isArray($certificates, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + Assertion::greaterThan(count($certificates), 0, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + Assertion::allString($certificates, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + $certificates = CertificateToolbox::convertAllDERToPEM($certificates); + + return AttestationStatement::createAnonymizationCA($attestation['fmt'], $attestation['attStmt'], new CertificateTrustPath($certificates)); + } + + public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + $trustPath = $attestationStatement->getTrustPath(); + Assertion::isInstanceOf($trustPath, CertificateTrustPath::class, 'Invalid trust path'); + + $certificates = $trustPath->getCertificates(); + + //Decode leaf attestation certificate + $leaf = $certificates[0]; + + $this->checkCertificateAndGetPublicKey($leaf, $clientDataJSONHash, $authenticatorData); + + return true; + } + + private function checkCertificateAndGetPublicKey(string $certificate, string $clientDataHash, AuthenticatorData $authenticatorData): void + { + $resource = openssl_pkey_get_public($certificate); + $details = openssl_pkey_get_details($resource); + Assertion::isArray($details, 'Unable to read the certificate'); + + //Check that authData publicKey matches the public key in the attestation certificate + $attestedCredentialData = $authenticatorData->getAttestedCredentialData(); + Assertion::notNull($attestedCredentialData, 'No attested credential data found'); + $publicKeyData = $attestedCredentialData->getCredentialPublicKey(); + Assertion::notNull($publicKeyData, 'No attested public key found'); + $publicDataStream = new StringStream($publicKeyData); + $coseKey = $this->decoder->decode($publicDataStream)->getNormalizedData(false); + Assertion::true($publicDataStream->isEOF(), 'Invalid public key data. Presence of extra bytes.'); + $publicDataStream->close(); + $publicKey = Key::createFromData($coseKey); + + Assertion::true(($publicKey instanceof Ec2Key) || ($publicKey instanceof RsaKey), 'Unsupported key type'); + + //We check the attested key corresponds to the key in the certificate + Assertion::eq($publicKey->asPEM(), $details['key'], 'Invalid key'); + + /*---------------------------*/ + $certDetails = openssl_x509_parse($certificate); + + //Find Apple Extension with OID “1.2.840.113635.100.8.2” in certificate extensions + Assertion::isArray($certDetails, 'The certificate is not valid'); + Assertion::keyExists($certDetails, 'extensions', 'The certificate has no extension'); + Assertion::isArray($certDetails['extensions'], 'The certificate has no extension'); + Assertion::keyExists($certDetails['extensions'], '1.2.840.113635.100.8.2', 'The certificate extension "1.2.840.113635.100.8.2" is missing'); + $extension = $certDetails['extensions']['1.2.840.113635.100.8.2']; + + $nonceToHash = $authenticatorData->getAuthData().$clientDataHash; + $nonce = hash('sha256', $nonceToHash); + + //'3024a1220420' corresponds to the Sequence+Explicitly Tagged Object + Octet Object + Assertion::eq('3024a1220420'.$nonce, bin2hex($extension), 'The client data hash is not valid'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php new file mode 100644 index 00000000..47d0bc93 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php @@ -0,0 +1,81 @@ +rawAttestationObject = $rawAttestationObject; + $this->attStmt = $attStmt; + $this->authData = $authData; + $this->metadataStatement = $metadataStatement; + } + + public function getRawAttestationObject(): string + { + return $this->rawAttestationObject; + } + + public function getAttStmt(): AttestationStatement + { + return $this->attStmt; + } + + public function setAttStmt(AttestationStatement $attStmt): void + { + $this->attStmt = $attStmt; + } + + public function getAuthData(): AuthenticatorData + { + return $this->authData; + } + + public function getMetadataStatement(): ?MetadataStatement + { + return $this->metadataStatement; + } + + public function setMetadataStatement(MetadataStatement $metadataStatement): self + { + $this->metadataStatement = $metadataStatement; + + return $this; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php new file mode 100644 index 00000000..f02e19e7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php @@ -0,0 +1,148 @@ +decoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + $this->attestationStatementSupportManager = $attestationStatementSupportManager; + $this->logger = $logger ?? new NullLogger(); + } + + public static function create(AttestationStatementSupportManager $attestationStatementSupportManager): self + { + return new self($attestationStatementSupportManager); + } + + public function load(string $data): AttestationObject + { + try { + $this->logger->info('Trying to load the data', ['data' => $data]); + $decodedData = Base64Url::decode($data); + $stream = new StringStream($decodedData); + $parsed = $this->decoder->decode($stream); + + $this->logger->info('Loading the Attestation Statement'); + $attestationObject = $parsed->getNormalizedData(); + Assertion::true($stream->isEOF(), 'Invalid attestation object. Presence of extra bytes.'); + $stream->close(); + Assertion::isArray($attestationObject, 'Invalid attestation object'); + Assertion::keyExists($attestationObject, 'authData', 'Invalid attestation object'); + Assertion::keyExists($attestationObject, 'fmt', 'Invalid attestation object'); + Assertion::keyExists($attestationObject, 'attStmt', 'Invalid attestation object'); + $authData = $attestationObject['authData']; + + $attestationStatementSupport = $this->attestationStatementSupportManager->get($attestationObject['fmt']); + $attestationStatement = $attestationStatementSupport->load($attestationObject); + $this->logger->info('Attestation Statement loaded'); + $this->logger->debug('Attestation Statement loaded', ['attestationStatement' => $attestationStatement]); + + $authDataStream = new StringStream($authData); + $rp_id_hash = $authDataStream->read(32); + $flags = $authDataStream->read(1); + $signCount = $authDataStream->read(4); + $signCount = unpack('N', $signCount)[1]; + $this->logger->debug(sprintf('Signature counter: %d', $signCount)); + + $attestedCredentialData = null; + if (0 !== (ord($flags) & self::FLAG_AT)) { + $this->logger->info('Attested Credential Data is present'); + $aaguid = Uuid::fromBytes($authDataStream->read(16)); + $credentialLength = $authDataStream->read(2); + $credentialLength = unpack('n', $credentialLength)[1]; + $credentialId = $authDataStream->read($credentialLength); + $credentialPublicKey = $this->decoder->decode($authDataStream); + Assertion::isInstanceOf($credentialPublicKey, MapObject::class, 'The data does not contain a valid credential public key.'); + $attestedCredentialData = new AttestedCredentialData($aaguid, $credentialId, (string) $credentialPublicKey); + $this->logger->info('Attested Credential Data loaded'); + $this->logger->debug('Attested Credential Data loaded', ['at' => $attestedCredentialData]); + } + + $extension = null; + if (0 !== (ord($flags) & self::FLAG_ED)) { + $this->logger->info('Extension Data loaded'); + $extension = $this->decoder->decode($authDataStream); + $extension = AuthenticationExtensionsClientOutputsLoader::load($extension); + $this->logger->info('Extension Data loaded'); + $this->logger->debug('Extension Data loaded', ['ed' => $extension]); + } + Assertion::true($authDataStream->isEOF(), 'Invalid authentication data. Presence of extra bytes.'); + $authDataStream->close(); + + $authenticatorData = new AuthenticatorData($authData, $rp_id_hash, $flags, $signCount, $attestedCredentialData, $extension); + $attestationObject = new AttestationObject($data, $attestationStatement, $authenticatorData); + $this->logger->info('Attestation Object loaded'); + $this->logger->debug('Attestation Object', ['ed' => $attestationObject]); + + return $attestationObject; + } catch (Throwable $throwable) { + $this->logger->error('An error occurred', [ + 'exception' => $throwable, + ]); + throw $throwable; + } + } + + public function setLogger(LoggerInterface $logger): self + { + $this->logger = $logger; + + return $this; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php new file mode 100644 index 00000000..1622f64b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php @@ -0,0 +1,175 @@ +fmt = $fmt; + $this->attStmt = $attStmt; + $this->type = $type; + $this->trustPath = $trustPath; + } + + /** + * @param mixed[] $attStmt + */ + public static function createNone(string $fmt, array $attStmt, TrustPath $trustPath): self + { + return new self($fmt, $attStmt, self::TYPE_NONE, $trustPath); + } + + /** + * @param mixed[] $attStmt + */ + public static function createBasic(string $fmt, array $attStmt, TrustPath $trustPath): self + { + return new self($fmt, $attStmt, self::TYPE_BASIC, $trustPath); + } + + /** + * @param mixed[] $attStmt + */ + public static function createSelf(string $fmt, array $attStmt, TrustPath $trustPath): self + { + return new self($fmt, $attStmt, self::TYPE_SELF, $trustPath); + } + + /** + * @param mixed[] $attStmt + */ + public static function createAttCA(string $fmt, array $attStmt, TrustPath $trustPath): self + { + return new self($fmt, $attStmt, self::TYPE_ATTCA, $trustPath); + } + + /** + * @param mixed[] $attStmt + */ + public static function createEcdaa(string $fmt, array $attStmt, TrustPath $trustPath): self + { + return new self($fmt, $attStmt, self::TYPE_ECDAA, $trustPath); + } + + public static function createAnonymizationCA(string $fmt, array $attStmt, TrustPath $trustPath): self + { + return new self($fmt, $attStmt, self::TYPE_ANONCA, $trustPath); + } + + public function getFmt(): string + { + return $this->fmt; + } + + /** + * @return mixed[] + */ + public function getAttStmt(): array + { + return $this->attStmt; + } + + public function has(string $key): bool + { + return array_key_exists($key, $this->attStmt); + } + + /** + * @return mixed + */ + public function get(string $key) + { + Assertion::true($this->has($key), sprintf('The attestation statement has no key "%s".', $key)); + + return $this->attStmt[$key]; + } + + public function getTrustPath(): TrustPath + { + return $this->trustPath; + } + + public function getType(): string + { + return $this->type; + } + + /** + * @param mixed[] $data + */ + public static function createFromArray(array $data): self + { + foreach (['fmt', 'attStmt', 'trustPath', 'type'] as $key) { + Assertion::keyExists($data, $key, sprintf('The key "%s" is missing', $key)); + } + + return new self( + $data['fmt'], + $data['attStmt'], + $data['type'], + TrustPathLoader::loadTrustPath($data['trustPath']) + ); + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + return [ + 'fmt' => $this->fmt, + 'attStmt' => $this->attStmt, + 'trustPath' => $this->trustPath->jsonSerialize(), + 'type' => $this->type, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php new file mode 100644 index 00000000..76f1dd43 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php @@ -0,0 +1,28 @@ +attestationStatementSupports[$attestationStatementSupport->name()] = $attestationStatementSupport; + } + + public function has(string $name): bool + { + return array_key_exists($name, $this->attestationStatementSupports); + } + + public function get(string $name): AttestationStatementSupport + { + Assertion::true($this->has($name), sprintf('The attestation statement format "%s" is not supported.', $name)); + + return $this->attestationStatementSupports[$name]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php new file mode 100644 index 00000000..7fe326d8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php @@ -0,0 +1,118 @@ +decoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + } + + public function name(): string + { + return 'fido-u2f'; + } + + /** + * @param mixed[] $attestation + */ + public function load(array $attestation): AttestationStatement + { + Assertion::keyExists($attestation, 'attStmt', 'Invalid attestation object'); + foreach (['sig', 'x5c'] as $key) { + Assertion::keyExists($attestation['attStmt'], $key, sprintf('The attestation statement value "%s" is missing.', $key)); + } + $certificates = $attestation['attStmt']['x5c']; + Assertion::isArray($certificates, 'The attestation statement value "x5c" must be a list with one certificate.'); + Assertion::count($certificates, 1, 'The attestation statement value "x5c" must be a list with one certificate.'); + Assertion::allString($certificates, 'The attestation statement value "x5c" must be a list with one certificate.'); + + reset($certificates); + $certificates = CertificateToolbox::convertAllDERToPEM($certificates); + $this->checkCertificate($certificates[0]); + + return AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], new CertificateTrustPath($certificates)); + } + + public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + Assertion::eq( + $authenticatorData->getAttestedCredentialData()->getAaguid()->toString(), + '00000000-0000-0000-0000-000000000000', + 'Invalid AAGUID for fido-u2f attestation statement. Shall be "00000000-0000-0000-0000-000000000000"' + ); + $trustPath = $attestationStatement->getTrustPath(); + Assertion::isInstanceOf($trustPath, CertificateTrustPath::class, 'Invalid trust path'); + $dataToVerify = "\0"; + $dataToVerify .= $authenticatorData->getRpIdHash(); + $dataToVerify .= $clientDataJSONHash; + $dataToVerify .= $authenticatorData->getAttestedCredentialData()->getCredentialId(); + $dataToVerify .= $this->extractPublicKey($authenticatorData->getAttestedCredentialData()->getCredentialPublicKey()); + + return 1 === openssl_verify($dataToVerify, $attestationStatement->get('sig'), $trustPath->getCertificates()[0], OPENSSL_ALGO_SHA256); + } + + private function extractPublicKey(?string $publicKey): string + { + Assertion::notNull($publicKey, 'The attested credential data does not contain a valid public key.'); + + $publicKeyStream = new StringStream($publicKey); + $coseKey = $this->decoder->decode($publicKeyStream); + Assertion::true($publicKeyStream->isEOF(), 'Invalid public key. Presence of extra bytes.'); + $publicKeyStream->close(); + Assertion::isInstanceOf($coseKey, MapObject::class, 'The attested credential data does not contain a valid public key.'); + + $coseKey = $coseKey->getNormalizedData(); + $ec2Key = new Ec2Key($coseKey + [Ec2Key::TYPE => 2, Ec2Key::DATA_CURVE => Ec2Key::CURVE_P256]); + + return "\x04".$ec2Key->x().$ec2Key->y(); + } + + private function checkCertificate(string $publicKey): void + { + try { + $resource = openssl_pkey_get_public($publicKey); + $details = openssl_pkey_get_details($resource); + } catch (Throwable $throwable) { + throw new InvalidArgumentException('Invalid certificate or certificate chain', 0, $throwable); + } + Assertion::isArray($details, 'Invalid certificate or certificate chain'); + Assertion::keyExists($details, 'ec', 'Invalid certificate or certificate chain'); + Assertion::keyExists($details['ec'], 'curve_name', 'Invalid certificate or certificate chain'); + Assertion::eq($details['ec']['curve_name'], 'prime256v1', 'Invalid certificate or certificate chain'); + Assertion::keyExists($details['ec'], 'curve_oid', 'Invalid certificate or certificate chain'); + Assertion::eq($details['ec']['curve_oid'], '1.2.840.10045.3.1.7', 'Invalid certificate or certificate chain'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php new file mode 100644 index 00000000..8719ae7d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php @@ -0,0 +1,42 @@ +getAttStmt()); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php new file mode 100644 index 00000000..58fb6370 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php @@ -0,0 +1,194 @@ +decoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + $this->algorithmManager = $algorithmManager; + } + + public function name(): string + { + return 'packed'; + } + + /** + * @param mixed[] $attestation + */ + public function load(array $attestation): AttestationStatement + { + Assertion::keyExists($attestation['attStmt'], 'sig', 'The attestation statement value "sig" is missing.'); + Assertion::keyExists($attestation['attStmt'], 'alg', 'The attestation statement value "alg" is missing.'); + Assertion::string($attestation['attStmt']['sig'], 'The attestation statement value "sig" is missing.'); + switch (true) { + case array_key_exists('x5c', $attestation['attStmt']): + return $this->loadBasicType($attestation); + case array_key_exists('ecdaaKeyId', $attestation['attStmt']): + return $this->loadEcdaaType($attestation['attStmt']); + default: + return $this->loadEmptyType($attestation); + } + } + + public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + $trustPath = $attestationStatement->getTrustPath(); + switch (true) { + case $trustPath instanceof CertificateTrustPath: + return $this->processWithCertificate($clientDataJSONHash, $attestationStatement, $authenticatorData, $trustPath); + case $trustPath instanceof EcdaaKeyIdTrustPath: + return $this->processWithECDAA(); + case $trustPath instanceof EmptyTrustPath: + return $this->processWithSelfAttestation($clientDataJSONHash, $attestationStatement, $authenticatorData); + default: + throw new InvalidArgumentException('Unsupported attestation statement'); + } + } + + /** + * @param mixed[] $attestation + */ + private function loadBasicType(array $attestation): AttestationStatement + { + $certificates = $attestation['attStmt']['x5c']; + Assertion::isArray($certificates, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + Assertion::minCount($certificates, 1, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + $certificates = CertificateToolbox::convertAllDERToPEM($certificates); + + return AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], new CertificateTrustPath($certificates)); + } + + private function loadEcdaaType(array $attestation): AttestationStatement + { + $ecdaaKeyId = $attestation['attStmt']['ecdaaKeyId']; + Assertion::string($ecdaaKeyId, 'The attestation statement value "ecdaaKeyId" is invalid.'); + + return AttestationStatement::createEcdaa($attestation['fmt'], $attestation['attStmt'], new EcdaaKeyIdTrustPath($attestation['ecdaaKeyId'])); + } + + /** + * @param mixed[] $attestation + */ + private function loadEmptyType(array $attestation): AttestationStatement + { + return AttestationStatement::createSelf($attestation['fmt'], $attestation['attStmt'], new EmptyTrustPath()); + } + + private function checkCertificate(string $attestnCert, AuthenticatorData $authenticatorData): void + { + $parsed = openssl_x509_parse($attestnCert); + Assertion::isArray($parsed, 'Invalid certificate'); + + //Check version + Assertion::false(!isset($parsed['version']) || 2 !== $parsed['version'], 'Invalid certificate version'); + + //Check subject field + Assertion::false(!isset($parsed['name']) || false === mb_strpos($parsed['name'], '/OU=Authenticator Attestation'), 'Invalid certificate name. The Subject Organization Unit must be "Authenticator Attestation"'); + + //Check extensions + Assertion::false(!isset($parsed['extensions']) || !is_array($parsed['extensions']), 'Certificate extensions are missing'); + + //Check certificate is not a CA cert + Assertion::false(!isset($parsed['extensions']['basicConstraints']) || 'CA:FALSE' !== $parsed['extensions']['basicConstraints'], 'The Basic Constraints extension must have the CA component set to false'); + + $attestedCredentialData = $authenticatorData->getAttestedCredentialData(); + Assertion::notNull($attestedCredentialData, 'No attested credential available'); + + // id-fido-gen-ce-aaguid OID check + Assertion::false(in_array('1.3.6.1.4.1.45724.1.1.4', $parsed['extensions'], true) && !hash_equals($attestedCredentialData->getAaguid()->getBytes(), $parsed['extensions']['1.3.6.1.4.1.45724.1.1.4']), 'The value of the "aaguid" does not match with the certificate'); + } + + private function processWithCertificate(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData, CertificateTrustPath $trustPath): bool + { + $certificates = $trustPath->getCertificates(); + + // Check leaf certificate + $this->checkCertificate($certificates[0], $authenticatorData); + + // Get the COSE algorithm identifier and the corresponding OpenSSL one + $coseAlgorithmIdentifier = (int) $attestationStatement->get('alg'); + $opensslAlgorithmIdentifier = Algorithms::getOpensslAlgorithmFor($coseAlgorithmIdentifier); + + // Verification of the signature + $signedData = $authenticatorData->getAuthData().$clientDataJSONHash; + $result = openssl_verify($signedData, $attestationStatement->get('sig'), $certificates[0], $opensslAlgorithmIdentifier); + + return 1 === $result; + } + + private function processWithECDAA(): bool + { + throw new RuntimeException('ECDAA not supported'); + } + + private function processWithSelfAttestation(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + $attestedCredentialData = $authenticatorData->getAttestedCredentialData(); + Assertion::notNull($attestedCredentialData, 'No attested credential available'); + $credentialPublicKey = $attestedCredentialData->getCredentialPublicKey(); + Assertion::notNull($credentialPublicKey, 'No credential public key available'); + $publicKeyStream = new StringStream($credentialPublicKey); + $publicKey = $this->decoder->decode($publicKeyStream); + Assertion::true($publicKeyStream->isEOF(), 'Invalid public key. Presence of extra bytes.'); + $publicKeyStream->close(); + Assertion::isInstanceOf($publicKey, MapObject::class, 'The attested credential data does not contain a valid public key.'); + $publicKey = $publicKey->getNormalizedData(false); + $publicKey = new Key($publicKey); + Assertion::eq($publicKey->alg(), (int) $attestationStatement->get('alg'), 'The algorithm of the attestation statement and the key are not identical.'); + + $dataToVerify = $authenticatorData->getAuthData().$clientDataJSONHash; + $algorithm = $this->algorithmManager->get((int) $attestationStatement->get('alg')); + if (!$algorithm instanceof Signature) { + throw new RuntimeException('Invalid algorithm'); + } + $signature = CoseSignatureFixer::fix($attestationStatement->get('sig'), $algorithm); + + return $algorithm->verify($dataToVerify, $publicKey, $signature); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php new file mode 100644 index 00000000..b43effb4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php @@ -0,0 +1,309 @@ +checkCertInfo($attestation['attStmt']['certInfo']); + Assertion::eq('8017', bin2hex($certInfo['type']), 'Invalid attestation object'); + + $pubArea = $this->checkPubArea($attestation['attStmt']['pubArea']); + $pubAreaAttestedNameAlg = mb_substr($certInfo['attestedName'], 0, 2, '8bit'); + $pubAreaHash = hash($this->getTPMHash($pubAreaAttestedNameAlg), $attestation['attStmt']['pubArea'], true); + $attestedName = $pubAreaAttestedNameAlg.$pubAreaHash; + Assertion::eq($attestedName, $certInfo['attestedName'], 'Invalid attested name'); + + $attestation['attStmt']['parsedCertInfo'] = $certInfo; + $attestation['attStmt']['parsedPubArea'] = $pubArea; + + $certificates = CertificateToolbox::convertAllDERToPEM($attestation['attStmt']['x5c']); + Assertion::minCount($certificates, 1, 'The attestation statement value "x5c" must be a list with at least one certificate.'); + + return AttestationStatement::createAttCA( + $this->name(), + $attestation['attStmt'], + new CertificateTrustPath($certificates) + ); + } + + public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + $attToBeSigned = $authenticatorData->getAuthData().$clientDataJSONHash; + $attToBeSignedHash = hash(Algorithms::getHashAlgorithmFor((int) $attestationStatement->get('alg')), $attToBeSigned, true); + Assertion::eq($attestationStatement->get('parsedCertInfo')['extraData'], $attToBeSignedHash, 'Invalid attestation hash'); + $this->checkUniquePublicKey( + $attestationStatement->get('parsedPubArea')['unique'], + $authenticatorData->getAttestedCredentialData()->getCredentialPublicKey() + ); + + switch (true) { + case $attestationStatement->getTrustPath() instanceof CertificateTrustPath: + return $this->processWithCertificate($clientDataJSONHash, $attestationStatement, $authenticatorData); + case $attestationStatement->getTrustPath() instanceof EcdaaKeyIdTrustPath: + return $this->processWithECDAA(); + default: + throw new InvalidArgumentException('Unsupported attestation statement'); + } + } + + private function checkUniquePublicKey(string $unique, string $cborPublicKey): void + { + $cborDecoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + $publicKey = $cborDecoder->decode(new StringStream($cborPublicKey)); + Assertion::isInstanceOf($publicKey, MapObject::class, 'Invalid public key'); + $key = new Key($publicKey->getNormalizedData(false)); + + switch ($key->type()) { + case Key::TYPE_OKP: + $uniqueFromKey = (new OkpKey($key->getData()))->x(); + break; + case Key::TYPE_EC2: + $ec2Key = new Ec2Key($key->getData()); + $uniqueFromKey = "\x04".$ec2Key->x().$ec2Key->y(); + break; + case Key::TYPE_RSA: + $uniqueFromKey = (new RsaKey($key->getData()))->n(); + break; + default: + throw new InvalidArgumentException('Invalid or unsupported key type.'); + } + + Assertion::eq($unique, $uniqueFromKey, 'Invalid pubArea.unique value'); + } + + /** + * @return mixed[] + */ + private function checkCertInfo(string $data): array + { + $certInfo = new StringStream($data); + + $magic = $certInfo->read(4); + Assertion::eq('ff544347', bin2hex($magic), 'Invalid attestation object'); + + $type = $certInfo->read(2); + + $qualifiedSignerLength = unpack('n', $certInfo->read(2))[1]; + $qualifiedSigner = $certInfo->read($qualifiedSignerLength); //Ignored + + $extraDataLength = unpack('n', $certInfo->read(2))[1]; + $extraData = $certInfo->read($extraDataLength); + + $clockInfo = $certInfo->read(17); //Ignore + + $firmwareVersion = $certInfo->read(8); + + $attestedNameLength = unpack('n', $certInfo->read(2))[1]; + $attestedName = $certInfo->read($attestedNameLength); + + $attestedQualifiedNameLength = unpack('n', $certInfo->read(2))[1]; + $attestedQualifiedName = $certInfo->read($attestedQualifiedNameLength); //Ignore + Assertion::true($certInfo->isEOF(), 'Invalid certificate information. Presence of extra bytes.'); + $certInfo->close(); + + return [ + 'magic' => $magic, + 'type' => $type, + 'qualifiedSigner' => $qualifiedSigner, + 'extraData' => $extraData, + 'clockInfo' => $clockInfo, + 'firmwareVersion' => $firmwareVersion, + 'attestedName' => $attestedName, + 'attestedQualifiedName' => $attestedQualifiedName, + ]; + } + + /** + * @return mixed[] + */ + private function checkPubArea(string $data): array + { + $pubArea = new StringStream($data); + + $type = $pubArea->read(2); + + $nameAlg = $pubArea->read(2); + + $objectAttributes = $pubArea->read(4); + + $authPolicyLength = unpack('n', $pubArea->read(2))[1]; + $authPolicy = $pubArea->read($authPolicyLength); + + $parameters = $this->getParameters($type, $pubArea); + + $uniqueLength = unpack('n', $pubArea->read(2))[1]; + $unique = $pubArea->read($uniqueLength); + Assertion::true($pubArea->isEOF(), 'Invalid public area. Presence of extra bytes.'); + $pubArea->close(); + + return [ + 'type' => $type, + 'nameAlg' => $nameAlg, + 'objectAttributes' => $objectAttributes, + 'authPolicy' => $authPolicy, + 'parameters' => $parameters, + 'unique' => $unique, + ]; + } + + /** + * @return mixed[] + */ + private function getParameters(string $type, StringStream $stream): array + { + switch (bin2hex($type)) { + case '0001': + case '0014': + case '0016': + return [ + 'symmetric' => $stream->read(2), + 'scheme' => $stream->read(2), + 'keyBits' => unpack('n', $stream->read(2))[1], + 'exponent' => $this->getExponent($stream->read(4)), + ]; + case '0018': + return [ + 'symmetric' => $stream->read(2), + 'scheme' => $stream->read(2), + 'curveId' => $stream->read(2), + 'kdf' => $stream->read(2), + ]; + default: + throw new InvalidArgumentException('Unsupported type'); + } + } + + private function getExponent(string $exponent): string + { + return '00000000' === bin2hex($exponent) ? Base64Url::decode('AQAB') : $exponent; + } + + private function getTPMHash(string $nameAlg): string + { + switch (bin2hex($nameAlg)) { + case '0004': + return 'sha1'; //: "TPM_ALG_SHA1", + case '000b': + return 'sha256'; //: "TPM_ALG_SHA256", + case '000c': + return 'sha384'; //: "TPM_ALG_SHA384", + case '000d': + return 'sha512'; //: "TPM_ALG_SHA512", + default: + throw new InvalidArgumentException('Unsupported hash algorithm'); + } + } + + private function processWithCertificate(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool + { + $trustPath = $attestationStatement->getTrustPath(); + Assertion::isInstanceOf($trustPath, CertificateTrustPath::class, 'Invalid trust path'); + + $certificates = $trustPath->getCertificates(); + + // Check certificate CA chain and returns the Attestation Certificate + $this->checkCertificate($certificates[0], $authenticatorData); + + // Get the COSE algorithm identifier and the corresponding OpenSSL one + $coseAlgorithmIdentifier = (int) $attestationStatement->get('alg'); + $opensslAlgorithmIdentifier = Algorithms::getOpensslAlgorithmFor($coseAlgorithmIdentifier); + + $result = openssl_verify($attestationStatement->get('certInfo'), $attestationStatement->get('sig'), $certificates[0], $opensslAlgorithmIdentifier); + + return 1 === $result; + } + + private function checkCertificate(string $attestnCert, AuthenticatorData $authenticatorData): void + { + $parsed = openssl_x509_parse($attestnCert); + Assertion::isArray($parsed, 'Invalid certificate'); + + //Check version + Assertion::false(!isset($parsed['version']) || 2 !== $parsed['version'], 'Invalid certificate version'); + + //Check subject field is empty + Assertion::false(!isset($parsed['subject']) || !is_array($parsed['subject']) || 0 !== count($parsed['subject']), 'Invalid certificate name. The Subject should be empty'); + + // Check period of validity + Assertion::keyExists($parsed, 'validFrom_time_t', 'Invalid certificate start date.'); + Assertion::integer($parsed['validFrom_time_t'], 'Invalid certificate start date.'); + $startDate = (new DateTimeImmutable())->setTimestamp($parsed['validFrom_time_t']); + Assertion::true($startDate < new DateTimeImmutable(), 'Invalid certificate start date.'); + + Assertion::keyExists($parsed, 'validTo_time_t', 'Invalid certificate end date.'); + Assertion::integer($parsed['validTo_time_t'], 'Invalid certificate end date.'); + $endDate = (new DateTimeImmutable())->setTimestamp($parsed['validTo_time_t']); + Assertion::true($endDate > new DateTimeImmutable(), 'Invalid certificate end date.'); + + //Check extensions + Assertion::false(!isset($parsed['extensions']) || !is_array($parsed['extensions']), 'Certificate extensions are missing'); + + //Check subjectAltName + Assertion::false(!isset($parsed['extensions']['subjectAltName']), 'The "subjectAltName" is missing'); + + //Check extendedKeyUsage + Assertion::false(!isset($parsed['extensions']['extendedKeyUsage']), 'The "subjectAltName" is missing'); + Assertion::eq($parsed['extensions']['extendedKeyUsage'], '2.23.133.8.3', 'The "extendedKeyUsage" is invalid'); + + // id-fido-gen-ce-aaguid OID check + Assertion::false(in_array('1.3.6.1.4.1.45724.1.1.4', $parsed['extensions'], true) && !hash_equals($authenticatorData->getAttestedCredentialData()->getAaguid()->getBytes(), $parsed['extensions']['1.3.6.1.4.1.45724.1.1.4']), 'The value of the "aaguid" does not match with the certificate'); + } + + private function processWithECDAA(): bool + { + throw new RuntimeException('ECDAA not supported'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestedCredentialData.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestedCredentialData.php new file mode 100644 index 00000000..329f2c6b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AttestedCredentialData.php @@ -0,0 +1,113 @@ +aaguid = $aaguid; + $this->credentialId = $credentialId; + $this->credentialPublicKey = $credentialPublicKey; + } + + public function getAaguid(): UuidInterface + { + return $this->aaguid; + } + + public function setAaguid(UuidInterface $aaguid): void + { + $this->aaguid = $aaguid; + } + + public function getCredentialId(): string + { + return $this->credentialId; + } + + public function getCredentialPublicKey(): ?string + { + return $this->credentialPublicKey; + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + Assertion::keyExists($json, 'aaguid', 'Invalid input. "aaguid" is missing.'); + Assertion::keyExists($json, 'credentialId', 'Invalid input. "credentialId" is missing.'); + switch (true) { + case 36 === mb_strlen($json['aaguid'], '8bit'): + $uuid = Uuid::fromString($json['aaguid']); + break; + default: // Kept for compatibility with old format + $decoded = base64_decode($json['aaguid'], true); + $uuid = Uuid::fromBytes($decoded); + } + $credentialId = base64_decode($json['credentialId'], true); + + $credentialPublicKey = null; + if (isset($json['credentialPublicKey'])) { + $credentialPublicKey = base64_decode($json['credentialPublicKey'], true); + } + + return new self( + $uuid, + $credentialId, + $credentialPublicKey + ); + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $result = [ + 'aaguid' => $this->aaguid->toString(), + 'credentialId' => base64_encode($this->credentialId), + ]; + if (null !== $this->credentialPublicKey) { + $result['credentialPublicKey'] = base64_encode($this->credentialPublicKey); + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php new file mode 100644 index 00000000..8a29b1c6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php @@ -0,0 +1,59 @@ +name = $name; + $this->value = $value; + } + + public function name(): string + { + return $this->name; + } + + /** + * @return mixed + */ + public function value() + { + return $this->value; + } + + /** + * @return mixed + */ + public function jsonSerialize() + { + return $this->value; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php new file mode 100644 index 00000000..2f171e7f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php @@ -0,0 +1,88 @@ +extensions[$extension->name()] = $extension; + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + $object = new self(); + foreach ($json as $k => $v) { + $object->add(new AuthenticationExtension($k, $v)); + } + + return $object; + } + + public function has(string $key): bool + { + return array_key_exists($key, $this->extensions); + } + + /** + * @return mixed + */ + public function get(string $key) + { + Assertion::true($this->has($key), sprintf('The extension with key "%s" is not available', $key)); + + return $this->extensions[$key]; + } + + /** + * @return AuthenticationExtension[] + */ + public function jsonSerialize(): array + { + return array_map(static function (AuthenticationExtension $object) { + return $object->jsonSerialize(); + }, $this->extensions); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->extensions); + } + + public function count(int $mode = COUNT_NORMAL): int + { + return count($this->extensions, $mode); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php new file mode 100644 index 00000000..d6ed0ffb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php @@ -0,0 +1,97 @@ +extensions[$extension->name()] = $extension; + } + + public static function createFromString(string $data): self + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + $object = new self(); + foreach ($json as $k => $v) { + $object->add(new AuthenticationExtension($k, $v)); + } + + return $object; + } + + public function has(string $key): bool + { + return array_key_exists($key, $this->extensions); + } + + /** + * @return mixed + */ + public function get(string $key) + { + Assertion::true($this->has($key), sprintf('The extension with key "%s" is not available', $key)); + + return $this->extensions[$key]; + } + + /** + * @return AuthenticationExtension[] + */ + public function jsonSerialize(): array + { + return array_map(static function (AuthenticationExtension $object) { + return $object->jsonSerialize(); + }, $this->extensions); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->extensions); + } + + public function count(int $mode = COUNT_NORMAL): int + { + return count($this->extensions, $mode); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php new file mode 100644 index 00000000..b4f69bf9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php @@ -0,0 +1,34 @@ +getNormalizedData(); + $extensions = new AuthenticationExtensionsClientOutputs(); + foreach ($data as $key => $value) { + Assertion::string($key, 'Invalid extension key'); + $extensions->add(new AuthenticationExtension($key, $value)); + } + + return $extensions; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php new file mode 100644 index 00000000..e53c88e5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php @@ -0,0 +1,22 @@ +checkers[] = $checker; + } + + /** + * @throws ExtensionOutputError + */ + public function check(AuthenticationExtensionsClientInputs $inputs, AuthenticationExtensionsClientOutputs $outputs): void + { + foreach ($this->checkers as $checker) { + $checker->check($inputs, $outputs); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php new file mode 100644 index 00000000..f16072f6 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php @@ -0,0 +1,36 @@ +authenticationExtension = $authenticationExtension; + } + + public function getAuthenticationExtension(): AuthenticationExtension + { + return $this->authenticationExtension; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php new file mode 100644 index 00000000..ec325e6e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php @@ -0,0 +1,64 @@ +authenticatorData = $authenticatorData; + $this->signature = $signature; + $this->userHandle = $userHandle; + } + + public function getAuthenticatorData(): AuthenticatorData + { + return $this->authenticatorData; + } + + public function getSignature(): string + { + return $this->signature; + } + + public function getUserHandle(): ?string + { + if (null === $this->userHandle || '' === $this->userHandle) { + return $this->userHandle; + } + + return base64_decode($this->userHandle, true); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php new file mode 100644 index 00000000..7550243a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php @@ -0,0 +1,272 @@ +publicKeyCredentialSourceRepository = $publicKeyCredentialSourceRepository; + $this->decoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + $this->tokenBindingHandler = $tokenBindingHandler; + $this->extensionOutputCheckerHandler = $extensionOutputCheckerHandler; + $this->algorithmManager = $algorithmManager; + $this->counterChecker = $counterChecker ?? new ThrowExceptionIfInvalid(); + $this->logger = $logger ?? new NullLogger(); + } + + /** + * @see https://www.w3.org/TR/webauthn/#verifying-assertion + */ + public function check(string $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface $request, ?string $userHandle, array $securedRelyingPartyId = []): PublicKeyCredentialSource + { + try { + $this->logger->info('Checking the authenticator assertion response', [ + 'credentialId' => $credentialId, + 'authenticatorAssertionResponse' => $authenticatorAssertionResponse, + 'publicKeyCredentialRequestOptions' => $publicKeyCredentialRequestOptions, + 'host' => $request->getUri()->getHost(), + 'userHandle' => $userHandle, + ]); + /** @see 7.2.1 */ + if (0 !== count($publicKeyCredentialRequestOptions->getAllowCredentials())) { + Assertion::true($this->isCredentialIdAllowed($credentialId, $publicKeyCredentialRequestOptions->getAllowCredentials()), 'The credential ID is not allowed.'); + } + + /** @see 7.2.2 */ + $publicKeyCredentialSource = $this->publicKeyCredentialSourceRepository->findOneByCredentialId($credentialId); + Assertion::notNull($publicKeyCredentialSource, 'The credential ID is invalid.'); + + /** @see 7.2.3 */ + $attestedCredentialData = $publicKeyCredentialSource->getAttestedCredentialData(); + $credentialUserHandle = $publicKeyCredentialSource->getUserHandle(); + $responseUserHandle = $authenticatorAssertionResponse->getUserHandle(); + + /** @see 7.2.2 User Handle*/ + if (null !== $userHandle) { //If the user was identified before the authentication ceremony was initiated, + Assertion::eq($credentialUserHandle, $userHandle, 'Invalid user handle'); + if (null !== $responseUserHandle && '' !== $responseUserHandle) { + Assertion::eq($credentialUserHandle, $responseUserHandle, 'Invalid user handle'); + } + } else { + Assertion::notEmpty($responseUserHandle, 'User handle is mandatory'); + Assertion::eq($credentialUserHandle, $responseUserHandle, 'Invalid user handle'); + } + + $credentialPublicKey = $attestedCredentialData->getCredentialPublicKey(); + $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey); + if ($isU2F) { + $credentialPublicKey = U2FPublicKey::createCOSEKey($credentialPublicKey); + } + Assertion::notNull($credentialPublicKey, 'No public key available.'); + $stream = new StringStream($credentialPublicKey); + $credentialPublicKeyStream = $this->decoder->decode($stream); + Assertion::true($stream->isEOF(), 'Invalid key. Presence of extra bytes.'); + $stream->close(); + + /** @see 7.2.4 */ + /** @see 7.2.5 */ + //Nothing to do. Use of objects directly + + /** @see 7.2.6 */ + $C = $authenticatorAssertionResponse->getClientDataJSON(); + + /** @see 7.2.7 */ + Assertion::eq('webauthn.get', $C->getType(), 'The client data type is not "webauthn.get".'); + + /** @see 7.2.8 */ + Assertion::true(hash_equals($publicKeyCredentialRequestOptions->getChallenge(), $C->getChallenge()), 'Invalid challenge.'); + + /** @see 7.2.9 */ + $rpId = $publicKeyCredentialRequestOptions->getRpId() ?? $request->getUri()->getHost(); + $facetId = $this->getFacetId($rpId, $publicKeyCredentialRequestOptions->getExtensions(), $authenticatorAssertionResponse->getAuthenticatorData()->getExtensions()); + $parsedRelyingPartyId = parse_url($C->getOrigin()); + Assertion::isArray($parsedRelyingPartyId, 'Invalid origin'); + if (!in_array($facetId, $securedRelyingPartyId, true)) { + $scheme = $parsedRelyingPartyId['scheme'] ?? ''; + Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); + } + $clientDataRpId = $parsedRelyingPartyId['host'] ?? ''; + Assertion::notEmpty($clientDataRpId, 'Invalid origin rpId.'); + $rpIdLength = mb_strlen($facetId); + Assertion::eq(mb_substr('.'.$clientDataRpId, -($rpIdLength + 1)), '.'.$facetId, 'rpId mismatch.'); + + /** @see 7.2.10 */ + if (null !== $C->getTokenBinding()) { + $this->tokenBindingHandler->check($C->getTokenBinding(), $request); + } + + $expectedRpIdHash = $isU2F ? $C->getOrigin() : $facetId; + // u2f response has full origin in rpIdHash + /** @see 7.2.11 */ + $rpIdHash = hash('sha256', $expectedRpIdHash, true); + Assertion::true(hash_equals($rpIdHash, $authenticatorAssertionResponse->getAuthenticatorData()->getRpIdHash()), 'rpId hash mismatch.'); + + /** @see 7.2.12 */ + Assertion::true($authenticatorAssertionResponse->getAuthenticatorData()->isUserPresent(), 'User was not present'); + /** @see 7.2.13 */ + if (AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED === $publicKeyCredentialRequestOptions->getUserVerification()) { + Assertion::true($authenticatorAssertionResponse->getAuthenticatorData()->isUserVerified(), 'User authentication required.'); + } + + /** @see 7.2.14 */ + $extensionsClientOutputs = $authenticatorAssertionResponse->getAuthenticatorData()->getExtensions(); + if (null !== $extensionsClientOutputs) { + $this->extensionOutputCheckerHandler->check( + $publicKeyCredentialRequestOptions->getExtensions(), + $extensionsClientOutputs + ); + } + + /** @see 7.2.15 */ + $getClientDataJSONHash = hash('sha256', $authenticatorAssertionResponse->getClientDataJSON()->getRawData(), true); + + /** @see 7.2.16 */ + $dataToVerify = $authenticatorAssertionResponse->getAuthenticatorData()->getAuthData().$getClientDataJSONHash; + $signature = $authenticatorAssertionResponse->getSignature(); + $coseKey = new Key($credentialPublicKeyStream->getNormalizedData()); + $algorithm = $this->algorithmManager->get($coseKey->alg()); + Assertion::isInstanceOf($algorithm, Signature::class, 'Invalid algorithm identifier. Should refer to a signature algorithm'); + $signature = CoseSignatureFixer::fix($signature, $algorithm); + Assertion::true($algorithm->verify($dataToVerify, $coseKey, $signature), 'Invalid signature.'); + + /** @see 7.2.17 */ + $storedCounter = $publicKeyCredentialSource->getCounter(); + $responseCounter = $authenticatorAssertionResponse->getAuthenticatorData()->getSignCount(); + if (0 !== $responseCounter || 0 !== $storedCounter) { + $this->counterChecker->check($publicKeyCredentialSource, $responseCounter); + } + $publicKeyCredentialSource->setCounter($responseCounter); + $this->publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource); + + /** @see 7.2.18 */ + //All good. We can continue. + $this->logger->info('The assertion is valid'); + $this->logger->debug('Public Key Credential Source', ['publicKeyCredentialSource' => $publicKeyCredentialSource]); + + return $publicKeyCredentialSource; + } catch (Throwable $throwable) { + $this->logger->error('An error occurred', [ + 'exception' => $throwable, + ]); + throw $throwable; + } + } + + public function setLogger(LoggerInterface $logger): self + { + $this->logger = $logger; + + return $this; + } + + public function setCounterChecker(CounterChecker $counterChecker): self + { + $this->counterChecker = $counterChecker; + + return $this; + } + + /** + * @param array $allowedCredentials + */ + private function isCredentialIdAllowed(string $credentialId, array $allowedCredentials): bool + { + foreach ($allowedCredentials as $allowedCredential) { + if (hash_equals($allowedCredential->getId(), $credentialId)) { + return true; + } + } + + return false; + } + + private function getFacetId(string $rpId, AuthenticationExtensionsClientInputs $authenticationExtensionsClientInputs, ?AuthenticationExtensionsClientOutputs $authenticationExtensionsClientOutputs): string + { + if (null === $authenticationExtensionsClientOutputs || !$authenticationExtensionsClientInputs->has('appid') || !$authenticationExtensionsClientOutputs->has('appid')) { + return $rpId; + } + $appId = $authenticationExtensionsClientInputs->get('appid')->value(); + $wasUsed = $authenticationExtensionsClientOutputs->get('appid')->value(); + if (!is_string($appId) || true !== $wasUsed) { + return $rpId; + } + + return $appId; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php new file mode 100644 index 00000000..7ac9e19f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php @@ -0,0 +1,38 @@ +attestationObject = $attestationObject; + } + + public function getAttestationObject(): AttestationObject + { + return $this->attestationObject; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php new file mode 100644 index 00000000..47fb4d28 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php @@ -0,0 +1,384 @@ +attestationStatementSupportManager = $attestationStatementSupportManager; + $this->publicKeyCredentialSource = $publicKeyCredentialSource; + $this->tokenBindingHandler = $tokenBindingHandler; + $this->extensionOutputCheckerHandler = $extensionOutputCheckerHandler; + $this->metadataStatementRepository = $metadataStatementRepository; + $this->logger = $logger ?? new NullLogger(); + } + + public function setLogger(LoggerInterface $logger): self + { + $this->logger = $logger; + + return $this; + } + + public function setCertificateChainChecker(CertificateChainChecker $certificateChainChecker): self + { + $this->certificateChainChecker = $certificateChainChecker; + + return $this; + } + + public function setMetadataStatementRepository(MetadataStatementRepository $metadataStatementRepository): self + { + $this->metadataStatementRepository = $metadataStatementRepository; + + return $this; + } + + /** + * @see https://www.w3.org/TR/webauthn/#registering-a-new-credential + */ + public function check(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface $request, array $securedRelyingPartyId = []): PublicKeyCredentialSource + { + try { + $this->logger->info('Checking the authenticator attestation response', [ + 'authenticatorAttestationResponse' => $authenticatorAttestationResponse, + 'publicKeyCredentialCreationOptions' => $publicKeyCredentialCreationOptions, + 'host' => $request->getUri()->getHost(), + ]); + /** @see 7.1.1 */ + //Nothing to do + + /** @see 7.1.2 */ + $C = $authenticatorAttestationResponse->getClientDataJSON(); + + /** @see 7.1.3 */ + Assertion::eq('webauthn.create', $C->getType(), 'The client data type is not "webauthn.create".'); + + /** @see 7.1.4 */ + Assertion::true(hash_equals($publicKeyCredentialCreationOptions->getChallenge(), $C->getChallenge()), 'Invalid challenge.'); + + /** @see 7.1.5 */ + $rpId = $publicKeyCredentialCreationOptions->getRp()->getId() ?? $request->getUri()->getHost(); + $facetId = $this->getFacetId($rpId, $publicKeyCredentialCreationOptions->getExtensions(), $authenticatorAttestationResponse->getAttestationObject()->getAuthData()->getExtensions()); + + $parsedRelyingPartyId = parse_url($C->getOrigin()); + Assertion::isArray($parsedRelyingPartyId, sprintf('The origin URI "%s" is not valid', $C->getOrigin())); + Assertion::keyExists($parsedRelyingPartyId, 'scheme', 'Invalid origin rpId.'); + $clientDataRpId = $parsedRelyingPartyId['host'] ?? ''; + Assertion::notEmpty($clientDataRpId, 'Invalid origin rpId.'); + $rpIdLength = mb_strlen($facetId); + Assertion::eq(mb_substr('.'.$clientDataRpId, -($rpIdLength + 1)), '.'.$facetId, 'rpId mismatch.'); + + if (!in_array($facetId, $securedRelyingPartyId, true)) { + $scheme = $parsedRelyingPartyId['scheme'] ?? ''; + Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); + } + + /** @see 7.1.6 */ + if (null !== $C->getTokenBinding()) { + $this->tokenBindingHandler->check($C->getTokenBinding(), $request); + } + + /** @see 7.1.7 */ + $clientDataJSONHash = hash('sha256', $authenticatorAttestationResponse->getClientDataJSON()->getRawData(), true); + + /** @see 7.1.8 */ + $attestationObject = $authenticatorAttestationResponse->getAttestationObject(); + + /** @see 7.1.9 */ + $rpIdHash = hash('sha256', $facetId, true); + Assertion::true(hash_equals($rpIdHash, $attestationObject->getAuthData()->getRpIdHash()), 'rpId hash mismatch.'); + + /** @see 7.1.10 */ + Assertion::true($attestationObject->getAuthData()->isUserPresent(), 'User was not present'); + /** @see 7.1.11 */ + if (AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED === $publicKeyCredentialCreationOptions->getAuthenticatorSelection()->getUserVerification()) { + Assertion::true($attestationObject->getAuthData()->isUserVerified(), 'User authentication required.'); + } + + /** @see 7.1.12 */ + $extensionsClientOutputs = $attestationObject->getAuthData()->getExtensions(); + if (null !== $extensionsClientOutputs) { + $this->extensionOutputCheckerHandler->check( + $publicKeyCredentialCreationOptions->getExtensions(), + $extensionsClientOutputs + ); + } + + /** @see 7.1.13 */ + $this->checkMetadataStatement($publicKeyCredentialCreationOptions, $attestationObject); + $fmt = $attestationObject->getAttStmt()->getFmt(); + Assertion::true($this->attestationStatementSupportManager->has($fmt), 'Unsupported attestation statement format.'); + + /** @see 7.1.14 */ + $attestationStatementSupport = $this->attestationStatementSupportManager->get($fmt); + Assertion::true($attestationStatementSupport->isValid($clientDataJSONHash, $attestationObject->getAttStmt(), $attestationObject->getAuthData()), 'Invalid attestation statement.'); + + /** @see 7.1.15 */ + /** @see 7.1.16 */ + /** @see 7.1.17 */ + Assertion::true($attestationObject->getAuthData()->hasAttestedCredentialData(), 'There is no attested credential data.'); + $attestedCredentialData = $attestationObject->getAuthData()->getAttestedCredentialData(); + Assertion::notNull($attestedCredentialData, 'There is no attested credential data.'); + $credentialId = $attestedCredentialData->getCredentialId(); + Assertion::null($this->publicKeyCredentialSource->findOneByCredentialId($credentialId), 'The credential ID already exists.'); + + /** @see 7.1.18 */ + /** @see 7.1.19 */ + $publicKeyCredentialSource = $this->createPublicKeyCredentialSource( + $credentialId, + $attestedCredentialData, + $attestationObject, + $publicKeyCredentialCreationOptions->getUser()->getId() + ); + $this->logger->info('The attestation is valid'); + $this->logger->debug('Public Key Credential Source', ['publicKeyCredentialSource' => $publicKeyCredentialSource]); + + return $publicKeyCredentialSource; + } catch (Throwable $throwable) { + $this->logger->error('An error occurred', [ + 'exception' => $throwable, + ]); + throw $throwable; + } + } + + private function checkCertificateChain(AttestationStatement $attestationStatement, ?MetadataStatement $metadataStatement): void + { + $trustPath = $attestationStatement->getTrustPath(); + if (!$trustPath instanceof CertificateTrustPath) { + return; + } + $authenticatorCertificates = $trustPath->getCertificates(); + + if (null === $metadataStatement) { + // @phpstan-ignore-next-line + null === $this->certificateChainChecker ? CertificateToolbox::checkChain($authenticatorCertificates) : $this->certificateChainChecker->check($authenticatorCertificates, [], null); + + return; + } + + $metadataStatementCertificates = $metadataStatement->getAttestationRootCertificates(); + $rootStatementCertificates = $metadataStatement->getRootCertificates(); + foreach ($metadataStatementCertificates as $key => $metadataStatementCertificate) { + $metadataStatementCertificates[$key] = CertificateToolbox::fixPEMStructure($metadataStatementCertificate); + } + $trustedCertificates = array_merge( + $metadataStatementCertificates, + $rootStatementCertificates + ); + + // @phpstan-ignore-next-line + null === $this->certificateChainChecker ? CertificateToolbox::checkChain($authenticatorCertificates, $trustedCertificates) : $this->certificateChainChecker->check($authenticatorCertificates, $trustedCertificates); + } + + private function checkMetadataStatement(PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, AttestationObject $attestationObject): void + { + $attestationStatement = $attestationObject->getAttStmt(); + $attestedCredentialData = $attestationObject->getAuthData()->getAttestedCredentialData(); + Assertion::notNull($attestedCredentialData, 'No attested credential data found'); + $aaguid = $attestedCredentialData->getAaguid()->toString(); + if (PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE === $publicKeyCredentialCreationOptions->getAttestation()) { + $this->logger->debug('No attestation is asked.'); + //No attestation is asked. We shall ensure that the data is anonymous. + if ( + '00000000-0000-0000-0000-000000000000' === $aaguid + && (AttestationStatement::TYPE_NONE === $attestationStatement->getType() || AttestationStatement::TYPE_SELF === $attestationStatement->getType())) { + $this->logger->debug('The Attestation Statement is anonymous.'); + $this->checkCertificateChain($attestationStatement, null); + + return; + } + $this->logger->debug('Anonymization required. AAGUID and Attestation Statement changed.', [ + 'aaguid' => $aaguid, + 'AttestationStatement' => $attestationStatement, + ]); + $attestedCredentialData->setAaguid( + Uuid::fromString('00000000-0000-0000-0000-000000000000') + ); + $attestationObject->setAttStmt(AttestationStatement::createNone('none', [], new EmptyTrustPath())); + + return; + } + if (AttestationStatement::TYPE_NONE === $attestationStatement->getType()) { + $this->logger->debug('No attestation returned.'); + //No attestation is returned. We shall ensure that the AAGUID is a null one. + if ('00000000-0000-0000-0000-000000000000' !== $aaguid) { + $this->logger->debug('Anonymization required. AAGUID and Attestation Statement changed.', [ + 'aaguid' => $aaguid, + 'AttestationStatement' => $attestationStatement, + ]); + $attestedCredentialData->setAaguid( + Uuid::fromString('00000000-0000-0000-0000-000000000000') + ); + + return; + } + + return; + } + + //The MDS Repository is mandatory here + Assertion::notNull($this->metadataStatementRepository, 'The Metadata Statement Repository is mandatory when requesting attestation objects.'); + $metadataStatement = $this->metadataStatementRepository->findOneByAAGUID($aaguid); + + // We check the last status report + $this->checkStatusReport(null === $metadataStatement ? [] : $metadataStatement->getStatusReports()); + + // We check the certificate chain (if any) + $this->checkCertificateChain($attestationStatement, $metadataStatement); + + // If no Attestation Statement has been returned or if null AAGUID (=00000000-0000-0000-0000-000000000000) + // => nothing to check + if ('00000000-0000-0000-0000-000000000000' === $aaguid || AttestationStatement::TYPE_NONE === $attestationStatement->getType()) { + return; + } + + // At this point, the Metadata Statement is mandatory + Assertion::notNull($metadataStatement, sprintf('The Metadata Statement for the AAGUID "%s" is missing', $aaguid)); + + // Check Attestation Type is allowed + if (0 !== count($metadataStatement->getAttestationTypes())) { + $type = $this->getAttestationType($attestationStatement); + Assertion::inArray($type, $metadataStatement->getAttestationTypes(), 'Invalid attestation statement. The attestation type is not allowed for this authenticator'); + } + } + + /** + * @param StatusReport[] $statusReports + */ + private function checkStatusReport(array $statusReports): void + { + if (0 !== count($statusReports)) { + $lastStatusReport = end($statusReports); + if ($lastStatusReport->isCompromised()) { + throw new LogicException('The authenticator is compromised and cannot be used'); + } + } + } + + private function createPublicKeyCredentialSource(string $credentialId, AttestedCredentialData $attestedCredentialData, AttestationObject $attestationObject, string $userHandle): PublicKeyCredentialSource + { + return new PublicKeyCredentialSource( + $credentialId, + PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, + [], + $attestationObject->getAttStmt()->getType(), + $attestationObject->getAttStmt()->getTrustPath(), + $attestedCredentialData->getAaguid(), + $attestedCredentialData->getCredentialPublicKey(), + $userHandle, + $attestationObject->getAuthData()->getSignCount() + ); + } + + private function getAttestationType(AttestationStatement $attestationStatement): int + { + switch ($attestationStatement->getType()) { + case AttestationStatement::TYPE_BASIC: + return MetadataStatement::ATTESTATION_BASIC_FULL; + case AttestationStatement::TYPE_SELF: + return MetadataStatement::ATTESTATION_BASIC_SURROGATE; + case AttestationStatement::TYPE_ATTCA: + return MetadataStatement::ATTESTATION_ATTCA; + case AttestationStatement::TYPE_ECDAA: + return MetadataStatement::ATTESTATION_ECDAA; + default: + throw new InvalidArgumentException('Invalid attestation type'); + } + } + + private function getFacetId(string $rpId, AuthenticationExtensionsClientInputs $authenticationExtensionsClientInputs, ?AuthenticationExtensionsClientOutputs $authenticationExtensionsClientOutputs): string + { + if (null === $authenticationExtensionsClientOutputs || !$authenticationExtensionsClientInputs->has('appid') || !$authenticationExtensionsClientOutputs->has('appid')) { + return $rpId; + } + $appId = $authenticationExtensionsClientInputs->get('appid')->value(); + $wasUsed = $authenticationExtensionsClientOutputs->get('appid')->value(); + if (!is_string($appId) || true !== $wasUsed) { + return $rpId; + } + + return $appId; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorData.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorData.php new file mode 100644 index 00000000..086ae50b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorData.php @@ -0,0 +1,124 @@ +rpIdHash = $rpIdHash; + $this->flags = $flags; + $this->signCount = $signCount; + $this->attestedCredentialData = $attestedCredentialData; + $this->extensions = $extensions; + $this->authData = $authData; + } + + public function getAuthData(): string + { + return $this->authData; + } + + public function getRpIdHash(): string + { + return $this->rpIdHash; + } + + public function isUserPresent(): bool + { + return 0 !== (ord($this->flags) & self::FLAG_UP) ? true : false; + } + + public function isUserVerified(): bool + { + return 0 !== (ord($this->flags) & self::FLAG_UV) ? true : false; + } + + public function hasAttestedCredentialData(): bool + { + return 0 !== (ord($this->flags) & self::FLAG_AT) ? true : false; + } + + public function hasExtensions(): bool + { + return 0 !== (ord($this->flags) & self::FLAG_ED) ? true : false; + } + + public function getReservedForFutureUse1(): int + { + return ord($this->flags) & self::FLAG_RFU1; + } + + public function getReservedForFutureUse2(): int + { + return ord($this->flags) & self::FLAG_RFU2; + } + + public function getSignCount(): int + { + return $this->signCount; + } + + public function getAttestedCredentialData(): ?AttestedCredentialData + { + return $this->attestedCredentialData; + } + + public function getExtensions(): ?AuthenticationExtensionsClientOutputs + { + return null !== $this->extensions && $this->hasExtensions() ? $this->extensions : null; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorResponse.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorResponse.php new file mode 100644 index 00000000..2bcee456 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorResponse.php @@ -0,0 +1,35 @@ +clientDataJSON = $clientDataJSON; + } + + public function getClientDataJSON(): CollectedClientData + { + return $this->clientDataJSON; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php new file mode 100644 index 00000000..7f700dd0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php @@ -0,0 +1,167 @@ +authenticatorAttachment = $authenticatorAttachment; + $this->requireResidentKey = $requireResidentKey ?? false; + $this->userVerification = $userVerification ?? self::USER_VERIFICATION_REQUIREMENT_PREFERRED; + $this->residentKey = $residentKey ?? self::RESIDENT_KEY_REQUIREMENT_NONE; + } + + public static function create(): self + { + return new self(); + } + + public function setAuthenticatorAttachment(?string $authenticatorAttachment): self + { + $this->authenticatorAttachment = $authenticatorAttachment; + + return $this; + } + + public function setRequireResidentKey(bool $requireResidentKey): self + { + $this->requireResidentKey = $requireResidentKey; + + return $this; + } + + public function setUserVerification(string $userVerification): self + { + $this->userVerification = $userVerification; + + return $this; + } + + public function setResidentKey(?string $residentKey): self + { + $this->residentKey = $residentKey; + + return $this; + } + + public function getAuthenticatorAttachment(): ?string + { + return $this->authenticatorAttachment; + } + + public function isRequireResidentKey(): bool + { + return $this->requireResidentKey; + } + + public function getUserVerification(): string + { + return $this->userVerification; + } + + public function getResidentKey(): ?string + { + return $this->residentKey; + } + + public static function createFromString(string $data): self + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + return self::create() + ->setAuthenticatorAttachment($json['authenticatorAttachment'] ?? null) + ->setRequireResidentKey($json['requireResidentKey'] ?? false) + ->setUserVerification($json['userVerification'] ?? self::USER_VERIFICATION_REQUIREMENT_PREFERRED) + ->setResidentKey($json['residentKey'] ?? self::RESIDENT_KEY_REQUIREMENT_NONE) + ; + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $json = [ + 'requireResidentKey' => $this->requireResidentKey, + 'userVerification' => $this->userVerification, + ]; + if (null !== $this->authenticatorAttachment) { + $json['authenticatorAttachment'] = $this->authenticatorAttachment; + } + if (null !== $this->residentKey) { + $json['residentKey'] = $this->residentKey; + } + + return $json; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php new file mode 100644 index 00000000..12e9974e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php @@ -0,0 +1,23 @@ +client = $client; + $this->requestFactory = $requestFactory; + } + + public function addRootCertificate(string $certificate): self + { + $this->rootCertificates[] = $certificate; + + return $this; + } + + /** + * @param string[] $authenticatorCertificates + * @param string[] $trustedCertificates + */ + public function check(array $authenticatorCertificates, array $trustedCertificates): void + { + if (0 === count($trustedCertificates)) { + $this->checkCertificatesValidity($authenticatorCertificates, true); + + return; + } + $this->checkCertificatesValidity($authenticatorCertificates, false); + + $hasCrls = false; + $processArguments = ['-no-CAfile', '-no-CApath']; + + $caDirname = $this->createTemporaryDirectory(); + $processArguments[] = '--CApath'; + $processArguments[] = $caDirname; + + foreach ($trustedCertificates as $certificate) { + $this->saveToTemporaryFile($caDirname, $certificate, 'webauthn-trusted-', '.pem'); + $crl = $this->getCrls($certificate); + if ('' !== $crl) { + $hasCrls = true; + $this->saveToTemporaryFile($caDirname, $crl, 'webauthn-trusted-crl-', '.crl'); + } + } + + $rehashProcess = new Process(['openssl', 'rehash', $caDirname]); + $rehashProcess->run(); + while ($rehashProcess->isRunning()) { + //Just wait + } + if (!$rehashProcess->isSuccessful()) { + throw new InvalidArgumentException('Invalid certificate or certificate chain'); + } + + $filenames = []; + $leafCertificate = array_shift($authenticatorCertificates); + $leafFilename = $this->saveToTemporaryFile(sys_get_temp_dir(), $leafCertificate, 'webauthn-leaf-', '.pem'); + $crl = $this->getCrls($leafCertificate); + if ('' !== $crl) { + $hasCrls = true; + $this->saveToTemporaryFile($caDirname, $crl, 'webauthn-leaf-crl-', '.pem'); + } + $filenames[] = $leafFilename; + + foreach ($authenticatorCertificates as $certificate) { + $untrustedFilename = $this->saveToTemporaryFile(sys_get_temp_dir(), $certificate, 'webauthn-untrusted-', '.pem'); + $crl = $this->getCrls($certificate); + if ('' !== $crl) { + $hasCrls = true; + $this->saveToTemporaryFile($caDirname, $crl, 'webauthn-untrusted-crl-', '.pem'); + } + $processArguments[] = '-untrusted'; + $processArguments[] = $untrustedFilename; + $filenames[] = $untrustedFilename; + } + + $processArguments[] = $leafFilename; + if ($hasCrls) { + array_unshift($processArguments, '-crl_check'); + array_unshift($processArguments, '-crl_check_all'); + //array_unshift($processArguments, '-crl_download'); + array_unshift($processArguments, '-extended_crl'); + } + array_unshift($processArguments, 'openssl', 'verify'); + + $process = new Process($processArguments); + $process->run(); + while ($process->isRunning()) { + //Just wait + } + + foreach ($filenames as $filename) { + try { + unlink($filename); + } catch (FilesystemException $e) { + continue; + } + } + $this->deleteDirectory($caDirname); + + if (!$process->isSuccessful()) { + throw new InvalidArgumentException('Invalid certificate or certificate chain'); + } + } + + /** + * @param string[] $certificates + */ + private function checkCertificatesValidity(array $certificates, bool $allowRootCertificate): void + { + foreach ($certificates as $certificate) { + $parsed = openssl_x509_parse($certificate); + Assertion::isArray($parsed, 'Unable to read the certificate'); + if (false === $allowRootCertificate) { + $this->checkRootCertificate($parsed); + } + + Assertion::keyExists($parsed, 'validTo_time_t', 'The certificate has no validity period'); + Assertion::keyExists($parsed, 'validFrom_time_t', 'The certificate has no validity period'); + Assertion::lessOrEqualThan(time(), $parsed['validTo_time_t'], 'The certificate expired'); + Assertion::greaterOrEqualThan(time(), $parsed['validFrom_time_t'], 'The certificate is not usable yet'); + } + } + + /** + * @param array $parsed + */ + private function checkRootCertificate(array $parsed): void + { + Assertion::keyExists($parsed, 'subject', 'The certificate has no subject'); + Assertion::keyExists($parsed, 'issuer', 'The certificate has no issuer'); + $subject = $parsed['subject']; + $issuer = $parsed['issuer']; + ksort($subject); + ksort($issuer); + Assertion::notEq($subject, $issuer, 'Root certificates are not allowed'); + } + + private function createTemporaryDirectory(): string + { + $caDir = tempnam(sys_get_temp_dir(), 'webauthn-ca-'); + if (file_exists($caDir)) { + unlink($caDir); + } + mkdir($caDir); + if (!is_dir($caDir)) { + throw new RuntimeException(sprintf('Directory "%s" was not created', $caDir)); + } + + return $caDir; + } + + private function deleteDirectory(string $dirname): void + { + $rehashProcess = new Process(['rm', '-rf', $dirname]); + $rehashProcess->run(); + while ($rehashProcess->isRunning()) { + //Just wait + } + } + + private function saveToTemporaryFile(string $folder, string $certificate, string $prefix, string $suffix): string + { + $filename = tempnam($folder, $prefix); + rename($filename, $filename.$suffix); + file_put_contents($filename.$suffix, $certificate, FILE_APPEND); + + return $filename.$suffix; + } + + private function getCrls(string $certificate): string + { + $parsed = openssl_x509_parse($certificate); + if (false === $parsed || !isset($parsed['extensions']['crlDistributionPoints'])) { + return ''; + } + $endpoint = $parsed['extensions']['crlDistributionPoints']; + $pos = mb_strpos($endpoint, 'URI:'); + if (!is_int($pos)) { + return ''; + } + + $endpoint = trim(mb_substr($endpoint, $pos + 4)); + $request = $this->requestFactory->createRequest('GET', $endpoint); + $response = $this->client->sendRequest($request); + + if (200 !== $response->getStatusCode()) { + return ''; + } + + return $response->getBody()->getContents(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateToolbox.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateToolbox.php new file mode 100644 index 00000000..51a08ab9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CertificateToolbox.php @@ -0,0 +1,223 @@ +run(); + while ($rehashProcess->isRunning()) { + //Just wait + } + if (!$rehashProcess->isSuccessful()) { + throw new InvalidArgumentException('Invalid certificate or certificate chain'); + } + + $filenames = []; + $leafCertificate = array_shift($authenticatorCertificates); + $leafFilename = self::prepareCertificate(sys_get_temp_dir(), $leafCertificate, 'webauthn-leaf-', '.pem'); + $filenames[] = $leafFilename; + + foreach ($authenticatorCertificates as $certificate) { + $untrustedFilename = self::prepareCertificate(sys_get_temp_dir(), $certificate, 'webauthn-untrusted-', '.pem'); + $processArguments[] = '-untrusted'; + $processArguments[] = $untrustedFilename; + $filenames[] = $untrustedFilename; + } + + $processArguments[] = $leafFilename; + array_unshift($processArguments, 'openssl', 'verify'); + + $process = new Process($processArguments); + $process->run(); + while ($process->isRunning()) { + //Just wait + } + + foreach ($filenames as $filename) { + try { + unlink($filename); + } catch (FilesystemException $e) { + continue; + } + } + self::deleteDirectory($caDirname); + + if (!$process->isSuccessful()) { + throw new InvalidArgumentException('Invalid certificate or certificate chain'); + } + } + + public static function fixPEMStructure(string $certificate, string $type = 'CERTIFICATE'): string + { + $pemCert = '-----BEGIN '.$type.'-----'.PHP_EOL; + $pemCert .= chunk_split($certificate, 64, PHP_EOL); + $pemCert .= '-----END '.$type.'-----'.PHP_EOL; + + return $pemCert; + } + + public static function convertDERToPEM(string $certificate, string $type = 'CERTIFICATE'): string + { + $derCertificate = self::unusedBytesFix($certificate); + + return self::fixPEMStructure(base64_encode($derCertificate), $type); + } + + /** + * @param string[] $certificates + * + * @return string[] + */ + public static function convertAllDERToPEM(array $certificates, string $type = 'CERTIFICATE'): array + { + $certs = []; + foreach ($certificates as $publicKey) { + $certs[] = self::convertDERToPEM($publicKey, $type); + } + + return $certs; + } + + private static function unusedBytesFix(string $certificate): string + { + $certificateHash = hash('sha256', $certificate); + if (in_array($certificateHash, self::getCertificateHashes(), true)) { + $certificate[mb_strlen($certificate, '8bit') - 257] = "\0"; + } + + return $certificate; + } + + /** + * @param string[] $certificates + */ + private static function checkCertificatesValidity(array $certificates, bool $allowRootCertificate): void + { + foreach ($certificates as $certificate) { + $parsed = openssl_x509_parse($certificate); + Assertion::isArray($parsed, 'Unable to read the certificate'); + if (false === $allowRootCertificate) { + self::checkRootCertificate($parsed); + } + + Assertion::keyExists($parsed, 'validTo_time_t', 'The certificate has no validity period'); + Assertion::keyExists($parsed, 'validFrom_time_t', 'The certificate has no validity period'); + Assertion::lessOrEqualThan(time(), $parsed['validTo_time_t'], 'The certificate expired'); + Assertion::greaterOrEqualThan(time(), $parsed['validFrom_time_t'], 'The certificate is not usable yet'); + } + } + + /** + * @param array $parsed + */ + private static function checkRootCertificate(array $parsed): void + { + Assertion::keyExists($parsed, 'subject', 'The certificate has no subject'); + Assertion::keyExists($parsed, 'issuer', 'The certificate has no issuer'); + $subject = $parsed['subject']; + $issuer = $parsed['issuer']; + ksort($subject); + ksort($issuer); + Assertion::notEq($subject, $issuer, 'Root certificates are not allowed'); + } + + /** + * @return string[] + */ + private static function getCertificateHashes(): array + { + return [ + '349bca1031f8c82c4ceca38b9cebf1a69df9fb3b94eed99eb3fb9aa3822d26e8', + 'dd574527df608e47ae45fbba75a2afdd5c20fd94a02419381813cd55a2a3398f', + '1d8764f0f7cd1352df6150045c8f638e517270e8b5dda1c63ade9c2280240cae', + 'd0edc9a91a1677435a953390865d208c55b3183c6759c9b5a7ff494c322558eb', + '6073c436dcd064a48127ddbf6032ac1a66fd59a0c24434f070d4e564c124c897', + 'ca993121846c464d666096d35f13bf44c1b05af205f9b4a1e00cf6cc10c5e511', + ]; + } + + private static function createTemporaryDirectory(): string + { + $caDir = tempnam(sys_get_temp_dir(), 'webauthn-ca-'); + if (file_exists($caDir)) { + unlink($caDir); + } + mkdir($caDir); + if (!is_dir($caDir)) { + throw new RuntimeException(sprintf('Directory "%s" was not created', $caDir)); + } + + return $caDir; + } + + private static function deleteDirectory(string $dirname): void + { + $rehashProcess = new Process(['rm', '-rf', $dirname]); + $rehashProcess->run(); + while ($rehashProcess->isRunning()) { + //Just wait + } + } + + private static function prepareCertificate(string $folder, string $certificate, string $prefix, string $suffix): string + { + $untrustedFilename = tempnam($folder, $prefix); + rename($untrustedFilename, $untrustedFilename.$suffix); + file_put_contents($untrustedFilename.$suffix, $certificate, FILE_APPEND); + file_put_contents($untrustedFilename.$suffix, PHP_EOL, FILE_APPEND); + + return $untrustedFilename.$suffix; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CollectedClientData.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CollectedClientData.php new file mode 100644 index 00000000..d020cca8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/CollectedClientData.php @@ -0,0 +1,145 @@ +type = $this->findData($data, 'type'); + $this->challenge = $this->findData($data, 'challenge', true, true); + $this->origin = $this->findData($data, 'origin'); + $this->tokenBinding = $this->findData($data, 'tokenBinding', false); + $this->rawData = $rawData; + $this->data = $data; + } + + public static function createFormJson(string $data): self + { + $rawData = Base64Url::decode($data); + $json = json_decode($rawData, true); + Assertion::isArray($json, 'Invalid collected client data'); + + return new self($rawData, $json); + } + + public function getType(): string + { + return $this->type; + } + + public function getChallenge(): string + { + return $this->challenge; + } + + public function getOrigin(): string + { + return $this->origin; + } + + public function getTokenBinding(): ?TokenBinding + { + return null === $this->tokenBinding ? null : TokenBinding::createFormArray($this->tokenBinding); + } + + public function getRawData(): string + { + return $this->rawData; + } + + /** + * @return string[] + */ + public function all(): array + { + return array_keys($this->data); + } + + public function has(string $key): bool + { + return array_key_exists($key, $this->data); + } + + /** + * @return mixed + */ + public function get(string $key) + { + if (!$this->has($key)) { + throw new InvalidArgumentException(sprintf('The key "%s" is missing', $key)); + } + + return $this->data[$key]; + } + + /** + * @param mixed[] $json + * + * @return mixed|null + */ + private function findData(array $json, string $key, bool $isRequired = true, bool $isB64 = false) + { + if (!array_key_exists($key, $json)) { + if ($isRequired) { + throw new InvalidArgumentException(sprintf('The key "%s" is missing', $key)); + } + + return; + } + + return $isB64 ? Base64Url::decode($json[$key]) : $json[$key]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Counter/CounterChecker.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Counter/CounterChecker.php new file mode 100644 index 00000000..ed128bb1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Counter/CounterChecker.php @@ -0,0 +1,21 @@ +logger = $logger ?? new NullLogger(); + } + + public function check(PublicKeyCredentialSource $publicKeyCredentialSource, int $currentCounter): void + { + try { + Assertion::greaterThan($currentCounter, $publicKeyCredentialSource->getCounter(), 'Invalid counter.'); + } catch (Throwable $throwable) { + $this->logger->error('The counter is invalid', [ + 'current' => $currentCounter, + 'new' => $publicKeyCredentialSource->getCounter(), + ]); + throw $throwable; + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Credential.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Credential.php new file mode 100644 index 00000000..bfaaadd7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Credential.php @@ -0,0 +1,46 @@ +id = $id; + $this->type = $type; + } + + public function getId(): string + { + return $this->id; + } + + public function getType(): string + { + return $this->type; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredential.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredential.php new file mode 100644 index 00000000..66758a9e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredential.php @@ -0,0 +1,62 @@ +rawId = $rawId; + $this->response = $response; + } + + public function __toString() + { + return json_encode($this); + } + + public function getRawId(): string + { + return $this->rawId; + } + + public function getResponse(): AuthenticatorResponse + { + return $this->response; + } + + /** + * @param string[] $transport + */ + public function getPublicKeyCredentialDescriptor(array $transport = []): PublicKeyCredentialDescriptor + { + return new PublicKeyCredentialDescriptor($this->getType(), $this->getRawId(), $transport); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php new file mode 100644 index 00000000..84a3d287 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php @@ -0,0 +1,261 @@ +rp = $rp; + $this->user = $user; + $this->pubKeyCredParams = $pubKeyCredParams; + $this->authenticatorSelection = $authenticatorSelection ?? new AuthenticatorSelectionCriteria(); + $this->attestation = $attestation ?? self::ATTESTATION_CONVEYANCE_PREFERENCE_NONE; + $this->excludeCredentials($excludeCredentials) + ; + } + + /** + * @param PublicKeyCredentialParameters[] $pubKeyCredParams + */ + public static function create(PublicKeyCredentialRpEntity $rp, PublicKeyCredentialUserEntity $user, string $challenge, array $pubKeyCredParams): self + { + return new self($rp, $user, $challenge, $pubKeyCredParams); + } + + public function addPubKeyCredParam(PublicKeyCredentialParameters $pubKeyCredParam): self + { + $this->pubKeyCredParams[] = $pubKeyCredParam; + + return $this; + } + + /** + * @param PublicKeyCredentialParameters[] $pubKeyCredParams + */ + public function addPubKeyCredParams(array $pubKeyCredParams): self + { + foreach ($pubKeyCredParams as $pubKeyCredParam) { + $this->addPubKeyCredParam($pubKeyCredParam); + } + + return $this; + } + + public function excludeCredential(PublicKeyCredentialDescriptor $excludeCredential): self + { + $this->excludeCredentials[] = $excludeCredential; + + return $this; + } + + /** + * @param PublicKeyCredentialDescriptor[] $excludeCredentials + */ + public function excludeCredentials(array $excludeCredentials): self + { + foreach ($excludeCredentials as $excludeCredential) { + $this->excludeCredential($excludeCredential); + } + + return $this; + } + + public function setAuthenticatorSelection(AuthenticatorSelectionCriteria $authenticatorSelection): self + { + $this->authenticatorSelection = $authenticatorSelection; + + return $this; + } + + public function setAttestation(string $attestation): self + { + Assertion::inArray($attestation, [ + self::ATTESTATION_CONVEYANCE_PREFERENCE_NONE, + self::ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT, + self::ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT, + self::ATTESTATION_CONVEYANCE_PREFERENCE_ENTERPRISE, + ], 'Invalid attestation conveyance mode'); + $this->attestation = $attestation; + + return $this; + } + + public function getRp(): PublicKeyCredentialRpEntity + { + return $this->rp; + } + + public function getUser(): PublicKeyCredentialUserEntity + { + return $this->user; + } + + /** + * @return PublicKeyCredentialParameters[] + */ + public function getPubKeyCredParams(): array + { + return $this->pubKeyCredParams; + } + + /** + * @return PublicKeyCredentialDescriptor[] + */ + public function getExcludeCredentials(): array + { + return $this->excludeCredentials; + } + + public function getAuthenticatorSelection(): AuthenticatorSelectionCriteria + { + return $this->authenticatorSelection; + } + + public function getAttestation(): string + { + return $this->attestation; + } + + public static function createFromString(string $data): PublicKeyCredentialOptions + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + public static function createFromArray(array $json): PublicKeyCredentialOptions + { + Assertion::keyExists($json, 'rp', 'Invalid input. "rp" is missing.'); + Assertion::keyExists($json, 'pubKeyCredParams', 'Invalid input. "pubKeyCredParams" is missing.'); + Assertion::isArray($json['pubKeyCredParams'], 'Invalid input. "pubKeyCredParams" is not an array.'); + Assertion::keyExists($json, 'challenge', 'Invalid input. "challenge" is missing.'); + Assertion::keyExists($json, 'attestation', 'Invalid input. "attestation" is missing.'); + Assertion::keyExists($json, 'user', 'Invalid input. "user" is missing.'); + Assertion::keyExists($json, 'authenticatorSelection', 'Invalid input. "authenticatorSelection" is missing.'); + + $pubKeyCredParams = []; + foreach ($json['pubKeyCredParams'] as $pubKeyCredParam) { + $pubKeyCredParams[] = PublicKeyCredentialParameters::createFromArray($pubKeyCredParam); + } + $excludeCredentials = []; + if (isset($json['excludeCredentials'])) { + foreach ($json['excludeCredentials'] as $excludeCredential) { + $excludeCredentials[] = PublicKeyCredentialDescriptor::createFromArray($excludeCredential); + } + } + + return self::create( + PublicKeyCredentialRpEntity::createFromArray($json['rp']), + PublicKeyCredentialUserEntity::createFromArray($json['user']), + Base64Url::decode($json['challenge']), + $pubKeyCredParams + ) + ->excludeCredentials($excludeCredentials) + ->setAuthenticatorSelection(AuthenticatorSelectionCriteria::createFromArray($json['authenticatorSelection'])) + ->setAttestation($json['attestation']) + ->setTimeout($json['timeout'] ?? null) + ->setExtensions(isset($json['extensions']) ? AuthenticationExtensionsClientInputs::createFromArray($json['extensions']) : new AuthenticationExtensionsClientInputs()) + ; + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $json = [ + 'rp' => $this->rp->jsonSerialize(), + 'pubKeyCredParams' => array_map(static function (PublicKeyCredentialParameters $object): array { + return $object->jsonSerialize(); + }, $this->pubKeyCredParams), + 'challenge' => Base64Url::encode($this->challenge), + 'attestation' => $this->attestation, + 'user' => $this->user->jsonSerialize(), + 'authenticatorSelection' => $this->authenticatorSelection->jsonSerialize(), + ]; + + if (0 !== count($this->excludeCredentials)) { + $json['excludeCredentials'] = array_map(static function (PublicKeyCredentialDescriptor $object): array { + return $object->jsonSerialize(); + }, $this->excludeCredentials); + } + + if (0 !== $this->extensions->count()) { + $json['extensions'] = $this->extensions; + } + + if (null !== $this->timeout) { + $json['timeout'] = $this->timeout; + } + + return $json; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php new file mode 100644 index 00000000..0008f105 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php @@ -0,0 +1,112 @@ +type = $type; + $this->id = $id; + $this->transports = $transports; + } + + public function getType(): string + { + return $this->type; + } + + public function getId(): string + { + return $this->id; + } + + /** + * @return string[] + */ + public function getTransports(): array + { + return $this->transports; + } + + public static function createFromString(string $data): self + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + Assertion::keyExists($json, 'type', 'Invalid input. "type" is missing.'); + Assertion::keyExists($json, 'id', 'Invalid input. "id" is missing.'); + + return new self( + $json['type'], + Base64Url::decode($json['id']), + $json['transports'] ?? [] + ); + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $json = [ + 'type' => $this->type, + 'id' => Base64Url::encode($this->id), + ]; + if (0 !== count($this->transports)) { + $json['transports'] = $this->transports; + } + + return $json; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php new file mode 100644 index 00000000..822b4731 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php @@ -0,0 +1,95 @@ +publicKeyCredentialDescriptors[$publicKeyCredentialDescriptor->getId()] = $publicKeyCredentialDescriptor; + } + + public function has(string $id): bool + { + return array_key_exists($id, $this->publicKeyCredentialDescriptors); + } + + public function remove(string $id): void + { + if (!$this->has($id)) { + return; + } + + unset($this->publicKeyCredentialDescriptors[$id]); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->publicKeyCredentialDescriptors); + } + + public function count(int $mode = COUNT_NORMAL): int + { + return count($this->publicKeyCredentialDescriptors, $mode); + } + + /** + * @return array[] + */ + public function jsonSerialize(): array + { + return array_map(static function (PublicKeyCredentialDescriptor $object): array { + return $object->jsonSerialize(); + }, $this->publicKeyCredentialDescriptors); + } + + public static function createFromString(string $data): self + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + $collection = new self(); + foreach ($json as $item) { + $collection->add(PublicKeyCredentialDescriptor::createFromArray($item)); + } + + return $collection; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php new file mode 100644 index 00000000..8e7533d3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php @@ -0,0 +1,60 @@ +name = $name; + $this->icon = $icon; + } + + public function getName(): string + { + return $this->name; + } + + public function getIcon(): ?string + { + return $this->icon; + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $json = [ + 'name' => $this->name, + ]; + if (null !== $this->icon) { + $json['icon'] = $this->icon; + } + + return $json; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php new file mode 100644 index 00000000..8fef7fe9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php @@ -0,0 +1,181 @@ +decoder = new Decoder(new TagObjectManager(), new OtherObjectManager()); + $this->attestationObjectLoader = $attestationObjectLoader; + $this->logger = $logger ?? new NullLogger(); + } + + public static function create(AttestationObjectLoader $attestationObjectLoader): self + { + return new self($attestationObjectLoader); + } + + public function setLogger(LoggerInterface $logger): self + { + $this->logger = $logger; + + return $this; + } + + /** + * @param mixed[] $json + */ + public function loadArray(array $json): PublicKeyCredential + { + $this->logger->info('Trying to load data from an array', ['data' => $json]); + try { + foreach (['id', 'rawId', 'type'] as $key) { + Assertion::keyExists($json, $key, sprintf('The parameter "%s" is missing', $key)); + Assertion::string($json[$key], sprintf('The parameter "%s" shall be a string', $key)); + } + Assertion::keyExists($json, 'response', 'The parameter "response" is missing'); + Assertion::isArray($json['response'], 'The parameter "response" shall be an array'); + Assertion::eq($json['type'], 'public-key', sprintf('Unsupported type "%s"', $json['type'])); + + $id = Base64Url::decode($json['id']); + $rawId = Base64Url::decode($json['rawId']); + Assertion::true(hash_equals($id, $rawId)); + + $publicKeyCredential = new PublicKeyCredential( + $json['id'], + $json['type'], + $rawId, + $this->createResponse($json['response']) + ); + $this->logger->info('The data has been loaded'); + $this->logger->debug('Public Key Credential', ['publicKeyCredential' => $publicKeyCredential]); + + return $publicKeyCredential; + } catch (Throwable $throwable) { + $this->logger->error('An error occurred', [ + 'exception' => $throwable, + ]); + throw $throwable; + } + } + + public function load(string $data): PublicKeyCredential + { + $this->logger->info('Trying to load data from a string', ['data' => $data]); + try { + $json = json_decode($data, true); + + return $this->loadArray($json); + } catch (Throwable $throwable) { + $this->logger->error('An error occurred', [ + 'exception' => $throwable, + ]); + throw $throwable; + } + } + + /** + * @param mixed[] $response + */ + private function createResponse(array $response): AuthenticatorResponse + { + Assertion::keyExists($response, 'clientDataJSON', 'Invalid data. The parameter "clientDataJSON" is missing'); + Assertion::string($response['clientDataJSON'], 'Invalid data. The parameter "clientDataJSON" is invalid'); + switch (true) { + case array_key_exists('attestationObject', $response): + Assertion::string($response['attestationObject'], 'Invalid data. The parameter "attestationObject " is invalid'); + $attestationObject = $this->attestationObjectLoader->load($response['attestationObject']); + + return new AuthenticatorAttestationResponse(CollectedClientData::createFormJson($response['clientDataJSON']), $attestationObject); + case array_key_exists('authenticatorData', $response) && array_key_exists('signature', $response): + $authData = Base64Url::decode($response['authenticatorData']); + + $authDataStream = new StringStream($authData); + $rp_id_hash = $authDataStream->read(32); + $flags = $authDataStream->read(1); + $signCount = $authDataStream->read(4); + $signCount = unpack('N', $signCount)[1]; + + $attestedCredentialData = null; + if (0 !== (ord($flags) & self::FLAG_AT)) { + $aaguid = Uuid::fromBytes($authDataStream->read(16)); + $credentialLength = $authDataStream->read(2); + $credentialLength = unpack('n', $credentialLength)[1]; + $credentialId = $authDataStream->read($credentialLength); + $credentialPublicKey = $this->decoder->decode($authDataStream); + Assertion::isInstanceOf($credentialPublicKey, MapObject::class, 'The data does not contain a valid credential public key.'); + $attestedCredentialData = new AttestedCredentialData($aaguid, $credentialId, (string) $credentialPublicKey); + } + + $extension = null; + if (0 !== (ord($flags) & self::FLAG_ED)) { + $extension = $this->decoder->decode($authDataStream); + $extension = AuthenticationExtensionsClientOutputsLoader::load($extension); + } + Assertion::true($authDataStream->isEOF(), 'Invalid authentication data. Presence of extra bytes.'); + $authDataStream->close(); + $authenticatorData = new AuthenticatorData($authData, $rp_id_hash, $flags, $signCount, $attestedCredentialData, $extension); + + return new AuthenticatorAssertionResponse( + CollectedClientData::createFormJson($response['clientDataJSON']), + $authenticatorData, + Base64Url::decode($response['signature']), + $response['userHandle'] ?? null + ); + default: + throw new InvalidArgumentException('Unable to create the response object'); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php new file mode 100644 index 00000000..6d5e79d7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php @@ -0,0 +1,104 @@ +challenge = $challenge; + $this->setTimeout($timeout); + $this->extensions = $extensions ?? new AuthenticationExtensionsClientInputs(); + } + + public function setTimeout(?int $timeout): self + { + $this->timeout = $timeout; + + return $this; + } + + public function addExtension(AuthenticationExtension $extension): self + { + $this->extensions->add($extension); + + return $this; + } + + /** + * @param AuthenticationExtension[] $extensions + */ + public function addExtensions(array $extensions): self + { + foreach ($extensions as $extension) { + $this->addExtension($extension); + } + + return $this; + } + + public function setExtensions(AuthenticationExtensionsClientInputs $extensions): self + { + $this->extensions = $extensions; + + return $this; + } + + public function getChallenge(): string + { + return $this->challenge; + } + + public function getTimeout(): ?int + { + return $this->timeout; + } + + public function getExtensions(): AuthenticationExtensionsClientInputs + { + return $this->extensions; + } + + abstract public static function createFromString(string $data): self; + + /** + * @param mixed[] $json + */ + abstract public static function createFromArray(array $json): self; +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php new file mode 100644 index 00000000..9b422450 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php @@ -0,0 +1,82 @@ +type = $type; + $this->alg = $alg; + } + + public function getType(): string + { + return $this->type; + } + + public function getAlg(): int + { + return $this->alg; + } + + public static function createFromString(string $data): self + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + Assertion::keyExists($json, 'type', 'Invalid input. "type" is missing.'); + Assertion::string($json['type'], 'Invalid input. "type" is not a string.'); + Assertion::keyExists($json, 'alg', 'Invalid input. "alg" is missing.'); + Assertion::integer($json['alg'], 'Invalid input. "alg" is not an integer.'); + + return new self( + $json['type'], + $json['alg'] + ); + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + return [ + 'type' => $this->type, + 'alg' => $this->alg, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php new file mode 100644 index 00000000..f11d1c01 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php @@ -0,0 +1,194 @@ +setRpId($rpId) + ->allowCredentials($allowCredentials) + ->setUserVerification($userVerification) + ; + } + + public static function create(string $challenge): self + { + return new self($challenge); + } + + public function setRpId(?string $rpId): self + { + $this->rpId = $rpId; + + return $this; + } + + public function allowCredential(PublicKeyCredentialDescriptor $allowCredential): self + { + $this->allowCredentials[] = $allowCredential; + + return $this; + } + + /** + * @param PublicKeyCredentialDescriptor[] $allowCredentials + */ + public function allowCredentials(array $allowCredentials): self + { + foreach ($allowCredentials as $allowCredential) { + $this->allowCredential($allowCredential); + } + + return $this; + } + + public function setUserVerification(?string $userVerification): self + { + if (null === $userVerification) { + $this->rpId = null; + + return $this; + } + Assertion::inArray($userVerification, [ + self::USER_VERIFICATION_REQUIREMENT_REQUIRED, + self::USER_VERIFICATION_REQUIREMENT_PREFERRED, + self::USER_VERIFICATION_REQUIREMENT_DISCOURAGED, + ], 'Invalid user verification requirement'); + $this->userVerification = $userVerification; + + return $this; + } + + public function getRpId(): ?string + { + return $this->rpId; + } + + /** + * @return PublicKeyCredentialDescriptor[] + */ + public function getAllowCredentials(): array + { + return $this->allowCredentials; + } + + public function getUserVerification(): ?string + { + return $this->userVerification; + } + + public static function createFromString(string $data): PublicKeyCredentialOptions + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): PublicKeyCredentialOptions + { + Assertion::keyExists($json, 'challenge', 'Invalid input. "challenge" is missing.'); + + $allowCredentials = []; + $allowCredentialList = $json['allowCredentials'] ?? []; + foreach ($allowCredentialList as $allowCredential) { + $allowCredentials[] = PublicKeyCredentialDescriptor::createFromArray($allowCredential); + } + + return self::create(Base64Url::decode($json['challenge'])) + ->setRpId($json['rpId'] ?? null) + ->allowCredentials($allowCredentials) + ->setUserVerification($json['userVerification'] ?? null) + ->setTimeout($json['timeout'] ?? null) + ->setExtensions(isset($json['extensions']) ? AuthenticationExtensionsClientInputs::createFromArray($json['extensions']) : new AuthenticationExtensionsClientInputs()) + ; + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $json = [ + 'challenge' => Base64Url::encode($this->challenge), + ]; + + if (null !== $this->rpId) { + $json['rpId'] = $this->rpId; + } + + if (null !== $this->userVerification) { + $json['userVerification'] = $this->userVerification; + } + + if (0 !== count($this->allowCredentials)) { + $json['allowCredentials'] = array_map(static function (PublicKeyCredentialDescriptor $object): array { + return $object->jsonSerialize(); + }, $this->allowCredentials); + } + + if (0 !== $this->extensions->count()) { + $json['extensions'] = $this->extensions->jsonSerialize(); + } + + if (null !== $this->timeout) { + $json['timeout'] = $this->timeout; + } + + return $json; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php new file mode 100644 index 00000000..336ce514 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php @@ -0,0 +1,62 @@ +id = $id; + } + + public function getId(): ?string + { + return $this->id; + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + Assertion::keyExists($json, 'name', 'Invalid input. "name" is missing.'); + + return new self( + $json['name'], + $json['id'] ?? null, + $json['icon'] ?? null + ); + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $json = parent::jsonSerialize(); + if (null !== $this->id) { + $json['id'] = $this->id; + } + + return $json; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php new file mode 100644 index 00000000..8c8ad323 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php @@ -0,0 +1,240 @@ +publicKeyCredentialId = $publicKeyCredentialId; + $this->type = $type; + $this->transports = $transports; + $this->aaguid = $aaguid; + $this->credentialPublicKey = $credentialPublicKey; + $this->userHandle = $userHandle; + $this->counter = $counter; + $this->attestationType = $attestationType; + $this->trustPath = $trustPath; + $this->otherUI = $otherUI; + } + + public function getPublicKeyCredentialId(): string + { + return $this->publicKeyCredentialId; + } + + public function getPublicKeyCredentialDescriptor(): PublicKeyCredentialDescriptor + { + return new PublicKeyCredentialDescriptor( + $this->type, + $this->publicKeyCredentialId, + $this->transports + ); + } + + public function getAttestationType(): string + { + return $this->attestationType; + } + + public function getTrustPath(): TrustPath + { + return $this->trustPath; + } + + public function getAttestedCredentialData(): AttestedCredentialData + { + return new AttestedCredentialData( + $this->aaguid, + $this->publicKeyCredentialId, + $this->credentialPublicKey + ); + } + + public function getType(): string + { + return $this->type; + } + + /** + * @return string[] + */ + public function getTransports(): array + { + return $this->transports; + } + + public function getAaguid(): UuidInterface + { + return $this->aaguid; + } + + public function getCredentialPublicKey(): string + { + return $this->credentialPublicKey; + } + + public function getUserHandle(): string + { + return $this->userHandle; + } + + public function getCounter(): int + { + return $this->counter; + } + + public function setCounter(int $counter): void + { + $this->counter = $counter; + } + + public function getOtherUI(): ?array + { + return $this->otherUI; + } + + public function setOtherUI(?array $otherUI): self + { + $this->otherUI = $otherUI; + + return $this; + } + + /** + * @param mixed[] $data + */ + public static function createFromArray(array $data): self + { + $keys = array_keys(get_class_vars(self::class)); + foreach ($keys as $key) { + if ('otherUI' === $key) { + continue; + } + Assertion::keyExists($data, $key, sprintf('The parameter "%s" is missing', $key)); + } + switch (true) { + case 36 === mb_strlen($data['aaguid'], '8bit'): + $uuid = Uuid::fromString($data['aaguid']); + break; + default: // Kept for compatibility with old format + $decoded = base64_decode($data['aaguid'], true); + $uuid = Uuid::fromBytes($decoded); + } + + try { + return new self( + Base64Url::decode($data['publicKeyCredentialId']), + $data['type'], + $data['transports'], + $data['attestationType'], + TrustPathLoader::loadTrustPath($data['trustPath']), + $uuid, + Base64Url::decode($data['credentialPublicKey']), + Base64Url::decode($data['userHandle']), + $data['counter'], + $data['otherUI'] ?? null + ); + } catch (Throwable $throwable) { + throw new InvalidArgumentException('Unable to load the data', $throwable->getCode(), $throwable); + } + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + return [ + 'publicKeyCredentialId' => Base64Url::encode($this->publicKeyCredentialId), + 'type' => $this->type, + 'transports' => $this->transports, + 'attestationType' => $this->attestationType, + 'trustPath' => $this->trustPath->jsonSerialize(), + 'aaguid' => $this->aaguid->toString(), + 'credentialPublicKey' => Base64Url::encode($this->credentialPublicKey), + 'userHandle' => Base64Url::encode($this->userHandle), + 'counter' => $this->counter, + 'otherUI' => $this->otherUI, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php new file mode 100644 index 00000000..66a0734e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php @@ -0,0 +1,26 @@ +id = $id; + $this->displayName = $displayName; + } + + public function getId(): string + { + return $this->id; + } + + public function getDisplayName(): string + { + return $this->displayName; + } + + public static function createFromString(string $data): self + { + $data = json_decode($data, true); + Assertion::isArray($data, 'Invalid data'); + + return self::createFromArray($data); + } + + /** + * @param mixed[] $json + */ + public static function createFromArray(array $json): self + { + Assertion::keyExists($json, 'name', 'Invalid input. "name" is missing.'); + Assertion::keyExists($json, 'id', 'Invalid input. "id" is missing.'); + Assertion::keyExists($json, 'displayName', 'Invalid input. "displayName" is missing.'); + $id = base64_decode($json['id'], true); + + return new self( + $json['name'], + $id, + $json['displayName'], + $json['icon'] ?? null + ); + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + $json = parent::jsonSerialize(); + $json['id'] = base64_encode($this->id); + $json['displayName'] = $this->displayName; + + return $json; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Server.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Server.php new file mode 100644 index 00000000..b1c0dca7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Server.php @@ -0,0 +1,351 @@ +rpEntity = $relyingParty; + $this->logger = new NullLogger(); + + $this->coseAlgorithmManagerFactory = new ManagerFactory(); + $this->coseAlgorithmManagerFactory->add('RS1', new RSA\RS1()); + $this->coseAlgorithmManagerFactory->add('RS256', new RSA\RS256()); + $this->coseAlgorithmManagerFactory->add('RS384', new RSA\RS384()); + $this->coseAlgorithmManagerFactory->add('RS512', new RSA\RS512()); + $this->coseAlgorithmManagerFactory->add('PS256', new RSA\PS256()); + $this->coseAlgorithmManagerFactory->add('PS384', new RSA\PS384()); + $this->coseAlgorithmManagerFactory->add('PS512', new RSA\PS512()); + $this->coseAlgorithmManagerFactory->add('ES256', new ECDSA\ES256()); + $this->coseAlgorithmManagerFactory->add('ES256K', new ECDSA\ES256K()); + $this->coseAlgorithmManagerFactory->add('ES384', new ECDSA\ES384()); + $this->coseAlgorithmManagerFactory->add('ES512', new ECDSA\ES512()); + $this->coseAlgorithmManagerFactory->add('Ed25519', new EdDSA\Ed25519()); + + $this->selectedAlgorithms = ['RS256', 'RS512', 'PS256', 'PS512', 'ES256', 'ES512', 'Ed25519']; + $this->publicKeyCredentialSourceRepository = $publicKeyCredentialSourceRepository; + $this->tokenBindingHandler = new IgnoreTokenBindingHandler(); + $this->extensionOutputCheckerHandler = new ExtensionOutputCheckerHandler(); + $this->metadataStatementRepository = $metadataStatementRepository; + } + + public function setMetadataStatementRepository(MetadataStatementRepository $metadataStatementRepository): self + { + $this->metadataStatementRepository = $metadataStatementRepository; + + return $this; + } + + /** + * @param string[] $selectedAlgorithms + */ + public function setSelectedAlgorithms(array $selectedAlgorithms): self + { + $this->selectedAlgorithms = $selectedAlgorithms; + + return $this; + } + + public function setTokenBindingHandler(TokenBindingHandler $tokenBindingHandler): self + { + $this->tokenBindingHandler = $tokenBindingHandler; + + return $this; + } + + public function addAlgorithm(string $alias, Algorithm $algorithm): self + { + $this->coseAlgorithmManagerFactory->add($alias, $algorithm); + $this->selectedAlgorithms[] = $alias; + $this->selectedAlgorithms = array_unique($this->selectedAlgorithms); + + return $this; + } + + public function setExtensionOutputCheckerHandler(ExtensionOutputCheckerHandler $extensionOutputCheckerHandler): self + { + $this->extensionOutputCheckerHandler = $extensionOutputCheckerHandler; + + return $this; + } + + /** + * @param string[] $securedRelyingPartyId + */ + public function setSecuredRelyingPartyId(array $securedRelyingPartyId): self + { + Assertion::allString($securedRelyingPartyId, 'Invalid list. Shall be a list of strings'); + $this->securedRelyingPartyId = $securedRelyingPartyId; + + return $this; + } + + /** + * @param PublicKeyCredentialDescriptor[] $excludedPublicKeyDescriptors + */ + public function generatePublicKeyCredentialCreationOptions(PublicKeyCredentialUserEntity $userEntity, ?string $attestationMode = null, array $excludedPublicKeyDescriptors = [], ?AuthenticatorSelectionCriteria $criteria = null, ?AuthenticationExtensionsClientInputs $extensions = null): PublicKeyCredentialCreationOptions + { + $coseAlgorithmManager = $this->coseAlgorithmManagerFactory->create($this->selectedAlgorithms); + $publicKeyCredentialParametersList = []; + foreach ($coseAlgorithmManager->all() as $algorithm) { + $publicKeyCredentialParametersList[] = new PublicKeyCredentialParameters( + PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, + $algorithm::identifier() + ); + } + $criteria = $criteria ?? new AuthenticatorSelectionCriteria(); + $extensions = $extensions ?? new AuthenticationExtensionsClientInputs(); + $challenge = random_bytes($this->challengeSize); + + return PublicKeyCredentialCreationOptions::create( + $this->rpEntity, + $userEntity, + $challenge, + $publicKeyCredentialParametersList + ) + ->excludeCredentials($excludedPublicKeyDescriptors) + ->setAuthenticatorSelection($criteria) + ->setAttestation($attestationMode ?? PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE) + ->setExtensions($extensions) + ->setTimeout($this->timeout) + ; + } + + /** + * @param PublicKeyCredentialDescriptor[] $allowedPublicKeyDescriptors + */ + public function generatePublicKeyCredentialRequestOptions(?string $userVerification = null, array $allowedPublicKeyDescriptors = [], ?AuthenticationExtensionsClientInputs $extensions = null): PublicKeyCredentialRequestOptions + { + return PublicKeyCredentialRequestOptions::create(random_bytes($this->challengeSize)) + ->setRpId($this->rpEntity->getId()) + ->setUserVerification($userVerification ?? PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_PREFERRED) + ->allowCredentials($allowedPublicKeyDescriptors) + ->setTimeout($this->timeout) + ->setExtensions($extensions ?? new AuthenticationExtensionsClientInputs()) + ; + } + + public function loadAndCheckAttestationResponse(string $data, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface $serverRequest): PublicKeyCredentialSource + { + $attestationStatementSupportManager = $this->getAttestationStatementSupportManager(); + $attestationObjectLoader = AttestationObjectLoader::create($attestationStatementSupportManager) + ->setLogger($this->logger) + ; + $publicKeyCredentialLoader = PublicKeyCredentialLoader::create($attestationObjectLoader) + ->setLogger($this->logger) + ; + + $publicKeyCredential = $publicKeyCredentialLoader->load($data); + $authenticatorResponse = $publicKeyCredential->getResponse(); + Assertion::isInstanceOf($authenticatorResponse, AuthenticatorAttestationResponse::class, 'Not an authenticator attestation response'); + + $authenticatorAttestationResponseValidator = new AuthenticatorAttestationResponseValidator( + $attestationStatementSupportManager, + $this->publicKeyCredentialSourceRepository, + $this->tokenBindingHandler, + $this->extensionOutputCheckerHandler, + $this->metadataStatementRepository + ); + $authenticatorAttestationResponseValidator->setLogger($this->logger); + + return $authenticatorAttestationResponseValidator->check($authenticatorResponse, $publicKeyCredentialCreationOptions, $serverRequest, $this->securedRelyingPartyId); + } + + public function loadAndCheckAssertionResponse(string $data, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ?PublicKeyCredentialUserEntity $userEntity, ServerRequestInterface $serverRequest): PublicKeyCredentialSource + { + $attestationStatementSupportManager = $this->getAttestationStatementSupportManager(); + $attestationObjectLoader = AttestationObjectLoader::create($attestationStatementSupportManager) + ->setLogger($this->logger) + ; + $publicKeyCredentialLoader = PublicKeyCredentialLoader::create($attestationObjectLoader) + ->setLogger($this->logger) + ; + + $publicKeyCredential = $publicKeyCredentialLoader->load($data); + $authenticatorResponse = $publicKeyCredential->getResponse(); + Assertion::isInstanceOf($authenticatorResponse, AuthenticatorAssertionResponse::class, 'Not an authenticator assertion response'); + + $authenticatorAssertionResponseValidator = new AuthenticatorAssertionResponseValidator( + $this->publicKeyCredentialSourceRepository, + $this->tokenBindingHandler, + $this->extensionOutputCheckerHandler, + $this->coseAlgorithmManagerFactory->create($this->selectedAlgorithms), + $this->counterChecker + ); + $authenticatorAssertionResponseValidator->setLogger($this->logger); + + return $authenticatorAssertionResponseValidator->check( + $publicKeyCredential->getRawId(), + $authenticatorResponse, + $publicKeyCredentialRequestOptions, + $serverRequest, + null !== $userEntity ? $userEntity->getId() : null, + $this->securedRelyingPartyId + ); + } + + public function setCounterChecker(CounterChecker $counterChecker): self + { + $this->counterChecker = $counterChecker; + + return $this; + } + + public function setLogger(LoggerInterface $logger): self + { + $this->logger = $logger; + + return $this; + } + + public function enforceAndroidSafetyNetVerification(ClientInterface $client, string $apiKey, RequestFactoryInterface $requestFactory): self + { + $this->httpClient = $client; + $this->googleApiKey = $apiKey; + $this->requestFactory = $requestFactory; + + return $this; + } + + private function getAttestationStatementSupportManager(): AttestationStatementSupportManager + { + $attestationStatementSupportManager = new AttestationStatementSupportManager(); + $attestationStatementSupportManager->add(new NoneAttestationStatementSupport()); + $attestationStatementSupportManager->add(new FidoU2FAttestationStatementSupport()); + if (class_exists(RS256::class) && class_exists(JWKFactory::class)) { + $androidSafetyNetAttestationStatementSupport = new AndroidSafetyNetAttestationStatementSupport(); + if (null !== $this->httpClient && null !== $this->googleApiKey && null !== $this->requestFactory) { + $androidSafetyNetAttestationStatementSupport + ->enableApiVerification($this->httpClient, $this->googleApiKey, $this->requestFactory) + ->setLeeway(2000) + ->setMaxAge(60000) + ; + } + $attestationStatementSupportManager->add($androidSafetyNetAttestationStatementSupport); + } + $attestationStatementSupportManager->add(new AndroidKeyAttestationStatementSupport()); + $attestationStatementSupportManager->add(new TPMAttestationStatementSupport()); + $coseAlgorithmManager = $this->coseAlgorithmManagerFactory->create($this->selectedAlgorithms); + $attestationStatementSupportManager->add(new PackedAttestationStatementSupport($coseAlgorithmManager)); + + return $attestationStatementSupportManager; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/StringStream.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/StringStream.php new file mode 100644 index 00000000..b60acee4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/StringStream.php @@ -0,0 +1,73 @@ +length = mb_strlen($data, '8bit'); + $resource = fopen('php://memory', 'rb+'); + fwrite($resource, $data); + rewind($resource); + $this->data = $resource; + } + + public function read(int $length): string + { + if (0 === $length) { + return ''; + } + $read = fread($this->data, $length); + $bytesRead = mb_strlen($read, '8bit'); + Assertion::length($read, $length, sprintf('Out of range. Expected: %d, read: %d.', $length, $bytesRead), null, '8bit'); + $this->totalRead += $bytesRead; + + return $read; + } + + public function close(): void + { + fclose($this->data); + } + + public function isEOF(): bool + { + return $this->totalRead === $this->length; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php new file mode 100644 index 00000000..4272acf0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php @@ -0,0 +1,24 @@ +getStatus()) { + return; + } + + Assertion::true($request->hasHeader('Sec-Token-Binding'), 'The header parameter "Sec-Token-Binding" is missing.'); + $tokenBindingIds = $request->getHeader('Sec-Token-Binding'); + Assertion::count($tokenBindingIds, 1, 'The header parameter "Sec-Token-Binding" is invalid.'); + $tokenBindingId = reset($tokenBindingIds); + Assertion::eq($tokenBindingId, $tokenBinding->getId(), 'The header parameter "Sec-Token-Binding" is invalid.'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php new file mode 100644 index 00000000..1a0adf73 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php @@ -0,0 +1,82 @@ +status = $status; + $this->id = $id; + } + + /** + * @param mixed[] $json + */ + public static function createFormArray(array $json): self + { + Assertion::keyExists($json, 'status', 'The member "status" is required'); + $status = $json['status']; + Assertion::inArray( + $status, + self::getSupportedStatus(), + sprintf('The member "status" is invalid. Supported values are: %s', implode(', ', self::getSupportedStatus())) + ); + $id = array_key_exists('id', $json) ? Base64Url::decode($json['id']) : null; + + return new self($status, $id); + } + + public function getStatus(): string + { + return $this->status; + } + + public function getId(): ?string + { + return $this->id; + } + + /** + * @return string[] + */ + private static function getSupportedStatus(): array + { + return [ + self::TOKEN_BINDING_STATUS_PRESENT, + self::TOKEN_BINDING_STATUS_SUPPORTED, + self::TOKEN_BINDING_STATUS_NOT_SUPPORTED, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php new file mode 100644 index 00000000..e81386ae --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php @@ -0,0 +1,21 @@ +getStatus(), 'Token binding not supported.'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php new file mode 100644 index 00000000..b2916ae0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php @@ -0,0 +1,61 @@ +certificates = $certificates; + } + + /** + * @return string[] + */ + public function getCertificates(): array + { + return $this->certificates; + } + + /** + * {@inheritdoc} + */ + public static function createFromArray(array $data): TrustPath + { + Assertion::keyExists($data, 'x5c', 'The trust path type is invalid'); + + return new CertificateTrustPath($data['x5c']); + } + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + return [ + 'type' => self::class, + 'x5c' => $this->certificates, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php new file mode 100644 index 00000000..0a575566 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php @@ -0,0 +1,55 @@ +ecdaaKeyId = $ecdaaKeyId; + } + + public function getEcdaaKeyId(): string + { + return $this->ecdaaKeyId; + } + + /** + * @return string[] + */ + public function jsonSerialize(): array + { + return [ + 'type' => self::class, + 'ecdaaKeyId' => $this->ecdaaKeyId, + ]; + } + + /** + * {@inheritdoc} + */ + public static function createFromArray(array $data): TrustPath + { + Assertion::keyExists($data, 'ecdaaKeyId', 'The trust path type is invalid'); + + return new EcdaaKeyIdTrustPath($data['ecdaaKeyId']); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php new file mode 100644 index 00000000..518ab0b9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php @@ -0,0 +1,35 @@ + self::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function createFromArray(array $data): TrustPath + { + return new EmptyTrustPath(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/TrustPath.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/TrustPath.php new file mode 100644 index 00000000..f83cfd94 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/TrustPath/TrustPath.php @@ -0,0 +1,24 @@ + EmptyTrustPath::class, + 'ecdaa_key_id' => EcdaaKeyIdTrustPath::class, + 'x5c' => CertificateTrustPath::class, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/U2FPublicKey.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/U2FPublicKey.php new file mode 100644 index 00000000..2bba5148 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/U2FPublicKey.php @@ -0,0 +1,46 @@ + MapItem::create( + new UnsignedIntegerObject(1, null), + new UnsignedIntegerObject(2, null) + ), + 3 => MapItem::create( + new UnsignedIntegerObject(3, null), + new NegativeIntegerObject(6, null) + ), + -1 => MapItem::create( + new NegativeIntegerObject(0, null), + new UnsignedIntegerObject(1, null) + ), + -2 => MapItem::create( + new NegativeIntegerObject(1, null), + new ByteStringObject(substr($publicKey, 1, 32)) + ), + -3 => MapItem::create( + new NegativeIntegerObject(2, null), + new ByteStringObject(substr($publicKey, 33)) + ), + ]); + + return $mapObject->__toString(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php new file mode 100644 index 00000000..3a01fba3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php @@ -0,0 +1,54 @@ +add($algorithm); + } + } + + /** + * Returns true if the algorithm is supported. + * + * @param string $algorithm The algorithm + */ + public function has(string $algorithm): bool + { + return array_key_exists($algorithm, $this->algorithms); + } + + /** + * Returns the list of names of supported algorithms. + * + * @return string[] + */ + public function list(): array + { + return array_keys($this->algorithms); + } + + /** + * Returns the algorithm if supported, otherwise throw an exception. + * + * @param string $algorithm The algorithm + * + * @throws InvalidArgumentException if the algorithm is not supported + */ + public function get(string $algorithm): Algorithm + { + if (!$this->has($algorithm)) { + throw new InvalidArgumentException(sprintf('The algorithm "%s" is not supported.', $algorithm)); + } + + return $this->algorithms[$algorithm]; + } + + /** + * Adds an algorithm to the manager. + */ + public function add(Algorithm $algorithm): void + { + $name = $algorithm->name(); + $this->algorithms[$name] = $algorithm; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/AlgorithmManagerFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/AlgorithmManagerFactory.php new file mode 100644 index 00000000..34e76313 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/AlgorithmManagerFactory.php @@ -0,0 +1,80 @@ +algorithms[$alias] = $algorithm; + } + + /** + * Returns the list of aliases. + * + * @return string[] + */ + public function aliases(): array + { + return array_keys($this->algorithms); + } + + /** + * Returns all algorithms supported by this factory. + * This is an associative array. Keys are the aliases of the algorithms. + * + * @return Algorithm[] + */ + public function all(): array + { + return $this->algorithms; + } + + /** + * Create an algorithm manager using the given aliases. + * + * @param string[] $aliases + * + * @throws InvalidArgumentException if the alias is invalid or is not supported + */ + public function create(array $aliases): AlgorithmManager + { + $algorithms = []; + foreach ($aliases as $alias) { + if (!is_string($alias)) { + throw new InvalidArgumentException('Invalid alias'); + } + if (!isset($this->algorithms[$alias])) { + throw new InvalidArgumentException(sprintf('The algorithm with the alias "%s" is not supported.', $alias)); + } + $algorithms[] = $this->algorithms[$alias]; + } + + return new AlgorithmManager($algorithms); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWK.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWK.php new file mode 100644 index 00000000..b029cd59 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWK.php @@ -0,0 +1,146 @@ +values = $values; + } + + /** + * Creates a JWK object using the given Json string. + * + * @throws InvalidArgumentException if the data is not valid + * + * @return JWK + */ + public static function createFromJson(string $json): self + { + $data = json_decode($json, true); + if (!is_array($data)) { + throw new InvalidArgumentException('Invalid argument.'); + } + + return new self($data); + } + + /** + * Returns the values to be serialized. + */ + public function jsonSerialize(): array + { + return $this->values; + } + + /** + * Get the value with a specific key. + * + * @param string $key The key + * + * @throws InvalidArgumentException if the key does not exist + * + * @return null|mixed + */ + public function get(string $key) + { + if (!$this->has($key)) { + throw new InvalidArgumentException(sprintf('The value identified by "%s" does not exist.', $key)); + } + + return $this->values[$key]; + } + + /** + * Returns true if the JWK has the value identified by. + * + * @param string $key The key + */ + public function has(string $key): bool + { + return array_key_exists($key, $this->values); + } + + /** + * Get all values stored in the JWK object. + * + * @return array Values of the JWK object + */ + public function all(): array + { + return $this->values; + } + + /** + * Returns the thumbprint of the key. + * + * @see https://tools.ietf.org/html/rfc7638 + * + * @throws InvalidArgumentException if the hashing function is not supported + */ + public function thumbprint(string $hash_algorithm): string + { + if (!in_array($hash_algorithm, hash_algos(), true)) { + throw new InvalidArgumentException(sprintf('The hash algorithm "%s" is not supported.', $hash_algorithm)); + } + $values = array_intersect_key($this->values, array_flip(['kty', 'n', 'e', 'crv', 'x', 'y', 'k'])); + ksort($values); + $input = json_encode($values, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + if (false === $input) { + throw new InvalidArgumentException('Unable to compute the key thumbprint'); + } + + return Base64Url::encode(hash($hash_algorithm, $input, true)); + } + + /** + * Returns the associated public key. + * This method has no effect for: + * - public keys + * - shared keys + * - unknown keys. + * + * Known keys are "oct", "RSA", "EC" and "OKP". + * + * @return JWK + */ + public function toPublic(): self + { + $values = array_diff_key($this->values, array_flip(['p', 'd', 'q', 'dp', 'dq', 'qi'])); + + return new self($values); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWKSet.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWKSet.php new file mode 100644 index 00000000..c72cea23 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWKSet.php @@ -0,0 +1,340 @@ + $key) { + if (!$key instanceof JWK) { + throw new InvalidArgumentException('Invalid list. Should only contains JWK objects'); + } + + if ($key->has('kid')) { + unset($keys[$k]); + $this->keys[$key->get('kid')] = $key; + } else { + $this->keys[] = $key; + } + } + } + + /** + * Creates a JWKSet object using the given values. + * + * @throws InvalidArgumentException if the keyset is not valid + * + * @return JWKSet + */ + public static function createFromKeyData(array $data): self + { + if (!isset($data['keys'])) { + throw new InvalidArgumentException('Invalid data.'); + } + if (!is_array($data['keys'])) { + throw new InvalidArgumentException('Invalid data.'); + } + + $jwkset = new self([]); + foreach ($data['keys'] as $key) { + $jwk = new JWK($key); + if ($jwk->has('kid')) { + $jwkset->keys[$jwk->get('kid')] = $jwk; + } else { + $jwkset->keys[] = $jwk; + } + } + + return $jwkset; + } + + /** + * Creates a JWKSet object using the given Json string. + * + * @throws InvalidArgumentException if the data is not valid + * + * @return JWKSet + */ + public static function createFromJson(string $json): self + { + $data = json_decode($json, true); + if (!is_array($data)) { + throw new InvalidArgumentException('Invalid argument.'); + } + + return self::createFromKeyData($data); + } + + /** + * Returns an array of keys stored in the key set. + * + * @return JWK[] + */ + public function all(): array + { + return $this->keys; + } + + /** + * Add key to store in the key set. + * This method is immutable and will return a new object. + * + * @return JWKSet + */ + public function with(JWK $jwk): self + { + $clone = clone $this; + + if ($jwk->has('kid')) { + $clone->keys[$jwk->get('kid')] = $jwk; + } else { + $clone->keys[] = $jwk; + } + + return $clone; + } + + /** + * Remove key from the key set. + * This method is immutable and will return a new object. + * + * @param int|string $key Key to remove from the key set + * + * @return JWKSet + */ + public function without($key): self + { + if (!$this->has($key)) { + return $this; + } + + $clone = clone $this; + unset($clone->keys[$key]); + + return $clone; + } + + /** + * Returns true if the key set contains a key with the given index. + * + * @param int|string $index + */ + public function has($index): bool + { + return array_key_exists($index, $this->keys); + } + + /** + * Returns the key with the given index. Throws an exception if the index is not present in the key store. + * + * @param int|string $index + * + * @throws InvalidArgumentException if the index is not defined + */ + public function get($index): JWK + { + if (!$this->has($index)) { + throw new InvalidArgumentException('Undefined index.'); + } + + return $this->keys[$index]; + } + + /** + * Returns the values to be serialized. + */ + public function jsonSerialize(): array + { + return ['keys' => array_values($this->keys)]; + } + + /** + * Returns the number of keys in the key set. + * + * @param int $mode + */ + public function count($mode = COUNT_NORMAL): int + { + return count($this->keys, $mode); + } + + /** + * Try to find a key that fits on the selected requirements. + * Returns null if not found. + * + * @param string $type Must be 'sig' (signature) or 'enc' (encryption) + * @param null|Algorithm $algorithm Specifies the algorithm to be used + * @param array $restrictions More restrictions such as 'kid' or 'kty' + * + * @throws InvalidArgumentException if the key type is not valid (must be "sig" or "enc") + */ + public function selectKey(string $type, ?Algorithm $algorithm = null, array $restrictions = []): ?JWK + { + if (!in_array($type, ['enc', 'sig'], true)) { + throw new InvalidArgumentException('Allowed key types are "sig" or "enc".'); + } + + $result = []; + foreach ($this->keys as $key) { + $ind = 0; + + $can_use = $this->canKeyBeUsedFor($type, $key); + if (false === $can_use) { + continue; + } + $ind += $can_use; + + $alg = $this->canKeyBeUsedWithAlgorithm($algorithm, $key); + if (false === $alg) { + continue; + } + $ind += $alg; + + if (false === $this->doesKeySatisfyRestrictions($restrictions, $key)) { + continue; + } + + $result[] = ['key' => $key, 'ind' => $ind]; + } + + if (0 === count($result)) { + return null; + } + + usort($result, [$this, 'sortKeys']); + + return $result[0]['key']; + } + + /** + * Internal method only. Should not be used. + * + * @internal + * @internal + */ + public static function sortKeys(array $a, array $b): int + { + if ($a['ind'] === $b['ind']) { + return 0; + } + + return ($a['ind'] > $b['ind']) ? -1 : 1; + } + + /** + * Internal method only. Should not be used. + * + * @internal + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->keys); + } + + /** + * @throws InvalidArgumentException if the key does not fulfill with the "key_ops" constraint + * + * @return bool|int + */ + private function canKeyBeUsedFor(string $type, JWK $key) + { + if ($key->has('use')) { + return $type === $key->get('use') ? 1 : false; + } + if ($key->has('key_ops')) { + $key_ops = $key->get('key_ops'); + if (!is_array($key_ops)) { + throw new InvalidArgumentException('Invalid key parameter "key_ops". Should be a list of key operations'); + } + + return $type === self::convertKeyOpsToKeyUse($key_ops) ? 1 : false; + } + + return 0; + } + + /** + * @return bool|int + */ + private function canKeyBeUsedWithAlgorithm(?Algorithm $algorithm, JWK $key) + { + if (null === $algorithm) { + return 0; + } + if (!in_array($key->get('kty'), $algorithm->allowedKeyTypes(), true)) { + return false; + } + if ($key->has('alg')) { + return $algorithm->name() === $key->get('alg') ? 2 : false; + } + + return 1; + } + + private function doesKeySatisfyRestrictions(array $restrictions, JWK $key): bool + { + foreach ($restrictions as $k => $v) { + if (!$key->has($k) || $v !== $key->get($k)) { + return false; + } + } + + return true; + } + + /** + * @throws InvalidArgumentException if the key operation is not supported + */ + private static function convertKeyOpsToKeyUse(array $key_ops): string + { + switch (true) { + case in_array('verify', $key_ops, true): + case in_array('sign', $key_ops, true): + return 'sig'; + + case in_array('encrypt', $key_ops, true): + case in_array('decrypt', $key_ops, true): + case in_array('wrapKey', $key_ops, true): + case in_array('unwrapKey', $key_ops, true): + case in_array('deriveKey', $key_ops, true): + case in_array('deriveBits', $key_ops, true): + return 'enc'; + + default: + throw new InvalidArgumentException(sprintf('Unsupported key operation value "%s"', implode(', ', $key_ops))); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWT.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWT.php new file mode 100644 index 00000000..d3a6065f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/JWT.php @@ -0,0 +1,23 @@ +value = $value; + } + + /** + * @return BigInteger + */ + public static function createFromBinaryString(string $value): self + { + $res = unpack('H*', $value); + if (false === $res) { + throw new InvalidArgumentException('Unable to convert the value'); + } + $data = current($res); + + return new self(BrickBigInteger::fromBase($data, 16)); + } + + /** + * @return BigInteger + */ + public static function createFromDecimal(int $value): self + { + return new self(BrickBigInteger::of($value)); + } + + /** + * @return BigInteger + */ + public static function createFromBigInteger(BrickBigInteger $value): self + { + return new self($value); + } + + /** + * Converts a BigInteger to a binary string. + */ + public function toBytes(): string + { + if ($this->value->isEqualTo(BrickBigInteger::zero())) { + return ''; + } + + $temp = $this->value->toBase(16); + $temp = 0 !== (mb_strlen($temp, '8bit') & 1) ? '0'.$temp : $temp; + $temp = hex2bin($temp); + if (false === $temp) { + throw new InvalidArgumentException('Unable to convert the value into bytes'); + } + + return ltrim($temp, chr(0)); + } + + /** + * Adds two BigIntegers. + * + * @param BigInteger $y + * + * @return BigInteger + */ + public function add(self $y): self + { + $value = $this->value->plus($y->value); + + return new self($value); + } + + /** + * Subtracts two BigIntegers. + * + * @param BigInteger $y + * + * @return BigInteger + */ + public function subtract(self $y): self + { + $value = $this->value->minus($y->value); + + return new self($value); + } + + /** + * Multiplies two BigIntegers. + * + * @param BigInteger $x + * + * @return BigInteger + */ + public function multiply(self $x): self + { + $value = $this->value->multipliedBy($x->value); + + return new self($value); + } + + /** + * Divides two BigIntegers. + * + * @param BigInteger $x + * + * @return BigInteger + */ + public function divide(self $x): self + { + $value = $this->value->dividedBy($x->value); + + return new self($value); + } + + /** + * Performs modular exponentiation. + * + * @param BigInteger $e + * @param BigInteger $n + * + * @return BigInteger + */ + public function modPow(self $e, self $n): self + { + $value = $this->value->modPow($e->value, $n->value); + + return new self($value); + } + + /** + * Performs modular exponentiation. + * + * @param BigInteger $d + * + * @return BigInteger + */ + public function mod(self $d): self + { + $value = $this->value->mod($d->value); + + return new self($value); + } + + public function modInverse(BigInteger $m): BigInteger + { + return new self($this->value->modInverse($m->value)); + } + + /** + * Compares two numbers. + * + * @param BigInteger $y + */ + public function compare(self $y): int + { + return $this->value->compareTo($y->value); + } + + /** + * @param BigInteger $y + */ + public function equals(self $y): bool + { + return $this->value->isEqualTo($y->value); + } + + /** + * @param BigInteger $y + * + * @return BigInteger + */ + public static function random(self $y): self + { + return new self(BrickBigInteger::randomRange(0, $y->value)); + } + + /** + * @param BigInteger $y + * + * @return BigInteger + */ + public function gcd(self $y): self + { + return new self($this->value->gcd($y->value)); + } + + /** + * @param BigInteger $y + */ + public function lowerThan(self $y): bool + { + return $this->value->isLessThan($y->value); + } + + public function isEven(): bool + { + return $this->value->isEven(); + } + + public function get(): BrickBigInteger + { + return $this->value; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECKey.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECKey.php new file mode 100644 index 00000000..3e05827a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECKey.php @@ -0,0 +1,366 @@ +has('d')) { + return self::convertPrivateKeyToPEM($jwk); + } + + return self::convertPublicKeyToPEM($jwk); + } + + /** + * @throws InvalidArgumentException if the curve is not supported + */ + public static function convertPublicKeyToPEM(JWK $jwk): string + { + switch ($jwk->get('crv')) { + case 'P-256': + $der = self::p256PublicKey(); + + break; + + case 'secp256k1': + $der = self::p256KPublicKey(); + + break; + + case 'P-384': + $der = self::p384PublicKey(); + + break; + + case 'P-521': + $der = self::p521PublicKey(); + + break; + + default: + throw new InvalidArgumentException('Unsupported curve.'); + } + $der .= self::getKey($jwk); + $pem = '-----BEGIN PUBLIC KEY-----'.PHP_EOL; + $pem .= chunk_split(base64_encode($der), 64, PHP_EOL); + $pem .= '-----END PUBLIC KEY-----'.PHP_EOL; + + return $pem; + } + + /** + * @throws InvalidArgumentException if the curve is not supported + */ + public static function convertPrivateKeyToPEM(JWK $jwk): string + { + switch ($jwk->get('crv')) { + case 'P-256': + $der = self::p256PrivateKey($jwk); + + break; + + case 'secp256k1': + $der = self::p256KPrivateKey($jwk); + + break; + + case 'P-384': + $der = self::p384PrivateKey($jwk); + + break; + + case 'P-521': + $der = self::p521PrivateKey($jwk); + + break; + + default: + throw new InvalidArgumentException('Unsupported curve.'); + } + $der .= self::getKey($jwk); + $pem = '-----BEGIN EC PRIVATE KEY-----'.PHP_EOL; + $pem .= chunk_split(base64_encode($der), 64, PHP_EOL); + $pem .= '-----END EC PRIVATE KEY-----'.PHP_EOL; + + return $pem; + } + + /** + * Creates a EC key with the given curve and additional values. + * + * @param string $curve The curve + * @param array $values values to configure the key + */ + public static function createECKey(string $curve, array $values = []): JWK + { + $jwk = self::createECKeyUsingOpenSSL($curve); + $values = array_merge($values, $jwk); + + return new JWK($values); + } + + /** + * @throws InvalidArgumentException if the curve is not supported + */ + private static function getNistCurveSize(string $curve): int + { + switch ($curve) { + case 'P-256': + case 'secp256k1': + return 256; + + case 'P-384': + return 384; + + case 'P-521': + return 521; + + default: + throw new InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve)); + } + } + + /** + * @throws RuntimeException if the extension OpenSSL is not available + * @throws RuntimeException if the key cannot be created + */ + private static function createECKeyUsingOpenSSL(string $curve): array + { + if (!extension_loaded('openssl')) { + throw new RuntimeException('Please install the OpenSSL extension'); + } + $key = openssl_pkey_new([ + 'curve_name' => self::getOpensslCurveName($curve), + 'private_key_type' => OPENSSL_KEYTYPE_EC, + ]); + if (false === $key) { + throw new RuntimeException('Unable to create the key'); + } + $result = openssl_pkey_export($key, $out); + if (false === $result) { + throw new RuntimeException('Unable to create the key'); + } + $res = openssl_pkey_get_private($out); + if (false === $res) { + throw new RuntimeException('Unable to create the key'); + } + $details = openssl_pkey_get_details($res); + if (false === $details) { + throw new InvalidArgumentException('Unable to get the key details'); + } + $nistCurveSize = self::getNistCurveSize($curve); + + return [ + 'kty' => 'EC', + 'crv' => $curve, + 'd' => Base64Url::encode(str_pad($details['ec']['d'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)), + 'x' => Base64Url::encode(str_pad($details['ec']['x'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)), + 'y' => Base64Url::encode(str_pad($details['ec']['y'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)), + ]; + } + + /** + * @throws InvalidArgumentException if the curve is not supported + */ + private static function getOpensslCurveName(string $curve): string + { + switch ($curve) { + case 'P-256': + return 'prime256v1'; + + case 'secp256k1': + return 'secp256k1'; + + case 'P-384': + return 'secp384r1'; + + case 'P-521': + return 'secp521r1'; + + default: + throw new InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve)); + } + } + + private static function p256PublicKey(): string + { + return pack( + 'H*', + '3059' // SEQUENCE, length 89 + .'3013' // SEQUENCE, length 19 + .'0607' // OID, length 7 + .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key + .'0608' // OID, length 8 + .'2a8648ce3d030107' // 1.2.840.10045.3.1.7 = P-256 Curve + .'0342' // BIT STRING, length 66 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function p256KPublicKey(): string + { + return pack( + 'H*', + '3056' // SEQUENCE, length 86 + .'3010' // SEQUENCE, length 16 + .'0607' // OID, length 7 + .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key + .'0605' // OID, length 8 + .'2B8104000A' // 1.3.132.0.10 secp256k1 + .'0342' // BIT STRING, length 66 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function p384PublicKey(): string + { + return pack( + 'H*', + '3076' // SEQUENCE, length 118 + .'3010' // SEQUENCE, length 16 + .'0607' // OID, length 7 + .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key + .'0605' // OID, length 5 + .'2b81040022' // 1.3.132.0.34 = P-384 Curve + .'0362' // BIT STRING, length 98 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function p521PublicKey(): string + { + return pack( + 'H*', + '30819b' // SEQUENCE, length 154 + .'3010' // SEQUENCE, length 16 + .'0607' // OID, length 7 + .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key + .'0605' // OID, length 5 + .'2b81040023' // 1.3.132.0.35 = P-521 Curve + .'038186' // BIT STRING, length 134 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function p256PrivateKey(JWK $jwk): string + { + $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 32, "\0", STR_PAD_LEFT)); + if (!is_array($d) || !isset($d[1])) { + throw new InvalidArgumentException('Unable to get the private key'); + } + + return pack( + 'H*', + '3077' // SEQUENCE, length 87+length($d)=32 + .'020101' // INTEGER, 1 + .'0420' // OCTET STRING, length($d) = 32 + .$d[1] + .'a00a' // TAGGED OBJECT #0, length 10 + .'0608' // OID, length 8 + .'2a8648ce3d030107' // 1.3.132.0.34 = P-256 Curve + .'a144' // TAGGED OBJECT #1, length 68 + .'0342' // BIT STRING, length 66 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function p256KPrivateKey(JWK $jwk): string + { + $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 32, "\0", STR_PAD_LEFT)); + if (!is_array($d) || !isset($d[1])) { + throw new InvalidArgumentException('Unable to get the private key'); + } + + return pack( + 'H*', + '3074' // SEQUENCE, length 84+length($d)=32 + .'020101' // INTEGER, 1 + .'0420' // OCTET STRING, length($d) = 32 + .$d[1] + .'a007' // TAGGED OBJECT #0, length 7 + .'0605' // OID, length 5 + .'2b8104000a' // 1.3.132.0.10 secp256k1 + .'a144' // TAGGED OBJECT #1, length 68 + .'0342' // BIT STRING, length 66 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function p384PrivateKey(JWK $jwk): string + { + $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 48, "\0", STR_PAD_LEFT)); + if (!is_array($d) || !isset($d[1])) { + throw new InvalidArgumentException('Unable to get the private key'); + } + + return pack( + 'H*', + '3081a4' // SEQUENCE, length 116 + length($d)=48 + .'020101' // INTEGER, 1 + .'0430' // OCTET STRING, length($d) = 30 + .$d[1] + .'a007' // TAGGED OBJECT #0, length 7 + .'0605' // OID, length 5 + .'2b81040022' // 1.3.132.0.34 = P-384 Curve + .'a164' // TAGGED OBJECT #1, length 100 + .'0362' // BIT STRING, length 98 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function p521PrivateKey(JWK $jwk): string + { + $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 66, "\0", STR_PAD_LEFT)); + if (!is_array($d) || !isset($d[1])) { + throw new InvalidArgumentException('Unable to get the private key'); + } + + return pack( + 'H*', + '3081dc' // SEQUENCE, length 154 + length($d)=66 + .'020101' // INTEGER, 1 + .'0442' // OCTET STRING, length(d) = 66 + .$d[1] + .'a007' // TAGGED OBJECT #0, length 7 + .'0605' // OID, length 5 + .'2b81040023' // 1.3.132.0.35 = P-521 Curve + .'a18189' // TAGGED OBJECT #1, length 137 + .'038186' // BIT STRING, length 134 + .'00' // prepend with NUL - pubkey will follow + ); + } + + private static function getKey(JWK $jwk): string + { + $nistCurveSize = self::getNistCurveSize($jwk->get('crv')); + $length = (int) ceil($nistCurveSize / 8); + + return + "\04" + .str_pad(Base64Url::decode($jwk->get('x')), $length, "\0", STR_PAD_LEFT) + .str_pad(Base64Url::decode($jwk->get('y')), $length, "\0", STR_PAD_LEFT); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECSignature.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECSignature.php new file mode 100644 index 00000000..763d8cd0 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/ECSignature.php @@ -0,0 +1,143 @@ + self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : ''; + + $bin = hex2bin( + self::ASN1_SEQUENCE + .$lengthPrefix.dechex($totalLength) + .self::ASN1_INTEGER.dechex($lengthR).$pointR + .self::ASN1_INTEGER.dechex($lengthS).$pointS + ); + if (!is_string($bin)) { + throw new InvalidArgumentException('Unable to parse the data'); + } + + return $bin; + } + + /** + * @throws InvalidArgumentException if the signature is not an ASN.1 sequence + */ + public static function fromAsn1(string $signature, int $length): string + { + $message = bin2hex($signature); + $position = 0; + + if (self::ASN1_SEQUENCE !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { + throw new InvalidArgumentException('Invalid data. Should start with a sequence.'); + } + + if (self::ASN1_LENGTH_2BYTES === self::readAsn1Content($message, $position, self::BYTE_SIZE)) { + $position += self::BYTE_SIZE; + } + + $pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); + $pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); + + $bin = hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT).str_pad($pointS, $length, '0', STR_PAD_LEFT)); + if (!is_string($bin)) { + throw new InvalidArgumentException('Unable to parse the data'); + } + + return $bin; + } + + private static function octetLength(string $data): int + { + return (int) (mb_strlen($data, '8bit') / self::BYTE_SIZE); + } + + private static function preparePositiveInteger(string $data): string + { + if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) { + return self::ASN1_NEGATIVE_INTEGER.$data; + } + + while (0 === mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit') + && mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT) { + $data = mb_substr($data, 2, null, '8bit'); + } + + return $data; + } + + private static function readAsn1Content(string $message, int &$position, int $length): string + { + $content = mb_substr($message, $position, $length, '8bit'); + $position += $length; + + return $content; + } + + /** + * @throws InvalidArgumentException if the data is not an integer + */ + private static function readAsn1Integer(string $message, int &$position): string + { + if (self::ASN1_INTEGER !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { + throw new InvalidArgumentException('Invalid data. Should contain an integer.'); + } + + $length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE)); + + return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE); + } + + private static function retrievePositiveInteger(string $data): string + { + while (0 === mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit') + && mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) { + $data = mb_substr($data, 2, null, '8bit'); + } + + return $data; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/Hash.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/Hash.php new file mode 100644 index 00000000..ef038c53 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/Hash.php @@ -0,0 +1,103 @@ +hash = $hash; + $this->length = $length; + $this->t = $t; + } + + /** + * @return Hash + */ + public static function sha1(): self + { + return new self('sha1', 20, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14"); + } + + /** + * @return Hash + */ + public static function sha256(): self + { + return new self('sha256', 32, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"); + } + + /** + * @return Hash + */ + public static function sha384(): self + { + return new self('sha384', 48, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30"); + } + + /** + * @return Hash + */ + public static function sha512(): self + { + return new self('sha512', 64, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40"); + } + + public function getLength(): int + { + return $this->length; + } + + /** + * Compute the HMAC. + */ + public function hash(string $text): string + { + return hash($this->hash, $text, true); + } + + public function name(): string + { + return $this->hash; + } + + public function t(): string + { + return $this->t; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/JsonConverter.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/JsonConverter.php new file mode 100644 index 00000000..259083d7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/JsonConverter.php @@ -0,0 +1,55 @@ +getCode(), $throwable); + } + } + + /** + * @throws RuntimeException if the payload cannot be decoded + * + * @return mixed + */ + public static function decode(string $payload) + { + try { + return json_decode($payload, true, 512, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } catch (Throwable $throwable) { + throw new RuntimeException('Invalid content.', $throwable->getCode(), $throwable); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/KeyChecker.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/KeyChecker.php new file mode 100644 index 00000000..30ae84bc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/KeyChecker.php @@ -0,0 +1,121 @@ +has('use')) { + self::checkUsage($key, $usage); + } + if ($key->has('key_ops')) { + self::checkOperation($key, $usage); + } + } + + /** + * @throws InvalidArgumentException if the key is not suitable for the selected algorithm + */ + public static function checkKeyAlgorithm(JWK $key, string $algorithm): void + { + if (!$key->has('alg')) { + return; + } + if ($key->get('alg') !== $algorithm) { + throw new InvalidArgumentException(sprintf('Key is only allowed for algorithm "%s".', $key->get('alg'))); + } + } + + /** + * @throws InvalidArgumentException if the key is not suitable for the selected operation + */ + private static function checkOperation(JWK $key, string $usage): void + { + $ops = $key->get('key_ops'); + if (!is_array($ops)) { + throw new InvalidArgumentException('Invalid key parameter "key_ops". Should be a list of key operations'); + } + + switch ($usage) { + case 'verification': + if (!in_array('verify', $ops, true)) { + throw new InvalidArgumentException('Key cannot be used to verify a signature'); + } + + break; + + case 'signature': + if (!in_array('sign', $ops, true)) { + throw new InvalidArgumentException('Key cannot be used to sign'); + } + + break; + + case 'encryption': + if (!in_array('encrypt', $ops, true) && !in_array('wrapKey', $ops, true) && !in_array('deriveKey', $ops, true)) { + throw new InvalidArgumentException('Key cannot be used to encrypt'); + } + + break; + + case 'decryption': + if (!in_array('decrypt', $ops, true) && !in_array('unwrapKey', $ops, true) && !in_array('deriveBits', $ops, true)) { + throw new InvalidArgumentException('Key cannot be used to decrypt'); + } + + break; + + default: + throw new InvalidArgumentException('Unsupported key usage.'); + } + } + + /** + * @throws InvalidArgumentException if the key is not suitable for the selected operation + */ + private static function checkUsage(JWK $key, string $usage): void + { + $use = $key->get('use'); + + switch ($usage) { + case 'verification': + case 'signature': + if ('sig' !== $use) { + throw new InvalidArgumentException('Key cannot be used to sign or verify a signature.'); + } + + break; + + case 'encryption': + case 'decryption': + if ('enc' !== $use) { + throw new InvalidArgumentException('Key cannot be used to encrypt or decrypt.'); + } + + break; + + default: + throw new InvalidArgumentException('Unsupported key usage.'); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/RSAKey.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/RSAKey.php new file mode 100644 index 00000000..843ba4c3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/Util/RSAKey.php @@ -0,0 +1,315 @@ +values = $data->all(); + $this->populateBigIntegers(); + $this->private = array_key_exists('d', $this->values); + } + + /** + * @return RSAKey + */ + public static function createFromJWK(JWK $jwk): self + { + return new self($jwk); + } + + public function getModulus(): BigInteger + { + return $this->modulus; + } + + public function getModulusLength(): int + { + return $this->modulus_length; + } + + public function getExponent(): BigInteger + { + $d = $this->getPrivateExponent(); + if (null !== $d) { + return $d; + } + + return $this->getPublicExponent(); + } + + public function getPublicExponent(): BigInteger + { + return $this->public_exponent; + } + + public function getPrivateExponent(): ?BigInteger + { + return $this->private_exponent; + } + + /** + * @return BigInteger[] + */ + public function getPrimes(): array + { + return $this->primes; + } + + /** + * @return BigInteger[] + */ + public function getExponents(): array + { + return $this->exponents; + } + + public function getCoefficient(): ?BigInteger + { + return $this->coefficient; + } + + public function isPublic(): bool + { + return !array_key_exists('d', $this->values); + } + + /** + * @param RSAKey $private + * + * @return RSAKey + */ + public static function toPublic(self $private): self + { + $data = $private->toArray(); + $keys = ['p', 'd', 'q', 'dp', 'dq', 'qi']; + foreach ($keys as $key) { + if (array_key_exists($key, $data)) { + unset($data[$key]); + } + } + + return new self(new JWK($data)); + } + + public function toArray(): array + { + return $this->values; + } + + public function toPEM(): string + { + if (null === $this->sequence) { + $this->sequence = new Sequence(); + if (array_key_exists('d', $this->values)) { + $this->initPrivateKey(); + } else { + $this->initPublicKey(); + } + } + $result = '-----BEGIN '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL; + $result .= chunk_split(base64_encode($this->sequence->getBinary()), 64, PHP_EOL); + $result .= '-----END '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL; + + return $result; + } + + /** + * Exponentiate with or without Chinese Remainder Theorem. + * Operation with primes 'p' and 'q' is appox. 2x faster. + * + * @param RSAKey $key + * + * @throws RuntimeException if the exponentiation cannot be achieved + */ + public static function exponentiate(self $key, BigInteger $c): BigInteger + { + if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare($key->getModulus()) > 0) { + throw new RuntimeException(); + } + if ($key->isPublic() || null === $key->getCoefficient() || 0 === count($key->getPrimes()) || 0 === count($key->getExponents())) { + return $c->modPow($key->getExponent(), $key->getModulus()); + } + + $p = $key->getPrimes()[0]; + $q = $key->getPrimes()[1]; + $dP = $key->getExponents()[0]; + $dQ = $key->getExponents()[1]; + $qInv = $key->getCoefficient(); + + $m1 = $c->modPow($dP, $p); + $m2 = $c->modPow($dQ, $q); + $h = $qInv->multiply($m1->subtract($m2)->add($p))->mod($p); + + return $m2->add($h->multiply($q)); + } + + private function populateBigIntegers(): void + { + $this->modulus = $this->convertBase64StringToBigInteger($this->values['n']); + $this->modulus_length = mb_strlen($this->getModulus()->toBytes(), '8bit'); + $this->public_exponent = $this->convertBase64StringToBigInteger($this->values['e']); + + if (!$this->isPublic()) { + $this->private_exponent = $this->convertBase64StringToBigInteger($this->values['d']); + + if (array_key_exists('p', $this->values) && array_key_exists('q', $this->values)) { + $this->primes = [ + $this->convertBase64StringToBigInteger($this->values['p']), + $this->convertBase64StringToBigInteger($this->values['q']), + ]; + if (array_key_exists('dp', $this->values) && array_key_exists('dq', $this->values) && array_key_exists('qi', $this->values)) { + $this->exponents = [ + $this->convertBase64StringToBigInteger($this->values['dp']), + $this->convertBase64StringToBigInteger($this->values['dq']), + ]; + $this->coefficient = $this->convertBase64StringToBigInteger($this->values['qi']); + } + } + } + } + + private function convertBase64StringToBigInteger(string $value): BigInteger + { + return BigInteger::createFromBinaryString(Base64Url::decode($value)); + } + + private function initPublicKey(): void + { + $oid_sequence = new Sequence(); + $oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1')); + $oid_sequence->addChild(new NullObject()); + $this->sequence->addChild($oid_sequence); + $n = new Integer($this->fromBase64ToInteger($this->values['n'])); + $e = new Integer($this->fromBase64ToInteger($this->values['e'])); + $key_sequence = new Sequence(); + $key_sequence->addChild($n); + $key_sequence->addChild($e); + $key_bit_string = new BitString(bin2hex($key_sequence->getBinary())); + $this->sequence->addChild($key_bit_string); + } + + private function initPrivateKey(): void + { + $this->sequence->addChild(new Integer(0)); + $oid_sequence = new Sequence(); + $oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1')); + $oid_sequence->addChild(new NullObject()); + $this->sequence->addChild($oid_sequence); + $v = new Integer(0); + $n = new Integer($this->fromBase64ToInteger($this->values['n'])); + $e = new Integer($this->fromBase64ToInteger($this->values['e'])); + $d = new Integer($this->fromBase64ToInteger($this->values['d'])); + $p = new Integer($this->fromBase64ToInteger($this->values['p'])); + $q = new Integer($this->fromBase64ToInteger($this->values['q'])); + $dp = array_key_exists('dp', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dp'])) : new Integer(0); + $dq = array_key_exists('dq', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dq'])) : new Integer(0); + $qi = array_key_exists('qi', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['qi'])) : new Integer(0); + $key_sequence = new Sequence(); + $key_sequence->addChild($v); + $key_sequence->addChild($n); + $key_sequence->addChild($e); + $key_sequence->addChild($d); + $key_sequence->addChild($p); + $key_sequence->addChild($q); + $key_sequence->addChild($dp); + $key_sequence->addChild($dq); + $key_sequence->addChild($qi); + $key_octet_string = new OctetString(bin2hex($key_sequence->getBinary())); + $this->sequence->addChild($key_octet_string); + } + + /** + * @param string $value + * + * @return string + */ + private function fromBase64ToInteger($value) + { + $unpacked = unpack('H*', Base64Url::decode($value)); + if (!is_array($unpacked) || 0 === count($unpacked)) { + throw new InvalidArgumentException('Unable to get the private key'); + } + + return \Brick\Math\BigInteger::fromBase(current($unpacked), 16)->toBase(10); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/composer.json b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/composer.json new file mode 100644 index 00000000..30bf70fa --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-core/composer.json @@ -0,0 +1,33 @@ +{ + "name": "web-token/jwt-core", + "description": "Core component of the JWT Framework.", + "type": "library", + "license": "MIT", + "keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"], + "homepage": "https://github.com/web-token", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + },{ + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "autoload": { + "psr-4": { + "Jose\\Component\\Core\\": "" + } + }, + "require": { + "php": ">=7.2", + "ext-json": "*", + "ext-mbstring": "*", + "brick/math": "^0.8.17|^0.9", + "fgrosse/phpasn1": "^2.0", + "spomky-labs/base64url": "^1.0|^2.0" + }, + "conflict": { + "spomky-labs/jose": "*" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/CONTRIBUTING.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/CONTRIBUTING.md new file mode 100644 index 00000000..fc360e5d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contributing + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. +Please do not submit any Pull Requests here. It will be automatically closed. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/FUNDING.yml b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/FUNDING.yml new file mode 100644 index 00000000..7e2ca0e7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: FlorentMorselli diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/PULL_REQUEST_TEMPLATE.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..d4ff96cb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ +Please do not submit any Pull Requests here. It will be automatically closed. + +You should submit it here: https://github.com/web-token/jwt-framework/pulls diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/AlgorithmAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/AlgorithmAnalyzer.php new file mode 100644 index 00000000..edb88888 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/AlgorithmAnalyzer.php @@ -0,0 +1,26 @@ +has('alg')) { + $bag->add(Message::medium('The parameter "alg" should be added.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES256KeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES256KeyAnalyzer.php new file mode 100644 index 00000000..2b7b71c4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES256KeyAnalyzer.php @@ -0,0 +1,61 @@ +get('kty')) { + return; + } + if (!$jwk->has('crv')) { + $bag->add(Message::high('Invalid key. The components "crv" is missing.')); + + return; + } + if ('P-256' !== $jwk->get('crv')) { + return; + } + $x = Base64Url::decode($jwk->get('x')); + $xLength = 8 * mb_strlen($x, '8bit'); + $y = Base64Url::decode($jwk->get('y')); + $yLength = 8 * mb_strlen($y, '8bit'); + if ($yLength !== $xLength || 256 !== $yLength) { + $bag->add(Message::high('Invalid key. The components "x" and "y" size shall be 256 bits.')); + } + $xBI = BigInteger::fromBase(bin2hex($x), 16); + $yBI = BigInteger::fromBase(bin2hex($y), 16); + $curve = NistCurve::curve256(); + if (!$curve->contains($xBI, $yBI)) { + $bag->add(Message::high('Invalid key. The point is not on the curve.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES384KeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES384KeyAnalyzer.php new file mode 100644 index 00000000..70bd52c5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES384KeyAnalyzer.php @@ -0,0 +1,61 @@ +get('kty')) { + return; + } + if (!$jwk->has('crv')) { + $bag->add(Message::high('Invalid key. The components "crv" is missing.')); + + return; + } + if ('P-384' !== $jwk->get('crv')) { + return; + } + $x = Base64Url::decode($jwk->get('x')); + $xLength = 8 * mb_strlen($x, '8bit'); + $y = Base64Url::decode($jwk->get('y')); + $yLength = 8 * mb_strlen($y, '8bit'); + if ($yLength !== $xLength || 384 !== $yLength) { + $bag->add(Message::high('Invalid key. The components "x" and "y" size shall be 384 bits.')); + } + $xBI = BigInteger::fromBase(bin2hex($x), 16); + $yBI = BigInteger::fromBase(bin2hex($y), 16); + $curve = NistCurve::curve384(); + if (!$curve->contains($xBI, $yBI)) { + $bag->add(Message::high('Invalid key. The point is not on the curve.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES512KeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES512KeyAnalyzer.php new file mode 100644 index 00000000..b729dee2 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ES512KeyAnalyzer.php @@ -0,0 +1,61 @@ +get('kty')) { + return; + } + if (!$jwk->has('crv')) { + $bag->add(Message::high('Invalid key. The components "crv" is missing.')); + + return; + } + if ('P-521' !== $jwk->get('crv')) { + return; + } + $x = Base64Url::decode($jwk->get('x')); + $xLength = 8 * mb_strlen($x, '8bit'); + $y = Base64Url::decode($jwk->get('y')); + $yLength = 8 * mb_strlen($y, '8bit'); + if ($yLength !== $xLength || 528 !== $yLength) { + $bag->add(Message::high('Invalid key. The components "x" and "y" size shall be 528 bits.')); + } + $xBI = BigInteger::fromBase(bin2hex($x), 16); + $yBI = BigInteger::fromBase(bin2hex($y), 16); + $curve = NistCurve::curve521(); + if (!$curve->contains($xBI, $yBI)) { + $bag->add(Message::high('Invalid key. The point is not on the curve.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS256KeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS256KeyAnalyzer.php new file mode 100644 index 00000000..4e4e4851 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS256KeyAnalyzer.php @@ -0,0 +1,35 @@ +get('kty')) { + return; + } + if (!$jwk->has('alg') || 'HS256' !== $jwk->get('alg')) { + return; + } + $k = Base64Url::decode($jwk->get('k')); + $kLength = 8 * mb_strlen($k, '8bit'); + if ($kLength < 256) { + $bag->add(Message::high('HS256 algorithm requires at least 256 bits key length.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS384KeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS384KeyAnalyzer.php new file mode 100644 index 00000000..75174e96 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS384KeyAnalyzer.php @@ -0,0 +1,35 @@ +get('kty')) { + return; + } + if (!$jwk->has('alg') || 'HS384' !== $jwk->get('alg')) { + return; + } + $k = Base64Url::decode($jwk->get('k')); + $kLength = 8 * mb_strlen($k, '8bit'); + if ($kLength < 384) { + $bag->add(Message::high('HS384 algorithm requires at least 384 bits key length.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS512KeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS512KeyAnalyzer.php new file mode 100644 index 00000000..1147aecc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/HS512KeyAnalyzer.php @@ -0,0 +1,35 @@ +get('kty')) { + return; + } + if (!$jwk->has('alg') || 'HS512' !== $jwk->get('alg')) { + return; + } + $k = Base64Url::decode($jwk->get('k')); + $kLength = 8 * mb_strlen($k, '8bit'); + if ($kLength < 512) { + $bag->add(Message::high('HS512 algorithm requires at least 512 bits key length.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzer.php new file mode 100644 index 00000000..978c57d9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyAnalyzer.php @@ -0,0 +1,24 @@ +analyzers[] = $analyzer; + } + + /** + * This method will analyze the JWK object using all analyzers. + * It returns a message bag that may contains messages. + */ + public function analyze(JWK $jwk): MessageBag + { + $bag = new MessageBag(); + foreach ($this->analyzers as $analyzer) { + $analyzer->analyze($jwk, $bag); + } + + return $bag; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyIdentifierAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyIdentifierAnalyzer.php new file mode 100644 index 00000000..a4e7708b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeyIdentifierAnalyzer.php @@ -0,0 +1,26 @@ +has('kid')) { + $bag->add(Message::medium('The parameter "kid" should be added.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzer.php new file mode 100644 index 00000000..6447e103 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/KeysetAnalyzer.php @@ -0,0 +1,24 @@ +analyzers[] = $analyzer; + } + + /** + * This method will analyze the JWKSet object using all analyzers. + * It returns a message bag that may contains messages. + */ + public function analyze(JWKSet $jwkset): MessageBag + { + $bag = new MessageBag(); + foreach ($this->analyzers as $analyzer) { + $analyzer->analyze($jwkset, $bag); + } + + return $bag; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/Message.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/Message.php new file mode 100644 index 00000000..19653cae --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/Message.php @@ -0,0 +1,97 @@ +message = $message; + $this->severity = $severity; + } + + /** + * Creates a message with severity=low. + * + * @return Message + */ + public static function low(string $message): self + { + return new self($message, self::SEVERITY_LOW); + } + + /** + * Creates a message with severity=medium. + * + * @return Message + */ + public static function medium(string $message): self + { + return new self($message, self::SEVERITY_MEDIUM); + } + + /** + * Creates a message with severity=high. + * + * @return Message + */ + public static function high(string $message): self + { + return new self($message, self::SEVERITY_HIGH); + } + + /** + * Returns the message. + */ + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns the severity of the message. + */ + public function getSeverity(): string + { + return $this->severity; + } + + public function jsonSerialize(): array + { + return [ + 'message' => $this->message, + 'severity' => $this->severity, + ]; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MessageBag.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MessageBag.php new file mode 100644 index 00000000..515ac7fd --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MessageBag.php @@ -0,0 +1,71 @@ +messages[] = $message; + } + + /** + * Returns all messages. + * + * @return Message[] + */ + public function all(): array + { + return $this->messages; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize(): array + { + return array_values($this->messages); + } + + /** + * {@inheritdoc} + */ + public function count(): int + { + return count($this->messages); + } + + /** + * {@inheritdoc} + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->messages); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedKeyTypes.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedKeyTypes.php new file mode 100644 index 00000000..af8e1e06 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedKeyTypes.php @@ -0,0 +1,49 @@ +count()) { + return; + } + + $hasSymmetricKeys = false; + $hasAsymmetricKeys = false; + + foreach ($jwkset as $jwk) { + switch ($jwk->get('kty')) { + case 'oct': + $hasSymmetricKeys = true; + + break; + + case 'OKP': + case 'RSA': + case 'EC': + $hasAsymmetricKeys = true; + + break; + } + } + + if ($hasAsymmetricKeys && $hasSymmetricKeys) { + $bag->add(Message::medium('This key set mixes symmetric and assymetric keys.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedPublicAndPrivateKeys.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedPublicAndPrivateKeys.php new file mode 100644 index 00000000..94ce3519 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/MixedPublicAndPrivateKeys.php @@ -0,0 +1,48 @@ +count()) { + return; + } + + $hasPublicKeys = false; + $hasPrivateKeys = false; + + foreach ($jwkset as $jwk) { + switch ($jwk->get('kty')) { + case 'OKP': + case 'RSA': + case 'EC': + if ($jwk->has('d')) { + $hasPrivateKeys = true; + } else { + $hasPublicKeys = true; + } + + break; + } + } + + if ($hasPrivateKeys && $hasPublicKeys) { + $bag->add(Message::high('This key set mixes public and private keys.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/NoneAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/NoneAnalyzer.php new file mode 100644 index 00000000..38b33f28 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/NoneAnalyzer.php @@ -0,0 +1,28 @@ +get('kty')) { + return; + } + + $bag->add(Message::high('This key is a meant to be used with the algorithm "none". This algorithm is not secured and should be used with care.')); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/OctAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/OctAnalyzer.php new file mode 100644 index 00000000..70a4761a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/OctAnalyzer.php @@ -0,0 +1,32 @@ +get('kty')) { + return; + } + $k = Base64Url::decode($jwk->get('k')); + $kLength = 8 * mb_strlen($k, '8bit'); + if ($kLength < 128) { + $bag->add(Message::high('The key length is less than 128 bits.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/RsaAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/RsaAnalyzer.php new file mode 100644 index 00000000..2a5743bf --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/RsaAnalyzer.php @@ -0,0 +1,54 @@ +get('kty')) { + return; + } + + $this->checkExponent($jwk, $bag); + $this->checkModulus($jwk, $bag); + } + + private function checkExponent(JWK $jwk, MessageBag $bag): void + { + $exponent = unpack('l', str_pad(Base64Url::decode($jwk->get('e')), 4, "\0")); + if (!is_array($exponent) || !isset($exponent[1])) { + throw new InvalidArgumentException('Unable to get the private key'); + } + if ($exponent[1] < 65537) { + $bag->add(Message::high('The exponent is too low. It should be at least 65537.')); + } + } + + private function checkModulus(JWK $jwk, MessageBag $bag): void + { + $n = 8 * mb_strlen(Base64Url::decode($jwk->get('n')), '8bit'); + if ($n < 2048) { + $bag->add(Message::high('The key length is less than 2048 bits.')); + } + if ($jwk->has('d') && (!$jwk->has('p') || !$jwk->has('q') || !$jwk->has('dp') || !$jwk->has('dq') || !$jwk->has('p') || !$jwk->has('qi'))) { + $bag->add(Message::medium('The key is a private RSA key, but Chinese Remainder Theorem primes are missing. These primes are not mandatory, but signatures and decryption processes are faster when available.')); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/UsageAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/UsageAnalyzer.php new file mode 100644 index 00000000..2edb19fe --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/UsageAnalyzer.php @@ -0,0 +1,32 @@ +has('use')) { + $bag->add(Message::medium('The parameter "use" should be added.')); + } elseif (!in_array($jwk->get('use'), ['sig', 'enc'], true)) { + $bag->add(Message::high(sprintf('The parameter "use" has an unsupported value "%s". Please use "sig" (signature) or "enc" (encryption).', $jwk->get('use')))); + } + if ($jwk->has('key_ops') && !in_array($jwk->get('key_ops'), ['sign', 'verify', 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], true)) { + $bag->add(Message::high(sprintf('The parameter "key_ops" has an unsupported value "%s". Please use one of the following values: %s.', $jwk->get('use'), implode(', ', ['verify', 'sign', 'encryp', 'decrypt', 'wrapKey', 'unwrapKey'])))); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ZxcvbnKeyAnalyzer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ZxcvbnKeyAnalyzer.php new file mode 100644 index 00000000..66a0457d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/Analyzer/ZxcvbnKeyAnalyzer.php @@ -0,0 +1,48 @@ +get('kty')) { + return; + } + $k = Base64Url::decode($jwk->get('k')); + if (class_exists(Zxcvbn::class)) { + $zxcvbn = new Zxcvbn(); + $strength = $zxcvbn->passwordStrength($k); + + switch (true) { + case $strength['score'] < 3: + $bag->add(Message::high('The octet string is weak and easily guessable. Please change your key as soon as possible.')); + + break; + + case 3 === $strength['score']: + $bag->add(Message::medium('The octet string is safe, but a longer key is preferable.')); + + break; + + default: + break; + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JKUFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JKUFactory.php new file mode 100644 index 00000000..6f404c7f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JKUFactory.php @@ -0,0 +1,39 @@ +getContent($url, $header); + $data = JsonConverter::decode($content); + if (!is_array($data)) { + throw new RuntimeException('Invalid content.'); + } + + return JWKSet::createFromKeyData($data); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JWKFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JWKFactory.php new file mode 100644 index 00000000..4620089e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/JWKFactory.php @@ -0,0 +1,328 @@ + $size) { + throw new InvalidArgumentException('Key length is too short. It needs to be at least 512 bits.'); + } + + $key = openssl_pkey_new([ + 'private_key_bits' => $size, + 'private_key_type' => OPENSSL_KEYTYPE_RSA, + ]); + if (false === $key) { + throw new InvalidArgumentException('Unable to create the key'); + } + $details = openssl_pkey_get_details($key); + if (!is_array($details)) { + throw new InvalidArgumentException('Unable to create the key'); + } + $rsa = RSAKey::createFromKeyDetails($details['rsa']); + $values = array_merge( + $values, + $rsa->toArray() + ); + + return new JWK($values); + } + + /** + * Creates a EC key with the given curve and additional values. + * + * @param string $curve The curve + * @param array $values values to configure the key + */ + public static function createECKey(string $curve, array $values = []): JWK + { + return ECKey::createECKey($curve, $values); + } + + /** + * Creates a octet key with the given key size and additional values. + * + * @param int $size The key size in bits + * @param array $values values to configure the key + * + * @throws InvalidArgumentException if the key has an invalid size + */ + public static function createOctKey(int $size, array $values = []): JWK + { + if (0 !== $size % 8) { + throw new InvalidArgumentException('Invalid key size.'); + } + $values = array_merge( + $values, + [ + 'kty' => 'oct', + 'k' => Base64Url::encode(random_bytes($size / 8)), + ] + ); + + return new JWK($values); + } + + /** + * Creates a OKP key with the given curve and additional values. + * + * @param string $curve The curve + * @param array $values values to configure the key + * + * @throws InvalidArgumentException if the extension "sobium" is not available + * @throws InvalidArgumentException if the curve is not supported + */ + public static function createOKPKey(string $curve, array $values = []): JWK + { + if (!extension_loaded('sodium')) { + throw new RuntimeException('The extension "sodium" is not available. Please install it to use this method'); + } + + switch ($curve) { + case 'X25519': + $keyPair = sodium_crypto_box_keypair(); + $secret = sodium_crypto_box_secretkey($keyPair); + $x = sodium_crypto_box_publickey($keyPair); + + break; + + case 'Ed25519': + $keyPair = sodium_crypto_sign_keypair(); + $secret = sodium_crypto_sign_secretkey($keyPair); + $x = sodium_crypto_sign_publickey($keyPair); + + break; + + default: + throw new InvalidArgumentException(sprintf('Unsupported "%s" curve', $curve)); + } + $secretLength = mb_strlen($secret, '8bit'); + $d = mb_substr($secret, 0, -$secretLength / 2, '8bit'); + + $values = array_merge( + $values, + [ + 'kty' => 'OKP', + 'crv' => $curve, + 'd' => Base64Url::encode($d), + 'x' => Base64Url::encode($x), + ] + ); + + return new JWK($values); + } + + /** + * Creates a none key with the given additional values. + * Please note that this key type is not pat of any specification. + * It is used to prevent the use of the "none" algorithm with other key types. + * + * @param array $values values to configure the key + */ + public static function createNoneKey(array $values = []): JWK + { + $values = array_merge( + $values, + [ + 'kty' => 'none', + 'alg' => 'none', + 'use' => 'sig', + ] + ); + + return new JWK($values); + } + + /** + * Creates a key from a Json string. + * + * @throws InvalidArgumentException if the key or keyset is not valid + * + * @return JWK|JWKSet + */ + public static function createFromJsonObject(string $value) + { + $json = json_decode($value, true); + if (!is_array($json)) { + throw new InvalidArgumentException('Invalid key or key set.'); + } + + return self::createFromValues($json); + } + + /** + * Creates a key or key set from the given input. + * + * @return JWK|JWKSet + */ + public static function createFromValues(array $values) + { + if (array_key_exists('keys', $values) && is_array($values['keys'])) { + return JWKSet::createFromKeyData($values); + } + + return new JWK($values); + } + + /** + * This method create a JWK object using a shared secret. + */ + public static function createFromSecret(string $secret, array $additional_values = []): JWK + { + $values = array_merge( + $additional_values, + [ + 'kty' => 'oct', + 'k' => Base64Url::encode($secret), + ] + ); + + return new JWK($values); + } + + /** + * This method will try to load a X.509 certificate and convert it into a public key. + */ + public static function createFromCertificateFile(string $file, array $additional_values = []): JWK + { + $values = KeyConverter::loadKeyFromCertificateFile($file); + $values = array_merge($values, $additional_values); + + return new JWK($values); + } + + /** + * Extract a keyfrom a key set identified by the given index . + * + * @param int|string $index + */ + public static function createFromKeySet(JWKSet $jwkset, $index): JWK + { + return $jwkset->get($index); + } + + /** + * This method will try to load a PKCS#12 file and convert it into a public key. + * + * @throws InvalidArgumentException if the certificate cannot be loaded + */ + public static function createFromPKCS12CertificateFile(string $file, ?string $secret = '', array $additional_values = []): JWK + { + try { + $content = file_get_contents($file); + if (!is_string($content)) { + throw new RuntimeException('Unable to read the file.'); + } + openssl_pkcs12_read($content, $certs, $secret); + } catch (Throwable $throwable) { + throw new RuntimeException('Unable to load the certificates.', $throwable->getCode(), $throwable); + } + if (!is_array($certs) || !array_key_exists('pkey', $certs)) { + throw new RuntimeException('Unable to load the certificates.'); + } + + return self::createFromKey($certs['pkey'], null, $additional_values); + } + + /** + * This method will try to convert a X.509 certificate into a public key. + */ + public static function createFromCertificate(string $certificate, array $additional_values = []): JWK + { + $values = KeyConverter::loadKeyFromCertificate($certificate); + $values = array_merge($values, $additional_values); + + return new JWK($values); + } + + /** + * This method will try to convert a X.509 certificate resource into a public key. + * + * @param resource $res + */ + public static function createFromX509Resource($res, array $additional_values = []): JWK + { + $values = KeyConverter::loadKeyFromX509Resource($res); + $values = array_merge($values, $additional_values); + + return new JWK($values); + } + + /** + * This method will try to load and convert a key file into a JWK object. + * If the key is encrypted, the password must be set. + */ + public static function createFromKeyFile(string $file, ?string $password = null, array $additional_values = []): JWK + { + $values = KeyConverter::loadFromKeyFile($file, $password); + $values = array_merge($values, $additional_values); + + return new JWK($values); + } + + /** + * This method will try to load and convert a key into a JWK object. + * If the key is encrypted, the password must be set. + */ + public static function createFromKey(string $key, ?string $password = null, array $additional_values = []): JWK + { + $values = KeyConverter::loadFromKey($key, $password); + $values = array_merge($values, $additional_values); + + return new JWK($values); + } + + /** + * This method will try to load and convert a X.509 certificate chain into a public key. + * + * Be careful! The certificate chain is loaded, but it is NOT VERIFIED by any mean! + * It is mandatory to verify the root CA or intermediate CA are trusted. + * If not done, it may lead to potential security issues. + */ + public static function createFromX5C(array $x5c, array $additional_values = []): JWK + { + $values = KeyConverter::loadFromX5C($x5c); + $values = array_merge($values, $additional_values); + + return new JWK($values); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/ECKey.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/ECKey.php new file mode 100644 index 00000000..a93501b5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/ECKey.php @@ -0,0 +1,307 @@ +loadJWK($data); + } + + public static function createFromPEM(string $pem): self + { + $data = self::loadPEM($pem); + + return new self($data); + } + + /** + * @param ECKey $private + * + * @return ECKey + */ + public static function toPublic(self $private): self + { + $data = $private->toArray(); + if (array_key_exists('d', $data)) { + unset($data['d']); + } + + return new self($data); + } + + /** + * @return array + */ + public function toArray() + { + return $this->values; + } + + /** + * @throws InvalidArgumentException if the key cannot be loaded + * @throws ParserException if the key cannot be loaded + */ + private static function loadPEM(string $data): array + { + $data = base64_decode(preg_replace('#-.*-|\r|\n#', '', $data), true); + $asnObject = ASNObject::fromBinary($data); + if (!$asnObject instanceof Sequence) { + throw new InvalidArgumentException('Unable to load the key.'); + } + $children = $asnObject->getChildren(); + if (self::isPKCS8($children)) { + $children = self::loadPKCS8($children); + } + + if (4 === count($children)) { + return self::loadPrivatePEM($children); + } + if (2 === count($children)) { + return self::loadPublicPEM($children); + } + + throw new InvalidArgumentException('Unable to load the key.'); + } + + /** + * @param ASNObject[] $children + * + * @throws InvalidArgumentException if the key cannot be loaded + * @throws ParserException if the key cannot be loaded + */ + private static function loadPKCS8(array $children): array + { + $binary = hex2bin($children[2]->getContent()); + $asnObject = ASNObject::fromBinary($binary); + if (!$asnObject instanceof Sequence) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + return $asnObject->getChildren(); + } + + /** + * @throws InvalidArgumentException if the key cannot be loaded + */ + private static function loadPublicPEM(array $children): array + { + if (!$children[0] instanceof Sequence) { + throw new InvalidArgumentException('Unsupported key type.'); + } + + $sub = $children[0]->getChildren(); + if (!$sub[0] instanceof ObjectIdentifier) { + throw new InvalidArgumentException('Unsupported key type.'); + } + if ('1.2.840.10045.2.1' !== $sub[0]->getContent()) { + throw new InvalidArgumentException('Unsupported key type.'); + } + if (!$sub[1] instanceof ObjectIdentifier) { + throw new InvalidArgumentException('Unsupported key type.'); + } + if (!$children[1] instanceof BitString) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + $bits = $children[1]->getContent(); + $bits_length = mb_strlen($bits, '8bit'); + if (0 !== mb_strpos($bits, '04', 0, '8bit')) { + throw new InvalidArgumentException('Unsupported key type'); + } + + $values = ['kty' => 'EC']; + $values['crv'] = self::getCurve($sub[1]->getContent()); + + $xBin = hex2bin(mb_substr($bits, 2, ($bits_length - 2) / 2, '8bit')); + $yBin = hex2bin(mb_substr($bits, (int) (($bits_length - 2) / 2 + 2), ($bits_length - 2) / 2, '8bit')); + if (!is_string($xBin) || !is_string($yBin)) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + $values['x'] = Base64Url::encode($xBin); + $values['y'] = Base64Url::encode($yBin); + + return $values; + } + + /** + * @throws InvalidArgumentException if the OID is not supported + */ + private static function getCurve(string $oid): string + { + $curves = self::getSupportedCurves(); + $curve = array_search($oid, $curves, true); + if (!is_string($curve)) { + throw new InvalidArgumentException('Unsupported OID.'); + } + + return $curve; + } + + private static function getSupportedCurves(): array + { + return [ + 'P-256' => '1.2.840.10045.3.1.7', + 'P-384' => '1.3.132.0.34', + 'P-521' => '1.3.132.0.35', + ]; + } + + /** + * @throws InvalidArgumentException if the key cannot be loaded + */ + private static function verifyVersion(ASNObject $children): void + { + if (!$children instanceof Integer || '1' !== $children->getContent()) { + throw new InvalidArgumentException('Unable to load the key.'); + } + } + + /** + * @throws InvalidArgumentException if the key cannot be loaded + */ + private static function getXAndY(ASNObject $children, string &$x, string &$y): void + { + if (!$children instanceof ExplicitlyTaggedObject || !is_array($children->getContent())) { + throw new InvalidArgumentException('Unable to load the key.'); + } + if (!$children->getContent()[0] instanceof BitString) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + $bits = $children->getContent()[0]->getContent(); + $bits_length = mb_strlen($bits, '8bit'); + + if (0 !== mb_strpos($bits, '04', 0, '8bit')) { + throw new InvalidArgumentException('Unsupported key type'); + } + + $x = mb_substr($bits, 2, (int) (($bits_length - 2) / 2), '8bit'); + $y = mb_substr($bits, (int) (($bits_length - 2) / 2 + 2), (int) (($bits_length - 2) / 2), '8bit'); + } + + /** + * @throws InvalidArgumentException if the key cannot be loaded + */ + private static function getD(ASNObject $children): string + { + if (!$children instanceof OctetString) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + return $children->getContent(); + } + + /** + * @throws InvalidArgumentException if the key cannot be loaded + */ + private static function loadPrivatePEM(array $children): array + { + self::verifyVersion($children[0]); + $x = ''; + $y = ''; + $d = self::getD($children[1]); + self::getXAndY($children[3], $x, $y); + + if (!$children[2] instanceof ExplicitlyTaggedObject || !is_array($children[2]->getContent())) { + throw new InvalidArgumentException('Unable to load the key.'); + } + if (!$children[2]->getContent()[0] instanceof ObjectIdentifier) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + $curve = $children[2]->getContent()[0]->getContent(); + $dBin = hex2bin($d); + $xBin = hex2bin($x); + $yBin = hex2bin($y); + if (!is_string($dBin) || !is_string($xBin) || !is_string($yBin)) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + $values = ['kty' => 'EC']; + $values['crv'] = self::getCurve($curve); + $values['d'] = Base64Url::encode($dBin); + $values['x'] = Base64Url::encode($xBin); + $values['y'] = Base64Url::encode($yBin); + + return $values; + } + + /** + * @param ASNObject[] $children + */ + private static function isPKCS8(array $children): bool + { + if (3 !== count($children)) { + return false; + } + + $classes = [0 => Integer::class, 1 => Sequence::class, 2 => OctetString::class]; + foreach ($classes as $k => $class) { + if (!$children[$k] instanceof $class) { + return false; + } + } + + return true; + } + + /** + * @throws InvalidArgumentException if the key is invalid + */ + private function loadJWK(array $jwk): void + { + $keys = [ + 'kty' => 'The key parameter "kty" is missing.', + 'crv' => 'Curve parameter is missing', + 'x' => 'Point parameters are missing.', + 'y' => 'Point parameters are missing.', + ]; + foreach ($keys as $k => $v) { + if (!array_key_exists($k, $jwk)) { + throw new InvalidArgumentException($v); + } + } + + if ('EC' !== $jwk['kty']) { + throw new InvalidArgumentException('JWK is not an Elliptic Curve key.'); + } + $this->values = $jwk; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/KeyConverter.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/KeyConverter.php new file mode 100644 index 00000000..4b986f24 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/KeyConverter.php @@ -0,0 +1,272 @@ + $cert) { + $x5c[$id] = '-----BEGIN CERTIFICATE-----'.PHP_EOL.chunk_split($cert, 64, PHP_EOL).'-----END CERTIFICATE-----'; + $x509 = openssl_x509_read($x5c[$id]); + if (false === $x509) { + throw new InvalidArgumentException('Unable to load the certificate chain'); + } + $parsed = openssl_x509_parse($x509); + if (false === $parsed) { + throw new InvalidArgumentException('Unable to load the certificate chain'); + } + } + + return self::loadKeyFromCertificate(reset($x5c)); + } + + private static function loadKeyFromDER(string $der, ?string $password = null): array + { + $pem = self::convertDerToPem($der); + + return self::loadKeyFromPEM($pem, $password); + } + + /** + * @throws InvalidArgumentException if the OpenSSL extension is not available + * @throws InvalidArgumentException if the key cannot be loaded + */ + private static function loadKeyFromPEM(string $pem, ?string $password = null): array + { + if (1 === preg_match('#DEK-Info: (.+),(.+)#', $pem, $matches)) { + $pem = self::decodePem($pem, $matches, $password); + } + + if (!extension_loaded('openssl')) { + throw new RuntimeException('Please install the OpenSSL extension'); + } + self::sanitizePEM($pem); + $res = openssl_pkey_get_private($pem); + if (false === $res) { + $res = openssl_pkey_get_public($pem); + } + if (false === $res) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + $details = openssl_pkey_get_details($res); + if (!is_array($details) || !array_key_exists('type', $details)) { + throw new InvalidArgumentException('Unable to get details of the key'); + } + + switch ($details['type']) { + case OPENSSL_KEYTYPE_EC: + $ec_key = ECKey::createFromPEM($pem); + + return $ec_key->toArray(); + + case OPENSSL_KEYTYPE_RSA: + $rsa_key = RSAKey::createFromPEM($pem); + + return $rsa_key->toArray(); + + default: + throw new InvalidArgumentException('Unsupported key type'); + } + } + + /** + * This method modifies the PEM to get 64 char lines and fix bug with old OpenSSL versions. + */ + private static function sanitizePEM(string &$pem): void + { + preg_match_all('#(-.*-)#', $pem, $matches, PREG_PATTERN_ORDER); + $ciphertext = preg_replace('#-.*-|\r|\n| #', '', $pem); + + $pem = $matches[0][0].PHP_EOL; + $pem .= chunk_split($ciphertext, 64, PHP_EOL); + $pem .= $matches[0][1].PHP_EOL; + } + + /** + * @param string[] $matches + * + * @throws InvalidArgumentException if the password to decrypt the key is not provided + * @throws InvalidArgumentException if the key cannot be loaded + */ + private static function decodePem(string $pem, array $matches, ?string $password = null): string + { + if (null === $password) { + throw new InvalidArgumentException('Password required for encrypted keys.'); + } + + $iv = pack('H*', trim($matches[2])); + $iv_sub = mb_substr($iv, 0, 8, '8bit'); + $symkey = pack('H*', md5($password.$iv_sub)); + $symkey .= pack('H*', md5($symkey.$password.$iv_sub)); + $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $pem); + $ciphertext = base64_decode(preg_replace('#-.*-|\r|\n#', '', $key), true); + if (!is_string($ciphertext)) { + throw new InvalidArgumentException('Unable to encode the data.'); + } + + $decoded = openssl_decrypt($ciphertext, mb_strtolower($matches[1]), $symkey, OPENSSL_RAW_DATA, $iv); + if (false === $decoded) { + throw new RuntimeException('Unable to decrypt the key'); + } + $number = preg_match_all('#-{5}.*-{5}#', $pem, $result); + if (2 !== $number) { + throw new InvalidArgumentException('Unable to load the key'); + } + + $pem = $result[0][0].PHP_EOL; + $pem .= chunk_split(base64_encode($decoded), 64); + $pem .= $result[0][1].PHP_EOL; + + return $pem; + } + + private static function convertDerToPem(string $der_data): string + { + $pem = chunk_split(base64_encode($der_data), 64, PHP_EOL); + + return '-----BEGIN CERTIFICATE-----'.PHP_EOL.$pem.'-----END CERTIFICATE-----'.PHP_EOL; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/RSAKey.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/RSAKey.php new file mode 100644 index 00000000..a52eb642 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/KeyConverter/RSAKey.php @@ -0,0 +1,263 @@ +loadJWK($data); + } + + /** + * @return RSAKey + */ + public static function createFromKeyDetails(array $details): self + { + $values = ['kty' => 'RSA']; + $keys = [ + 'n' => 'n', + 'e' => 'e', + 'd' => 'd', + 'p' => 'p', + 'q' => 'q', + 'dp' => 'dmp1', + 'dq' => 'dmq1', + 'qi' => 'iqmp', + ]; + foreach ($details as $key => $value) { + if (in_array($key, $keys, true)) { + $value = Base64Url::encode($value); + $values[array_search($key, $keys, true)] = $value; + } + } + + return new self($values); + } + + /** + * @throws RuntimeException if the extension OpenSSL is not available + * @throws InvalidArgumentException if the key cannot be loaded + * + * @return RSAKey + */ + public static function createFromPEM(string $pem): self + { + if (!extension_loaded('openssl')) { + throw new RuntimeException('Please install the OpenSSL extension'); + } + $res = openssl_pkey_get_private($pem); + if (false === $res) { + $res = openssl_pkey_get_public($pem); + } + if (false === $res) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + $details = openssl_pkey_get_details($res); + if (!is_array($details) || !isset($details['rsa'])) { + throw new InvalidArgumentException('Unable to load the key.'); + } + + return self::createFromKeyDetails($details['rsa']); + } + + /** + * @return RSAKey + */ + public static function createFromJWK(JWK $jwk): self + { + return new self($jwk->all()); + } + + public function isPublic(): bool + { + return !array_key_exists('d', $this->values); + } + + /** + * @param RSAKey $private + * + * @return RSAKey + */ + public static function toPublic(self $private): self + { + $data = $private->toArray(); + $keys = ['p', 'd', 'q', 'dp', 'dq', 'qi']; + foreach ($keys as $key) { + if (array_key_exists($key, $data)) { + unset($data[$key]); + } + } + + return new self($data); + } + + public function toArray(): array + { + return $this->values; + } + + public function toJwk(): JWK + { + return new JWK($this->values); + } + + /** + * This method will try to add Chinese Remainder Theorem (CRT) parameters. + * With those primes, the decryption process is really fast. + */ + public function optimize(): void + { + if (array_key_exists('d', $this->values)) { + $this->populateCRT(); + } + } + + /** + * @throws InvalidArgumentException if the key is invalid or not an RSA key + */ + private function loadJWK(array $jwk): void + { + if (!array_key_exists('kty', $jwk)) { + throw new InvalidArgumentException('The key parameter "kty" is missing.'); + } + if ('RSA' !== $jwk['kty']) { + throw new InvalidArgumentException('The JWK is not a RSA key.'); + } + + $this->values = $jwk; + } + + /** + * This method adds Chinese Remainder Theorem (CRT) parameters if primes 'p' and 'q' are available. + * If 'p' and 'q' are missing, they are computed and added to the key data. + */ + private function populateCRT(): void + { + if (!array_key_exists('p', $this->values) && !array_key_exists('q', $this->values)) { + $d = BigInteger::createFromBinaryString(Base64Url::decode($this->values['d'])); + $e = BigInteger::createFromBinaryString(Base64Url::decode($this->values['e'])); + $n = BigInteger::createFromBinaryString(Base64Url::decode($this->values['n'])); + + [$p, $q] = $this->findPrimeFactors($d, $e, $n); + $this->values['p'] = Base64Url::encode($p->toBytes()); + $this->values['q'] = Base64Url::encode($q->toBytes()); + } + + if (array_key_exists('dp', $this->values) && array_key_exists('dq', $this->values) && array_key_exists('qi', $this->values)) { + return; + } + + $one = BigInteger::createFromDecimal(1); + $d = BigInteger::createFromBinaryString(Base64Url::decode($this->values['d'])); + $p = BigInteger::createFromBinaryString(Base64Url::decode($this->values['p'])); + $q = BigInteger::createFromBinaryString(Base64Url::decode($this->values['q'])); + + $this->values['dp'] = Base64Url::encode($d->mod($p->subtract($one))->toBytes()); + $this->values['dq'] = Base64Url::encode($d->mod($q->subtract($one))->toBytes()); + $this->values['qi'] = Base64Url::encode($q->modInverse($p)->toBytes()); + } + + /** + * @throws RuntimeException if the prime factors cannot be found + * + * @return BigInteger[] + */ + private function findPrimeFactors(BigInteger $d, BigInteger $e, BigInteger $n): array + { + $zero = BigInteger::createFromDecimal(0); + $one = BigInteger::createFromDecimal(1); + $two = BigInteger::createFromDecimal(2); + + $k = $d->multiply($e)->subtract($one); + + if ($k->isEven()) { + $r = $k; + $t = $zero; + + do { + $r = $r->divide($two); + $t = $t->add($one); + } while ($r->isEven()); + + $found = false; + $y = null; + + for ($i = 1; $i <= 100; ++$i) { + $g = BigInteger::random($n->subtract($one)); + $y = $g->modPow($r, $n); + + if ($y->equals($one) || $y->equals($n->subtract($one))) { + continue; + } + + for ($j = $one; $j->lowerThan($t->subtract($one)); $j = $j->add($one)) { + $x = $y->modPow($two, $n); + + if ($x->equals($one)) { + $found = true; + + break; + } + + if ($x->equals($n->subtract($one))) { + continue; + } + + $y = $x; + } + + $x = $y->modPow($two, $n); + if ($x->equals($one)) { + $found = true; + + break; + } + } + if (null === $y) { + throw new InvalidArgumentException('Unable to find prime factors.'); + } + if (true === $found) { + $p = $y->subtract($one)->gcd($n); + $q = $n->divide($p); + + return [$p, $q]; + } + } + + throw new InvalidArgumentException('Unable to find prime factors.'); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/LICENSE b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/LICENSE new file mode 100644 index 00000000..37cf976b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/README.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/README.md new file mode 100644 index 00000000..62651e50 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/README.md @@ -0,0 +1,15 @@ +PHP JWT Key Management Component +================================ + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. + +**Please do not submit any Pull Request here.** +You should go to [the main repository](https://github.com/web-token/jwt-framework) instead. + +# Documentation + +The official documentation is available as https://web-token.spomky-labs.com/ + +# Licence + +This software is release under [MIT licence](LICENSE). diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/UrlKeySetFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/UrlKeySetFactory.php new file mode 100644 index 00000000..e880fd6c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/UrlKeySetFactory.php @@ -0,0 +1,58 @@ +client = $client; + $this->requestFactory = $requestFactory; + } + + /** + * @throws RuntimeException if the response content is invalid + */ + protected function getContent(string $url, array $header = []): string + { + $request = $this->requestFactory->createRequest('GET', $url); + foreach ($header as $k => $v) { + $request = $request->withHeader($k, $v); + } + $response = $this->client->sendRequest($request); + + if ($response->getStatusCode() >= 400) { + throw new RuntimeException('Unable to get the key set.', $response->getStatusCode()); + } + + return $response->getBody()->getContents(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/X5UFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/X5UFactory.php new file mode 100644 index 00000000..8b81c995 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/X5UFactory.php @@ -0,0 +1,56 @@ +getContent($url, $header); + $data = JsonConverter::decode($content); + if (!is_array($data)) { + throw new RuntimeException('Invalid content.'); + } + + $keys = []; + foreach ($data as $kid => $cert) { + if (false === mb_strpos($cert, '-----BEGIN CERTIFICATE-----')) { + $cert = '-----BEGIN CERTIFICATE-----'.PHP_EOL.$cert.PHP_EOL.'-----END CERTIFICATE-----'; + } + $jwk = KeyConverter::loadKeyFromCertificate($cert); + if (is_string($kid)) { + $jwk['kid'] = $kid; + $keys[$kid] = new JWK($jwk); + } else { + $keys[] = new JWK($jwk); + } + } + + return new JWKSet($keys); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/composer.json b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/composer.json new file mode 100644 index 00000000..8a3cb323 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-key-mgmt/composer.json @@ -0,0 +1,34 @@ +{ + "name": "web-token/jwt-key-mgmt", + "description": "Key Management component of the JWT Framework.", + "type": "library", + "license": "MIT", + "keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"], + "homepage": "https://github.com/web-token", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + },{ + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-key-mgmt/contributors" + } + ], + "autoload": { + "psr-4": { + "Jose\\Component\\KeyManagement\\": "" + } + }, + "require": { + "ext-openssl": "*", + "psr/http-factory": "^1.0", + "psr/http-client": "^1.0", + "web-token/jwt-core": "^2.0" + }, + "suggest": { + "ext-sodium": "Sodium is required for OKP key creation, EdDSA signature algorithm and ECDH-ES key encryption with OKP keys", + "web-token/jwt-util-ecc": "To use EC key analyzers.", + "php-http/message-factory": "To enable JKU/X5U support.", + "php-http/httplug": "To enable JKU/X5U support." + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/CONTRIBUTING.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/CONTRIBUTING.md new file mode 100644 index 00000000..fc360e5d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contributing + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. +Please do not submit any Pull Requests here. It will be automatically closed. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/FUNDING.yml b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/FUNDING.yml new file mode 100644 index 00000000..7e2ca0e7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: FlorentMorselli diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/PULL_REQUEST_TEMPLATE.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..d4ff96cb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ +Please do not submit any Pull Requests here. It will be automatically closed. + +You should submit it here: https://github.com/web-token/jwt-framework/pulls diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ECDSA.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ECDSA.php new file mode 100644 index 00000000..75b28a26 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ECDSA.php @@ -0,0 +1,80 @@ +checkKey($key); + if (!$key->has('d')) { + throw new InvalidArgumentException('The EC key is not private'); + } + $pem = ECKey::convertPrivateKeyToPEM($key); + openssl_sign($input, $signature, $pem, $this->getHashAlgorithm()); + + return ECSignature::fromAsn1($signature, $this->getSignaturePartLength()); + } + + public function verify(JWK $key, string $input, string $signature): bool + { + $this->checkKey($key); + + try { + $der = ECSignature::toAsn1($signature, $this->getSignaturePartLength()); + $pem = ECKey::convertPublicKeyToPEM($key); + + return 1 === openssl_verify($input, $der, $pem, $this->getHashAlgorithm()); + } catch (Throwable $e) { + return false; + } + } + + abstract protected function getHashAlgorithm(): string; + + abstract protected function getSignaturePartLength(): int; + + private function checkKey(JWK $key): void + { + if (!in_array($key->get('kty'), $this->allowedKeyTypes(), true)) { + throw new InvalidArgumentException('Wrong key type.'); + } + foreach (['x', 'y', 'crv'] as $k) { + if (!$key->has($k)) { + throw new InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k)); + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ES256.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ES256.php new file mode 100644 index 00000000..1999e7d4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-ecdsa/ES256.php @@ -0,0 +1,32 @@ +checkKey($key); + if (!$key->has('d')) { + throw new InvalidArgumentException('The EC key is not private'); + } + $x = Base64Url::decode($key->get('x')); + $d = Base64Url::decode($key->get('d')); + $secret = $d.$x; + + switch ($key->get('crv')) { + case 'Ed25519': + return sodium_crypto_sign_detached($input, $secret); + + default: + throw new InvalidArgumentException('Unsupported curve'); + } + } + + /** + * @throws InvalidArgumentException if the curve is not supported + */ + public function verify(JWK $key, string $input, string $signature): bool + { + $this->checkKey($key); + + $public = Base64Url::decode($key->get('x')); + + switch ($key->get('crv')) { + case 'Ed25519': + return sodium_crypto_sign_verify_detached($signature, $input, $public); + + default: + throw new InvalidArgumentException('Unsupported curve'); + } + } + + public function name(): string + { + return 'EdDSA'; + } + + /** + * @throws InvalidArgumentException if the key type is not valid + * @throws InvalidArgumentException if a mandatory key parameter is missing + * @throws InvalidArgumentException if the curve is not suuported + */ + private function checkKey(JWK $key): void + { + if (!in_array($key->get('kty'), $this->allowedKeyTypes(), true)) { + throw new InvalidArgumentException('Wrong key type.'); + } + foreach (['x', 'crv'] as $k) { + if (!$key->has($k)) { + throw new InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k)); + } + } + if ('Ed25519' !== $key->get('crv')) { + throw new InvalidArgumentException('Unsupported curve.'); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/LICENSE b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/LICENSE new file mode 100644 index 00000000..37cf976b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/README.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/README.md new file mode 100644 index 00000000..39f21ff4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/README.md @@ -0,0 +1,15 @@ +EdDSA Based Signature Algorithms For JWT-Framework +================================================== + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. + +**Please do not submit any Pull Request here.** +You should go to [the main repository](https://github.com/web-token/jwt-framework) instead. + +# Documentation + +The official documentation is available as https://web-token.spomky-labs.com/ + +# Licence + +This software is release under [MIT licence](LICENSE). diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/composer.json b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/composer.json new file mode 100644 index 00000000..d1d45b40 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-eddsa/composer.json @@ -0,0 +1,26 @@ +{ + "name": "web-token/jwt-signature-algorithm-eddsa", + "description": "EdDSA Signature Algorithm the JWT Framework.", + "type": "library", + "license": "MIT", + "keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"], + "homepage": "https://github.com/web-token", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + },{ + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\Algorithm\\": "" + } + }, + "require": { + "ext-sodium": "*", + "web-token/jwt-signature": "^2.1" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/CONTRIBUTING.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/CONTRIBUTING.md new file mode 100644 index 00000000..fc360e5d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contributing + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. +Please do not submit any Pull Requests here. It will be automatically closed. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/FUNDING.yml b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/FUNDING.yml new file mode 100644 index 00000000..7e2ca0e7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: FlorentMorselli diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/PULL_REQUEST_TEMPLATE.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..d4ff96cb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ +Please do not submit any Pull Requests here. It will be automatically closed. + +You should submit it here: https://github.com/web-token/jwt-framework/pulls diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/LICENSE b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/LICENSE new file mode 100644 index 00000000..37cf976b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/PS256.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/PS256.php new file mode 100644 index 00000000..dfaabd58 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/PS256.php @@ -0,0 +1,27 @@ +checkKey($key); + $pub = RSAKey::createFromJWK($key->toPublic()); + + return JoseRSA::verify($pub, $input, $signature, $this->getAlgorithm(), $this->getSignatureMethod()); + } + + /** + * @throws InvalidArgumentException if the key is not private + */ + public function sign(JWK $key, string $input): string + { + $this->checkKey($key); + if (!$key->has('d')) { + throw new InvalidArgumentException('The key is not a private key.'); + } + + $priv = RSAKey::createFromJWK($key); + + return JoseRSA::sign($priv, $input, $this->getAlgorithm(), $this->getSignatureMethod()); + } + + abstract protected function getAlgorithm(): string; + + abstract protected function getSignatureMethod(): int; + + /** + * @throws InvalidArgumentException if the key type is not allowed + * @throws InvalidArgumentException if the key is invalid + */ + private function checkKey(JWK $key): void + { + if (!in_array($key->get('kty'), $this->allowedKeyTypes(), true)) { + throw new InvalidArgumentException('Wrong key type.'); + } + foreach (['n', 'e'] as $k) { + if (!$key->has($k)) { + throw new InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k)); + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPKCS1.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPKCS1.php new file mode 100644 index 00000000..da2fd807 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPKCS1.php @@ -0,0 +1,75 @@ +checkKey($key); + $pub = RSAKey::createFromJWK($key->toPublic()); + + return 1 === openssl_verify($input, $signature, $pub->toPEM(), $this->getAlgorithm()); + } + + /** + * @throws InvalidArgumentException if the key is not private + * @throws InvalidArgumentException if the data cannot be signed + */ + public function sign(JWK $key, string $input): string + { + $this->checkKey($key); + if (!$key->has('d')) { + throw new InvalidArgumentException('The key is not a private key.'); + } + + $priv = RSAKey::createFromJWK($key); + + $result = openssl_sign($input, $signature, $priv->toPEM(), $this->getAlgorithm()); + if (true !== $result) { + throw new RuntimeException('Unable to sign'); + } + + return $signature; + } + + abstract protected function getAlgorithm(): string; + + /** + * @throws InvalidArgumentException if the key type is not allowed + * @throws InvalidArgumentException if the key is not valid + */ + private function checkKey(JWK $key): void + { + if (!in_array($key->get('kty'), $this->allowedKeyTypes(), true)) { + throw new InvalidArgumentException('Wrong key type.'); + } + foreach (['n', 'e'] as $k) { + if (!$key->has($k)) { + throw new InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k)); + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPSS.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPSS.php new file mode 100644 index 00000000..9112c417 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/RSAPSS.php @@ -0,0 +1,69 @@ +checkKey($key); + $pub = RSAKey::createFromJWK($key->toPublic()); + + return JoseRSA::verify($pub, $input, $signature, $this->getAlgorithm(), JoseRSA::SIGNATURE_PSS); + } + + /** + * @throws InvalidArgumentException if the key is not private + */ + public function sign(JWK $key, string $input): string + { + $this->checkKey($key); + if (!$key->has('d')) { + throw new InvalidArgumentException('The key is not a private key.'); + } + + $priv = RSAKey::createFromJWK($key); + + return JoseRSA::sign($priv, $input, $this->getAlgorithm(), JoseRSA::SIGNATURE_PSS); + } + + abstract protected function getAlgorithm(): string; + + /** + * @throws InvalidArgumentException if the key type is not allowed + * @throws InvalidArgumentException if the key is not valid + */ + private function checkKey(JWK $key): void + { + if (!in_array($key->get('kty'), $this->allowedKeyTypes(), true)) { + throw new InvalidArgumentException('Wrong key type.'); + } + foreach (['n', 'e'] as $k) { + if (!$key->has($k)) { + throw new InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k)); + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/Util/RSA.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/Util/RSA.php new file mode 100644 index 00000000..b0f7e313 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/Util/RSA.php @@ -0,0 +1,251 @@ +toPEM(), $hash); + if (true !== $result) { + throw new RuntimeException('Unable to sign the data'); + } + + return $signature; + + default: + throw new InvalidArgumentException('Unsupported mode.'); + } + } + + /** + * Create a signature. + */ + public static function signWithPSS(RSAKey $key, string $message, string $hash): string + { + $em = self::encodeEMSAPSS($message, 8 * $key->getModulusLength() - 1, Hash::$hash()); + $message = BigInteger::createFromBinaryString($em); + $signature = RSAKey::exponentiate($key, $message); + + return self::convertIntegerToOctetString($signature, $key->getModulusLength()); + } + + /** + * Create a signature. + * + * @deprecated Please use openssl_sign + */ + public static function signWithPKCS15(RSAKey $key, string $message, string $hash): string + { + $em = self::encodeEMSA15($message, $key->getModulusLength(), Hash::$hash()); + $message = BigInteger::createFromBinaryString($em); + $signature = RSAKey::exponentiate($key, $message); + + return self::convertIntegerToOctetString($signature, $key->getModulusLength()); + } + + /** + * @throws InvalidArgumentException if the signature mode is not supported + */ + public static function verify(RSAKey $key, string $message, string $signature, string $hash, int $mode): bool + { + switch ($mode) { + case self::SIGNATURE_PSS: + return self::verifyWithPSS($key, $message, $signature, $hash); + + case self::SIGNATURE_PKCS1: + return 1 === openssl_verify($message, $signature, $key->toPEM(), $hash); + + default: + throw new InvalidArgumentException('Unsupported mode.'); + } + } + + /** + * Verifies a signature. + * + * @throws RuntimeException if the signature cannot be verified + */ + public static function verifyWithPSS(RSAKey $key, string $message, string $signature, string $hash): bool + { + if (mb_strlen($signature, '8bit') !== $key->getModulusLength()) { + throw new RuntimeException(); + } + $s2 = BigInteger::createFromBinaryString($signature); + $m2 = RSAKey::exponentiate($key, $s2); + $em = self::convertIntegerToOctetString($m2, $key->getModulusLength()); + $modBits = 8 * $key->getModulusLength(); + + return self::verifyEMSAPSS($message, $em, $modBits - 1, Hash::$hash()); + } + + /** + * Verifies a signature. + * + * @deprecated Please use openssl_sign + * + * @throws RuntimeException if the signature cannot be verified + */ + public static function verifyWithPKCS15(RSAKey $key, string $message, string $signature, string $hash): bool + { + if (mb_strlen($signature, '8bit') !== $key->getModulusLength()) { + throw new RuntimeException(); + } + $signature = BigInteger::createFromBinaryString($signature); + $m2 = RSAKey::exponentiate($key, $signature); + $em = self::convertIntegerToOctetString($m2, $key->getModulusLength()); + + return hash_equals($em, self::encodeEMSA15($message, $key->getModulusLength(), Hash::$hash())); + } + + /** + * @throws RuntimeException if the value cannot be converted + */ + private static function convertIntegerToOctetString(BigInteger $x, int $xLen): string + { + $x = $x->toBytes(); + if (mb_strlen($x, '8bit') > $xLen) { + throw new RuntimeException(); + } + + return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); + } + + /** + * MGF1. + */ + private static function getMGF1(string $mgfSeed, int $maskLen, Hash $mgfHash): string + { + $t = ''; + $count = ceil($maskLen / $mgfHash->getLength()); + for ($i = 0; $i < $count; ++$i) { + $c = pack('N', $i); + $t .= $mgfHash->hash($mgfSeed.$c); + } + + return mb_substr($t, 0, $maskLen, '8bit'); + } + + /** + * EMSA-PSS-ENCODE. + * + * @throws RuntimeException if the message length is invalid + */ + private static function encodeEMSAPSS(string $message, int $modulusLength, Hash $hash): string + { + $emLen = ($modulusLength + 1) >> 3; + $sLen = $hash->getLength(); + $mHash = $hash->hash($message); + if ($emLen <= $hash->getLength() + $sLen + 2) { + throw new RuntimeException(); + } + $salt = random_bytes($sLen); + $m2 = "\0\0\0\0\0\0\0\0".$mHash.$salt; + $h = $hash->hash($m2); + $ps = str_repeat(chr(0), $emLen - $sLen - $hash->getLength() - 2); + $db = $ps.chr(1).$salt; + $dbMask = self::getMGF1($h, $emLen - $hash->getLength() - 1, $hash); + $maskedDB = $db ^ $dbMask; + $maskedDB[0] = ~chr(0xFF << ($modulusLength & 7)) & $maskedDB[0]; + $em = $maskedDB.$h.chr(0xBC); + + return $em; + } + + /** + * EMSA-PSS-VERIFY. + * + * @throws InvalidArgumentException if the signature cannot be verified + */ + private static function verifyEMSAPSS(string $m, string $em, int $emBits, Hash $hash): bool + { + $emLen = ($emBits + 1) >> 3; + $sLen = $hash->getLength(); + $mHash = $hash->hash($m); + if ($emLen < $hash->getLength() + $sLen + 2) { + throw new InvalidArgumentException(); + } + if ($em[mb_strlen($em, '8bit') - 1] !== chr(0xBC)) { + throw new InvalidArgumentException(); + } + $maskedDB = mb_substr($em, 0, -$hash->getLength() - 1, '8bit'); + $h = mb_substr($em, -$hash->getLength() - 1, $hash->getLength(), '8bit'); + $temp = chr(0xFF << ($emBits & 7)); + if ((~$maskedDB[0] & $temp) !== $temp) { + throw new InvalidArgumentException(); + } + $dbMask = self::getMGF1($h, $emLen - $hash->getLength() - 1, $hash/*MGF*/); + $db = $maskedDB ^ $dbMask; + $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; + $temp = $emLen - $hash->getLength() - $sLen - 2; + if (mb_substr($db, 0, $temp, '8bit') !== str_repeat(chr(0), $temp)) { + throw new InvalidArgumentException(); + } + if (1 !== ord($db[$temp])) { + throw new InvalidArgumentException(); + } + $salt = mb_substr($db, $temp + 1, null, '8bit'); // should be $sLen long + $m2 = "\0\0\0\0\0\0\0\0".$mHash.$salt; + $h2 = $hash->hash($m2); + + return hash_equals($h, $h2); + } + + /** + * @throws RuntimeException if the value cannot be encoded + */ + private static function encodeEMSA15(string $m, int $emBits, Hash $hash): string + { + $h = $hash->hash($m); + $t = $hash->t(); + $t .= $h; + $tLen = mb_strlen($t, '8bit'); + if ($emBits < $tLen + 11) { + throw new RuntimeException(); + } + $ps = str_repeat(chr(0xFF), $emBits - $tLen - 3); + + return "\0\1{$ps}\0{$t}"; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/composer.json b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/composer.json new file mode 100644 index 00000000..eb57efa8 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature-algorithm-rsa/composer.json @@ -0,0 +1,31 @@ +{ + "name": "web-token/jwt-signature-algorithm-rsa", + "description": "RSA Based Signature Algorithms the JWT Framework.", + "type": "library", + "license": "MIT", + "keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"], + "homepage": "https://github.com/web-token", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + },{ + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\Algorithm\\": "" + } + }, + "require": { + "brick/math": "^0.8.17|^0.9", + "ext-openssl": "*", + "web-token/jwt-signature": "^2.1" + }, + "suggest": { + "ext-gmp": "GMP or BCMath is highly recommended to improve the library performance", + "ext-bcmath": "GMP or BCMath is highly recommended to improve the library performance" + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/CONTRIBUTING.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/CONTRIBUTING.md new file mode 100644 index 00000000..fc360e5d --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contributing + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. +Please do not submit any Pull Requests here. It will be automatically closed. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/FUNDING.yml b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/FUNDING.yml new file mode 100644 index 00000000..7e2ca0e7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: FlorentMorselli diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/PULL_REQUEST_TEMPLATE.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..d4ff96cb --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ +Please do not submit any Pull Requests here. It will be automatically closed. + +You should submit it here: https://github.com/web-token/jwt-framework/pulls diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Algorithm/MacAlgorithm.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Algorithm/MacAlgorithm.php new file mode 100644 index 00000000..2304b367 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Algorithm/MacAlgorithm.php @@ -0,0 +1,37 @@ +payload = $payload; + $this->encodedPayload = $encodedPayload; + $this->isPayloadDetached = $isPayloadDetached; + } + + public function getPayload(): ?string + { + return $this->payload; + } + + /** + * Returns true if the payload is detached. + */ + public function isPayloadDetached(): bool + { + return $this->isPayloadDetached; + } + + /** + * Returns the Base64Url encoded payload. + * If the payload is detached, this method returns null. + */ + public function getEncodedPayload(): ?string + { + if (true === $this->isPayloadDetached()) { + return null; + } + + return $this->encodedPayload; + } + + /** + * Returns the signatures associated with the JWS. + * + * @return Signature[] + */ + public function getSignatures(): array + { + return $this->signatures; + } + + /** + * Returns the signature at the given index. + * + * @throws InvalidArgumentException if the signature index does not exist + */ + public function getSignature(int $id): Signature + { + if (isset($this->signatures[$id])) { + return $this->signatures[$id]; + } + + throw new InvalidArgumentException('The signature does not exist.'); + } + + /** + * This method adds a signature to the JWS object. + * Its returns a new JWS object. + * + * @internal + * + * @return JWS + */ + public function addSignature(string $signature, array $protectedHeader, ?string $encodedProtectedHeader, array $header = []): self + { + $jws = clone $this; + $jws->signatures[] = new Signature($signature, $protectedHeader, $encodedProtectedHeader, $header); + + return $jws; + } + + /** + * Returns the number of signature associated with the JWS. + */ + public function countSignatures(): int + { + return count($this->signatures); + } + + /** + * This method splits the JWS into a list of JWSs. + * It is only useful when the JWS contains more than one signature (JSON General Serialization). + * + * @return JWS[] + */ + public function split(): array + { + $result = []; + foreach ($this->signatures as $signature) { + $jws = new self( + $this->payload, + $this->encodedPayload, + $this->isPayloadDetached + ); + $jws = $jws->addSignature( + $signature->getSignature(), + $signature->getProtectedHeader(), + $signature->getEncodedProtectedHeader(), + $signature->getHeader() + ); + + $result[] = $jws; + } + + return $result; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilder.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilder.php new file mode 100644 index 00000000..afffd12f --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilder.php @@ -0,0 +1,235 @@ +signatureAlgorithmManager = $signatureAlgorithmManager; + } + + /** + * Returns the algorithm manager associated to the builder. + */ + public function getSignatureAlgorithmManager(): AlgorithmManager + { + return $this->signatureAlgorithmManager; + } + + /** + * Reset the current data. + * + * @return JWSBuilder + */ + public function create(): self + { + $this->payload = null; + $this->isPayloadDetached = false; + $this->signatures = []; + $this->isPayloadEncoded = null; + + return $this; + } + + /** + * Set the payload. + * This method will return a new JWSBuilder object. + * + * @throws InvalidArgumentException if the payload is not UTF-8 encoded + * + * @return JWSBuilder + */ + public function withPayload(string $payload, bool $isPayloadDetached = false): self + { + if (false === mb_detect_encoding($payload, 'UTF-8', true)) { + throw new InvalidArgumentException('The payload must be encoded in UTF-8'); + } + $clone = clone $this; + $clone->payload = $payload; + $clone->isPayloadDetached = $isPayloadDetached; + + return $clone; + } + + /** + * Adds the information needed to compute the signature. + * This method will return a new JWSBuilder object. + * + * @throws InvalidArgumentException if the payload encoding is inconsistent + * + * @return JWSBuilder + */ + public function addSignature(JWK $signatureKey, array $protectedHeader, array $header = []): self + { + $this->checkB64AndCriticalHeader($protectedHeader); + $isPayloadEncoded = $this->checkIfPayloadIsEncoded($protectedHeader); + if (null === $this->isPayloadEncoded) { + $this->isPayloadEncoded = $isPayloadEncoded; + } elseif ($this->isPayloadEncoded !== $isPayloadEncoded) { + throw new InvalidArgumentException('Foreign payload encoding detected.'); + } + $this->checkDuplicatedHeaderParameters($protectedHeader, $header); + KeyChecker::checkKeyUsage($signatureKey, 'signature'); + $algorithm = $this->findSignatureAlgorithm($signatureKey, $protectedHeader, $header); + KeyChecker::checkKeyAlgorithm($signatureKey, $algorithm->name()); + $clone = clone $this; + $clone->signatures[] = [ + 'signature_algorithm' => $algorithm, + 'signature_key' => $signatureKey, + 'protected_header' => $protectedHeader, + 'header' => $header, + ]; + + return $clone; + } + + /** + * Computes all signatures and return the expected JWS object. + * + * @throws RuntimeException if the payload is not set + * @throws RuntimeException if no signature is defined + */ + public function build(): JWS + { + if (null === $this->payload) { + throw new RuntimeException('The payload is not set.'); + } + if (0 === count($this->signatures)) { + throw new RuntimeException('At least one signature must be set.'); + } + + $encodedPayload = false === $this->isPayloadEncoded ? $this->payload : Base64Url::encode($this->payload); + $jws = new JWS($this->payload, $encodedPayload, $this->isPayloadDetached); + foreach ($this->signatures as $signature) { + /** @var MacAlgorithm|SignatureAlgorithm $algorithm */ + $algorithm = $signature['signature_algorithm']; + /** @var JWK $signatureKey */ + $signatureKey = $signature['signature_key']; + /** @var array $protectedHeader */ + $protectedHeader = $signature['protected_header']; + /** @var array $header */ + $header = $signature['header']; + $encodedProtectedHeader = 0 === count($protectedHeader) ? null : Base64Url::encode(JsonConverter::encode($protectedHeader)); + $input = sprintf('%s.%s', $encodedProtectedHeader, $encodedPayload); + if ($algorithm instanceof SignatureAlgorithm) { + $s = $algorithm->sign($signatureKey, $input); + } else { + $s = $algorithm->hash($signatureKey, $input); + } + $jws = $jws->addSignature($s, $protectedHeader, $encodedProtectedHeader, $header); + } + + return $jws; + } + + private function checkIfPayloadIsEncoded(array $protectedHeader): bool + { + return !array_key_exists('b64', $protectedHeader) || true === $protectedHeader['b64']; + } + + /** + * @throws LogicException if the header parameter "crit" is missing, invalid or does not contain "b64" when "b64" is set + */ + private function checkB64AndCriticalHeader(array $protectedHeader): void + { + if (!array_key_exists('b64', $protectedHeader)) { + return; + } + if (!array_key_exists('crit', $protectedHeader)) { + throw new LogicException('The protected header parameter "crit" is mandatory when protected header parameter "b64" is set.'); + } + if (!is_array($protectedHeader['crit'])) { + throw new LogicException('The protected header parameter "crit" must be an array.'); + } + if (!in_array('b64', $protectedHeader['crit'], true)) { + throw new LogicException('The protected header parameter "crit" must contain "b64" when protected header parameter "b64" is set.'); + } + } + + /** + * @throws InvalidArgumentException if the header parameter "alg" is missing or the algorithm is not allowed/not supported + * + * @return MacAlgorithm|SignatureAlgorithm + */ + private function findSignatureAlgorithm(JWK $key, array $protectedHeader, array $header): Algorithm + { + $completeHeader = array_merge($header, $protectedHeader); + if (!array_key_exists('alg', $completeHeader)) { + throw new InvalidArgumentException('No "alg" parameter set in the header.'); + } + if ($key->has('alg') && $key->get('alg') !== $completeHeader['alg']) { + throw new InvalidArgumentException(sprintf('The algorithm "%s" is not allowed with this key.', $completeHeader['alg'])); + } + + $algorithm = $this->signatureAlgorithmManager->get($completeHeader['alg']); + if (!$algorithm instanceof SignatureAlgorithm && !$algorithm instanceof MacAlgorithm) { + throw new InvalidArgumentException(sprintf('The algorithm "%s" is not supported.', $completeHeader['alg'])); + } + + return $algorithm; + } + + /** + * @throws InvalidArgumentException if the header contains duplicated entries + */ + private function checkDuplicatedHeaderParameters(array $header1, array $header2): void + { + $inter = array_intersect_key($header1, $header2); + if (0 !== count($inter)) { + throw new InvalidArgumentException(sprintf('The header contains duplicated entries: %s.', implode(', ', array_keys($inter)))); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilderFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilderFactory.php new file mode 100644 index 00000000..dbdf115a --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSBuilderFactory.php @@ -0,0 +1,41 @@ +signatureAlgorithmManagerFactory = $signatureAlgorithmManagerFactory; + } + + /** + * This method creates a JWSBuilder using the given algorithm aliases. + * + * @param string[] $algorithms + */ + public function create(array $algorithms): JWSBuilder + { + $algorithmManager = $this->signatureAlgorithmManagerFactory->create($algorithms); + + return new JWSBuilder($algorithmManager); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoader.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoader.php new file mode 100644 index 00000000..f19b449e --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoader.php @@ -0,0 +1,124 @@ +serializerManager = $serializerManager; + $this->jwsVerifier = $jwsVerifier; + $this->headerCheckerManager = $headerCheckerManager; + } + + /** + * Returns the JWSVerifier associated to the JWSLoader. + */ + public function getJwsVerifier(): JWSVerifier + { + return $this->jwsVerifier; + } + + /** + * Returns the Header Checker Manager associated to the JWSLoader. + */ + public function getHeaderCheckerManager(): ?HeaderCheckerManager + { + return $this->headerCheckerManager; + } + + /** + * Returns the JWSSerializer associated to the JWSLoader. + */ + public function getSerializerManager(): JWSSerializerManager + { + return $this->serializerManager; + } + + /** + * This method will try to load and verify the token using the given key. + * It returns a JWS and will populate the $signature variable in case of success, otherwise an exception is thrown. + * + * @throws Exception if the token cannot be loaded or verified + */ + public function loadAndVerifyWithKey(string $token, JWK $key, ?int &$signature, ?string $payload = null): JWS + { + $keyset = new JWKSet([$key]); + + return $this->loadAndVerifyWithKeySet($token, $keyset, $signature, $payload); + } + + /** + * This method will try to load and verify the token using the given key set. + * It returns a JWS and will populate the $signature variable in case of success, otherwise an exception is thrown. + * + * @throws Exception if the token cannot be loaded or verified + */ + public function loadAndVerifyWithKeySet(string $token, JWKSet $keyset, ?int &$signature, ?string $payload = null): JWS + { + try { + $jws = $this->serializerManager->unserialize($token); + $nbSignatures = $jws->countSignatures(); + for ($i = 0; $i < $nbSignatures; ++$i) { + if ($this->processSignature($jws, $keyset, $i, $payload)) { + $signature = $i; + + return $jws; + } + } + } catch (Throwable $e) { + // Nothing to do. Exception thrown just after + } + + throw new Exception('Unable to load and verify the token.'); + } + + private function processSignature(JWS $jws, JWKSet $keyset, int $signature, ?string $payload): bool + { + try { + if (null !== $this->headerCheckerManager) { + $this->headerCheckerManager->check($jws, $signature); + } + + return $this->jwsVerifier->verifyWithKeySet($jws, $keyset, $signature, $payload); + } catch (Throwable $e) { + return false; + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoaderFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoaderFactory.php new file mode 100644 index 00000000..8f29650c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSLoaderFactory.php @@ -0,0 +1,59 @@ +jwsSerializerManagerFactory = $jwsSerializerManagerFactory; + $this->jwsVerifierFactory = $jwsVerifierFactory; + $this->headerCheckerManagerFactory = $headerCheckerManagerFactory; + } + + /** + * Creates a JWSLoader using the given serializer aliases, signature algorithm aliases and (optionally) + * the header checker aliases. + */ + public function create(array $serializers, array $algorithms, array $headerCheckers = []): JWSLoader + { + $serializerManager = $this->jwsSerializerManagerFactory->create($serializers); + $jwsVerifier = $this->jwsVerifierFactory->create($algorithms); + if (null !== $this->headerCheckerManagerFactory) { + $headerCheckerManager = $this->headerCheckerManagerFactory->create($headerCheckers); + } else { + $headerCheckerManager = null; + } + + return new JWSLoader($serializerManager, $jwsVerifier, $headerCheckerManager); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSTokenSupport.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSTokenSupport.php new file mode 100644 index 00000000..f2f586f3 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSTokenSupport.php @@ -0,0 +1,42 @@ + $jwt->countSignatures()) { + throw new InvalidArgumentException('Unknown signature index.'); + } + $protectedHeader = $jwt->getSignature($index)->getProtectedHeader(); + $unprotectedHeader = $jwt->getSignature($index)->getHeader(); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifier.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifier.php new file mode 100644 index 00000000..42d12a66 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifier.php @@ -0,0 +1,170 @@ +signatureAlgorithmManager = $signatureAlgorithmManager; + } + + /** + * Returns the algorithm manager associated to the JWSVerifier. + */ + public function getSignatureAlgorithmManager(): AlgorithmManager + { + return $this->signatureAlgorithmManager; + } + + /** + * This method will try to verify the JWS object using the given key and for the given signature. + * It returns true if the signature is verified, otherwise false. + * + * @return bool true if the verification of the signature succeeded, else false + */ + public function verifyWithKey(JWS $jws, JWK $jwk, int $signature, ?string $detachedPayload = null): bool + { + $jwkset = new JWKSet([$jwk]); + + return $this->verifyWithKeySet($jws, $jwkset, $signature, $detachedPayload); + } + + /** + * This method will try to verify the JWS object using the given key set and for the given signature. + * It returns true if the signature is verified, otherwise false. + * + * @param JWS $jws A JWS object + * @param JWKSet $jwkset The signature will be verified using keys in the key set + * @param JWK $jwk The key used to verify the signature in case of success + * @param null|string $detachedPayload If not null, the value must be the detached payload encoded in Base64 URL safe. If the input contains a payload, throws an exception. + * + * @throws InvalidArgumentException if there is no key in the keyset + * @throws InvalidArgumentException if the token does not contain any signature + * + * @return bool true if the verification of the signature succeeded, else false + */ + public function verifyWithKeySet(JWS $jws, JWKSet $jwkset, int $signatureIndex, ?string $detachedPayload = null, JWK &$jwk = null): bool + { + if (0 === $jwkset->count()) { + throw new InvalidArgumentException('There is no key in the key set.'); + } + if (0 === $jws->countSignatures()) { + throw new InvalidArgumentException('The JWS does not contain any signature.'); + } + $this->checkPayload($jws, $detachedPayload); + $signature = $jws->getSignature($signatureIndex); + + return $this->verifySignature($jws, $jwkset, $signature, $detachedPayload, $jwk); + } + + private function verifySignature(JWS $jws, JWKSet $jwkset, Signature $signature, ?string $detachedPayload = null, JWK &$successJwk = null): bool + { + $input = $this->getInputToVerify($jws, $signature, $detachedPayload); + $algorithm = $this->getAlgorithm($signature); + foreach ($jwkset->all() as $jwk) { + try { + KeyChecker::checkKeyUsage($jwk, 'verification'); + KeyChecker::checkKeyAlgorithm($jwk, $algorithm->name()); + if (true === $algorithm->verify($jwk, $input, $signature->getSignature())) { + $successJwk = $jwk; + + return true; + } + } catch (Throwable $e) { + //We do nothing, we continue with other keys + continue; + } + } + + return false; + } + + private function getInputToVerify(JWS $jws, Signature $signature, ?string $detachedPayload): string + { + $isPayloadEmpty = $this->isPayloadEmpty($jws->getPayload()); + $encodedProtectedHeader = $signature->getEncodedProtectedHeader(); + if (!$signature->hasProtectedHeaderParameter('b64') || true === $signature->getProtectedHeaderParameter('b64')) { + if (null !== $jws->getEncodedPayload()) { + return sprintf('%s.%s', $encodedProtectedHeader, $jws->getEncodedPayload()); + } + + $payload = $isPayloadEmpty ? $detachedPayload : $jws->getPayload(); + + return sprintf('%s.%s', $encodedProtectedHeader, Base64Url::encode($payload)); + } + + $payload = $isPayloadEmpty ? $detachedPayload : $jws->getPayload(); + + return sprintf('%s.%s', $encodedProtectedHeader, $payload); + } + + /** + * @throws InvalidArgumentException if the payload is set when a detached payload is provided or no payload is defined + */ + private function checkPayload(JWS $jws, ?string $detachedPayload = null): void + { + $isPayloadEmpty = $this->isPayloadEmpty($jws->getPayload()); + if (null !== $detachedPayload && !$isPayloadEmpty) { + throw new InvalidArgumentException('A detached payload is set, but the JWS already has a payload.'); + } + if ($isPayloadEmpty && null === $detachedPayload) { + throw new InvalidArgumentException('The JWS has a detached payload, but no payload is provided.'); + } + } + + /** + * @throws InvalidArgumentException if the header parameter "alg" is missing or invalid + * + * @return MacAlgorithm|SignatureAlgorithm + */ + private function getAlgorithm(Signature $signature): Algorithm + { + $completeHeader = array_merge($signature->getProtectedHeader(), $signature->getHeader()); + if (!isset($completeHeader['alg'])) { + throw new InvalidArgumentException('No "alg" parameter set in the header.'); + } + + $algorithm = $this->signatureAlgorithmManager->get($completeHeader['alg']); + if (!$algorithm instanceof SignatureAlgorithm && !$algorithm instanceof MacAlgorithm) { + throw new InvalidArgumentException(sprintf('The algorithm "%s" is not supported or is not a signature or MAC algorithm.', $completeHeader['alg'])); + } + + return $algorithm; + } + + private function isPayloadEmpty(?string $payload): bool + { + return null === $payload || '' === $payload; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifierFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifierFactory.php new file mode 100644 index 00000000..67a65e84 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/JWSVerifierFactory.php @@ -0,0 +1,41 @@ +algorithmManagerFactory = $algorithmManagerFactory; + } + + /** + * Creates a JWSVerifier using the given signature algorithm aliases. + * + * @param string[] $algorithms + */ + public function create(array $algorithms): JWSVerifier + { + $algorithmManager = $this->algorithmManagerFactory->create($algorithms); + + return new JWSVerifier($algorithmManager); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/LICENSE b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/LICENSE new file mode 100644 index 00000000..37cf976b --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/README.md b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/README.md new file mode 100644 index 00000000..26f0befc --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/README.md @@ -0,0 +1,15 @@ +PHP JWT Signature Component +=========================== + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. + +**Please do not submit any Pull Request here.** +You should go to [the main repository](https://github.com/web-token/jwt-framework) instead. + +# Documentation + +The official documentation is available as https://web-token.spomky-labs.com/ + +# Licence + +This software is release under [MIT licence](LICENSE). diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/CompactSerializer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/CompactSerializer.php new file mode 100644 index 00000000..a4bdab26 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/CompactSerializer.php @@ -0,0 +1,96 @@ +getSignature($signatureIndex); + if (0 !== count($signature->getHeader())) { + throw new LogicException('The signature contains unprotected header parameters and cannot be converted into compact JSON.'); + } + $isEmptyPayload = null === $jws->getEncodedPayload() || '' === $jws->getEncodedPayload(); + if (!$this->isPayloadEncoded($signature->getProtectedHeader()) && !$isEmptyPayload) { + if (1 !== preg_match('/^[\x{20}-\x{2d}|\x{2f}-\x{7e}]*$/u', $jws->getPayload())) { + throw new LogicException('Unable to convert the JWS with non-encoded payload.'); + } + } + + return sprintf( + '%s.%s.%s', + $signature->getEncodedProtectedHeader(), + $jws->getEncodedPayload(), + Base64Url::encode($signature->getSignature()) + ); + } + + /** + * @throws InvalidArgumentException if the input is invalid + */ + public function unserialize(string $input): JWS + { + $parts = explode('.', $input); + if (3 !== count($parts)) { + throw new InvalidArgumentException('Unsupported input'); + } + + try { + $encodedProtectedHeader = $parts[0]; + $protectedHeader = JsonConverter::decode(Base64Url::decode($parts[0])); + $hasPayload = '' !== $parts[1]; + if (!$hasPayload) { + $payload = null; + $encodedPayload = null; + } else { + $encodedPayload = $parts[1]; + $payload = $this->isPayloadEncoded($protectedHeader) ? Base64Url::decode($encodedPayload) : $encodedPayload; + } + $signature = Base64Url::decode($parts[2]); + + $jws = new JWS($payload, $encodedPayload, !$hasPayload); + + return $jws->addSignature($signature, $protectedHeader, $encodedProtectedHeader); + } catch (Throwable $throwable) { + throw new InvalidArgumentException('Unsupported input', $throwable->getCode(), $throwable); + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php new file mode 100644 index 00000000..0d4f54ec --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php @@ -0,0 +1,110 @@ +getSignature($signatureIndex); + + $data = []; + $values = [ + 'payload' => $jws->getEncodedPayload(), + 'protected' => $signature->getEncodedProtectedHeader(), + 'header' => $signature->getHeader(), + ]; + $encodedPayload = $jws->getEncodedPayload(); + if (null !== $encodedPayload && '' !== $encodedPayload) { + $data['payload'] = $encodedPayload; + } + $encodedProtectedHeader = $signature->getEncodedProtectedHeader(); + if (null !== $encodedProtectedHeader && '' !== $encodedProtectedHeader) { + $data['protected'] = $encodedProtectedHeader; + } + $header = $signature->getHeader(); + if (0 !== count($header)) { + $data['header'] = $header; + } + $data['signature'] = Base64Url::encode($signature->getSignature()); + + return JsonConverter::encode($data); + } + + /** + * @throws InvalidArgumentException if the input is not supported + * @throws InvalidArgumentException if the JWS header is invalid + */ + public function unserialize(string $input): JWS + { + $data = JsonConverter::decode($input); + if (!is_array($data)) { + throw new InvalidArgumentException('Unsupported input.'); + } + if (!isset($data['signature'])) { + throw new InvalidArgumentException('Unsupported input.'); + } + $signature = Base64Url::decode($data['signature']); + + if (isset($data['protected'])) { + $encodedProtectedHeader = $data['protected']; + $protectedHeader = JsonConverter::decode(Base64Url::decode($data['protected'])); + } else { + $encodedProtectedHeader = null; + $protectedHeader = []; + } + if (isset($data['header'])) { + if (!is_array($data['header'])) { + throw new InvalidArgumentException('Bad header.'); + } + $header = $data['header']; + } else { + $header = []; + } + + if (isset($data['payload'])) { + $encodedPayload = $data['payload']; + $payload = $this->isPayloadEncoded($protectedHeader) ? Base64Url::decode($encodedPayload) : $encodedPayload; + } else { + $payload = null; + $encodedPayload = null; + } + + $jws = new JWS($payload, $encodedPayload, null === $encodedPayload); + + return $jws->addSignature($signature, $protectedHeader, $encodedProtectedHeader, $header); + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php new file mode 100644 index 00000000..1a88bab1 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php @@ -0,0 +1,167 @@ +countSignatures()) { + throw new LogicException('No signature.'); + } + + $data = []; + $this->checkPayloadEncoding($jws); + + if (false === $jws->isPayloadDetached()) { + $data['payload'] = $jws->getEncodedPayload(); + } + + $data['signatures'] = []; + foreach ($jws->getSignatures() as $signature) { + $tmp = ['signature' => Base64Url::encode($signature->getSignature())]; + $values = [ + 'protected' => $signature->getEncodedProtectedHeader(), + 'header' => $signature->getHeader(), + ]; + + foreach ($values as $key => $value) { + if ((is_string($value) && '' !== $value) || (is_array($value) && 0 !== count($value))) { + $tmp[$key] = $value; + } + } + $data['signatures'][] = $tmp; + } + + return JsonConverter::encode($data); + } + + /** + * @throws InvalidArgumentException if the input is not supported + */ + public function unserialize(string $input): JWS + { + $data = JsonConverter::decode($input); + if (!isset($data['signatures'])) { + throw new InvalidArgumentException('Unsupported input.'); + } + + $isPayloadEncoded = null; + $rawPayload = $data['payload'] ?? null; + $signatures = []; + foreach ($data['signatures'] as $signature) { + if (!isset($signature['signature'])) { + throw new InvalidArgumentException('Unsupported input.'); + } + [$encodedProtectedHeader, $protectedHeader, $header] = $this->processHeaders($signature); + $signatures[] = [ + 'signature' => Base64Url::decode($signature['signature']), + 'protected' => $protectedHeader, + 'encoded_protected' => $encodedProtectedHeader, + 'header' => $header, + ]; + $isPayloadEncoded = $this->processIsPayloadEncoded($isPayloadEncoded, $protectedHeader); + } + + $payload = $this->processPayload($rawPayload, $isPayloadEncoded); + $jws = new JWS($payload, $rawPayload); + foreach ($signatures as $signature) { + $jws = $jws->addSignature( + $signature['signature'], + $signature['protected'], + $signature['encoded_protected'], + $signature['header'] + ); + } + + return $jws; + } + + /** + * @throws InvalidArgumentException if the payload encoding is invalid + */ + private function processIsPayloadEncoded(?bool $isPayloadEncoded, array $protectedHeader): bool + { + if (null === $isPayloadEncoded) { + return $this->isPayloadEncoded($protectedHeader); + } + if ($this->isPayloadEncoded($protectedHeader) !== $isPayloadEncoded) { + throw new InvalidArgumentException('Foreign payload encoding detected.'); + } + + return $isPayloadEncoded; + } + + private function processHeaders(array $signature): array + { + $encodedProtectedHeader = $signature['protected'] ?? null; + $protectedHeader = null === $encodedProtectedHeader ? [] : JsonConverter::decode(Base64Url::decode($encodedProtectedHeader)); + $header = array_key_exists('header', $signature) ? $signature['header'] : []; + + return [$encodedProtectedHeader, $protectedHeader, $header]; + } + + private function processPayload(?string $rawPayload, ?bool $isPayloadEncoded): ?string + { + if (null === $rawPayload) { + return null; + } + + return false === $isPayloadEncoded ? $rawPayload : Base64Url::decode($rawPayload); + } + + // @throws LogicException if the payload encoding is invalid + private function checkPayloadEncoding(JWS $jws): void + { + if ($jws->isPayloadDetached()) { + return; + } + $is_encoded = null; + foreach ($jws->getSignatures() as $signature) { + if (null === $is_encoded) { + $is_encoded = $this->isPayloadEncoded($signature->getProtectedHeader()); + } + if (false === $jws->isPayloadDetached()) { + if ($is_encoded !== $this->isPayloadEncoded($signature->getProtectedHeader())) { + throw new LogicException('Foreign payload encoding detected.'); + } + } + } + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializer.php new file mode 100644 index 00000000..c2edd373 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializer.php @@ -0,0 +1,38 @@ +add($serializer); + } + } + + /** + * @return string[] + */ + public function list(): array + { + return array_keys($this->serializers); + } + + /** + * Converts a JWS into a string. + * + * @throws InvalidArgumentException if the serializer is not supported + */ + public function serialize(string $name, JWS $jws, ?int $signatureIndex = null): string + { + if (!isset($this->serializers[$name])) { + throw new InvalidArgumentException(sprintf('Unsupported serializer "%s".', $name)); + } + + return $this->serializers[$name]->serialize($jws, $signatureIndex); + } + + /** + * Loads data and return a JWS object. + * + * @param string $input A string that represents a JWS + * @param null|string $name the name of the serializer if the input is unserialized + * + * @throws InvalidArgumentException if the input is not supported + */ + public function unserialize(string $input, ?string &$name = null): JWS + { + foreach ($this->serializers as $serializer) { + try { + $jws = $serializer->unserialize($input); + $name = $serializer->name(); + + return $jws; + } catch (InvalidArgumentException $e) { + continue; + } + } + + throw new InvalidArgumentException('Unsupported input.'); + } + + private function add(JWSSerializer $serializer): void + { + $this->serializers[$serializer->name()] = $serializer; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php new file mode 100644 index 00000000..7e346eed --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php @@ -0,0 +1,63 @@ +serializers[$name])) { + throw new InvalidArgumentException(sprintf('Unsupported serializer "%s".', $name)); + } + $serializers[] = $this->serializers[$name]; + } + + return new JWSSerializerManager($serializers); + } + + /** + * @return string[] + */ + public function names(): array + { + return array_keys($this->serializers); + } + + /** + * @return JWSSerializer[] + */ + public function all(): array + { + return $this->serializers; + } + + public function add(JWSSerializer $serializer): void + { + $this->serializers[$serializer->name()] = $serializer; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/Serializer.php b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/Serializer.php new file mode 100644 index 00000000..48a11477 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/Serializer/Serializer.php @@ -0,0 +1,24 @@ +protectedHeader = null === $encodedProtectedHeader ? [] : $protectedHeader; + $this->encodedProtectedHeader = $encodedProtectedHeader; + $this->signature = $signature; + $this->header = $header; + } + + /** + * The protected header associated with the signature. + */ + public function getProtectedHeader(): array + { + return $this->protectedHeader; + } + + /** + * The unprotected header associated with the signature. + */ + public function getHeader(): array + { + return $this->header; + } + + /** + * The protected header associated with the signature. + */ + public function getEncodedProtectedHeader(): ?string + { + return $this->encodedProtectedHeader; + } + + /** + * Returns the value of the protected header of the specified key. + * + * @param string $key The key + * + * @throws InvalidArgumentException if the header parameter does not exist + * + * @return null|mixed Header value + */ + public function getProtectedHeaderParameter(string $key) + { + if ($this->hasProtectedHeaderParameter($key)) { + return $this->getProtectedHeader()[$key]; + } + + throw new InvalidArgumentException(sprintf('The protected header "%s" does not exist', $key)); + } + + /** + * Returns true if the protected header has the given parameter. + * + * @param string $key The key + */ + public function hasProtectedHeaderParameter(string $key): bool + { + return array_key_exists($key, $this->getProtectedHeader()); + } + + /** + * Returns the value of the unprotected header of the specified key. + * + * @param string $key The key + * + * @return null|mixed Header value + */ + public function getHeaderParameter(string $key) + { + if ($this->hasHeaderParameter($key)) { + return $this->header[$key]; + } + + throw new InvalidArgumentException(sprintf('The header "%s" does not exist', $key)); + } + + /** + * Returns true if the unprotected header has the given parameter. + * + * @param string $key The key + */ + public function hasHeaderParameter(string $key): bool + { + return array_key_exists($key, $this->header); + } + + /** + * Returns the value of the signature. + */ + public function getSignature(): string + { + return $this->signature; + } +} diff --git a/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/composer.json b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/composer.json new file mode 100644 index 00000000..92508bf7 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/vendor/web-token/jwt-signature/composer.json @@ -0,0 +1,33 @@ +{ + "name": "web-token/jwt-signature", + "description": "Signature component of the JWT Framework.", + "type": "library", + "license": "MIT", + "keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"], + "homepage": "https://github.com/web-token", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + },{ + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-signature/contributors" + } + ], + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\": "" + } + }, + "require": { + "web-token/jwt-core": "^2.1" + }, + "suggest": { + "web-token/jwt-signature-algorithm-ecdsa": "ECDSA Based Signature Algorithms", + "web-token/jwt-signature-algorithm-eddsa": "EdDSA Based Signature Algorithms", + "web-token/jwt-signature-algorithm-hmac": "HMAC Based Signature Algorithms", + "web-token/jwt-signature-algorithm-none": "None Signature Algorithm", + "web-token/jwt-signature-algorithm-rsa": "RSA Based Signature Algorithms", + "web-token/jwt-signature-algorithm-experimental": "Experimental Signature Algorithms" + } +} diff --git a/wp-content/plugins/wp-webauthn/wp-webauthn.php b/wp-content/plugins/wp-webauthn/wp-webauthn.php new file mode 100644 index 00000000..3760b387 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wp-webauthn.php @@ -0,0 +1,83 @@ + "{}", + 'user_credentials_meta' => "{}", + 'user_id' => array(), + 'first_choice' => 'true', + 'website_name' => get_bloginfo('name'), + 'website_domain' => $site_domain === NULL ? "" : $site_domain, + 'remember_me' => 'false', + 'user_verification' => 'false', + 'usernameless_login' => 'false', + 'allow_authenticator_type' => 'none', + 'logging' => 'false' + ); + update_option('wwa_options', $wwa_init_options); + include('wwa-version.php'); + update_option('wwa_version', $wwa_version); + update_option('wwa_log', array()); + update_option('wwa_init', md5(date('Y-m-d H:i:s'))); + }else{ + include('wwa-version.php'); + if(!get_option('wwa_version') || get_option('wwa_version')['version'] != $wwa_version['version']){ + update_option('wwa_version', $wwa_version); //update version + } + } +} + +// Wrap WP-WebAuthn settings +function wwa_get_option($option_name){ + $val = get_option("wwa_options"); + if(isset($val[$option_name])){ + return $val[$option_name]; + }else{ + return false; + } +} + +function wwa_update_option($option_name, $option_value){ + $options = get_option("wwa_options"); + $options[$option_name] = $option_value; + update_option('wwa_options',$options); + return true; +} + +include('wwa-menus.php'); +include('wwa-functions.php'); +include('wwa-ajax.php'); +include('wwa-shortcodes.php'); +?> \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/wwa-admin-content.php b/wp-content/plugins/wp-webauthn/wwa-admin-content.php new file mode 100644 index 00000000..4152e961 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wwa-admin-content.php @@ -0,0 +1,263 @@ + admin_url('admin-ajax.php'), + 'i18n_1' => __('User verification is disabled by default because some mobile devices do not support it (especially on Android devices). But we recommend you to enable it if possible to further secure your login.', 'wp-webauthn'), + 'i18n_2' => __('Log count: ', 'wp-webauthn'), + 'i18n_3' => __('Loading failed, maybe try refreshing?', 'wp-webauthn') +)); +wp_enqueue_style('wwa_admin', plugins_url('css/admin.css', __FILE__)); +?> +
+ +

your profile.', 'wp-webauthn'), admin_url('profile.php'));?>

+ \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/wwa-ajax.php b/wp-content/plugins/wp-webauthn/wwa-ajax.php new file mode 100644 index 00000000..878841f5 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wwa-ajax.php @@ -0,0 +1,1243 @@ +read(); + if(isset($data[base64_encode($publicKeyCredentialId)])){ + return PublicKeyCredentialSource::createFromArray($data[base64_encode($publicKeyCredentialId)]); + } + return null; + } + + // Get one credential's meta by credential ID + public function findOneMetaByCredentialId(string $publicKeyCredentialId): ?array { + $meta = json_decode(wwa_get_option("user_credentials_meta"), true); + if(isset($meta[base64_encode($publicKeyCredentialId)])){ + return $meta[base64_encode($publicKeyCredentialId)]; + } + return null; + } + + // Get all credentials of one user + public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array { + $sources = []; + foreach($this->read() as $data){ + $source = PublicKeyCredentialSource::createFromArray($data); + if($source->getUserHandle() === $publicKeyCredentialUserEntity->getId()){ + $sources[] = $source; + } + } + return $sources; + } + + public function findCredentialsForUserEntityByType(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity, string $credentialType): array { + $credentialsForUserEntity = $this->findAllForUserEntity($publicKeyCredentialUserEntity); + $credentialsByType = []; + foreach($credentialsForUserEntity as $credential){ + if($this->findOneMetaByCredentialId($credential->getPublicKeyCredentialId())["authenticator_type"] === $credentialType){ + $credentialsByType[] = $credential; + } + } + return $credentialsByType; + } + + // Save credential into database + public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, bool $usernameless = false): void { + $data = $this->read(); + $data_key = base64_encode($publicKeyCredentialSource->getPublicKeyCredentialId()); + $data[$data_key] = $publicKeyCredentialSource; + $this->write($data, $data_key, $usernameless); + } + + // Update credential's last used + public function updateCredentialLastUsed(string $publicKeyCredentialId): void { + $credential = $this->findOneMetaByCredentialId($publicKeyCredentialId); + if($credential !== null){ + $credential["last_used"] = date('Y-m-d H:i:s', current_time('timestamp')); + $meta = json_decode(wwa_get_option("user_credentials_meta"), true); + $meta[base64_encode($publicKeyCredentialId)] = $credential; + wwa_update_option("user_credentials_meta", json_encode($meta)); + } + } + + // List all authenticators + public function getShowList(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array { + $data = json_decode(wwa_get_option("user_credentials_meta"), true); + $arr = array(); + $user_id = $publicKeyCredentialUserEntity->getId(); + foreach($data as $key => $value){ + if($user_id === $value["user"]){ + array_push($arr, array( + "key" => rtrim(strtr(base64_encode($key), '+/', '-_'), '='), + "name" => base64_decode($value["human_name"]), + "type" => $value["authenticator_type"], + "added" => $value["added"], + "usernameless" => isset($value["usernameless"]) ? $value["usernameless"] : false, + "last_used" => isset($value["last_used"]) ? $value["last_used"] : "-" + )); + } + } + return array_map(function($item){return array("key" => $item["key"], "name" => $item["name"], "type" => $item["type"], "added" => $item["added"], "usernameless" => $item["usernameless"], "last_used" => $item["last_used"]);}, $arr); + } + + // Modify an authenticator + public function modifyAuthenticator(string $id, string $name, PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity, string $action, string $res_id): string { + $keys = $this->findAllForUserEntity($publicKeyCredentialUserEntity); + $user_id = $publicKeyCredentialUserEntity->getId(); + + // Check if the user has the authenticator + foreach($keys as $item){ + if($item->getUserHandle() === $user_id){ + if(base64_encode($item->getPublicKeyCredentialId()) === base64_decode(str_pad(strtr($id, '-_', '+/'), strlen($id) % 4, '=', STR_PAD_RIGHT))){ + if($action === "rename"){ + $this->renameCredential(base64_encode($item->getPublicKeyCredentialId()), $name, $res_id); + }else if($action === "remove"){ + $this->removeCredential(base64_encode($item->getPublicKeyCredentialId()), $res_id); + } + wwa_add_log($res_id, "ajax_modify_authenticator: Done"); + return "true"; + } + } + } + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Authenticator not found, exit"); + return "Not Found."; + } + + // Rename a credential from database by credential ID + private function renameCredential(string $id, string $name, string $res_id): void { + $meta = json_decode(wwa_get_option("user_credentials_meta"), true); + wwa_add_log($res_id, "ajax_modify_authenticator: Rename \"".base64_decode($meta[$id]["human_name"])."\" -> \"".$name."\""); + $meta[$id]["human_name"] = base64_encode($name); + wwa_update_option("user_credentials_meta", json_encode($meta)); + } + + // Remove a credential from database by credential ID + private function removeCredential(string $id, string $res_id): void { + $data = $this->read(); + unset($data[$id]); + $this->write($data, ''); + $meta = json_decode(wwa_get_option("user_credentials_meta"), true); + wwa_add_log($res_id, "ajax_modify_authenticator: Remove \"".base64_decode($meta[$id]["human_name"])."\""); + unset($meta[$id]); + wwa_update_option("user_credentials_meta", json_encode($meta)); + } + + // Read credential database + private function read(): array { + if(wwa_get_option("user_credentials") !== NULL){ + try{ + return json_decode(wwa_get_option("user_credentials"), true); + }catch(\Throwable $exception) { + return []; + } + } + return []; + } + + // Save credentials data + private function write(array $data, string $key, bool $usernameless = false): void { + if(isset($_POST["type"]) && ($_POST["type"] === "platform" || $_POST["type"] == "cross-platform" || $_POST["type"] === "none") && $key !== ''){ + // Save credentials's meta separately + $source = $data[$key]->getUserHandle(); + $meta = json_decode(wwa_get_option("user_credentials_meta"), true); + $meta[$key] = array("human_name" => base64_encode(sanitize_text_field($_POST["name"])), "added" => date('Y-m-d H:i:s', current_time('timestamp')), "authenticator_type" => $_POST["type"], "user" => $source, "usernameless" => $usernameless, "last_used" => "-"); + wwa_update_option("user_credentials_meta", json_encode($meta)); + } + wwa_update_option("user_credentials", json_encode($data)); + } +} + +// Bind an authenticator +function wwa_ajax_create(){ + try{ + $res_id = wwa_generate_random_string(5); + $client_id = strval(time()).wwa_generate_random_string(24); + + wwa_init_new_options(); + + wwa_add_log($res_id, "ajax_create: Start"); + + if(!current_user_can("read")){ + wwa_add_log($res_id, "ajax_create: (ERROR)Permission denied, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } + + if(wwa_get_option('website_name') === "" || wwa_get_option('website_domain') ===""){ + wwa_add_log($res_id, "ajax_create: (ERROR)Plugin not configured, exit"); + wwa_wp_die("Not configured.", $client_id); + } + + // Check queries + if(!isset($_GET["name"]) || !isset($_GET["type"]) || !isset($_GET["usernameless"])){ + wwa_add_log($res_id, "ajax_create: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + }else{ + // Sanitize the input + $wwa_get = array(); + $wwa_get["name"] = sanitize_text_field($_GET["name"]); + $wwa_get["type"] = sanitize_text_field($_GET["type"]); + $wwa_get["usernameless"] = sanitize_text_field($_GET["usernameless"]); + wwa_add_log($res_id, "ajax_create: name => \"".$wwa_get["name"]."\", type => \"".$wwa_get["type"]."\", usernameless => \"".$wwa_get["usernameless"]."\""); + } + + $user_info = wp_get_current_user(); + + if(isset($_GET["user_id"])){ + $user_id = intval(sanitize_text_field($_GET["user_id"])); + if($user_id <= 0){ + wwa_add_log($res_id, "ajax_create: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request."); + } + + if($user_info->ID !== $user_id){ + if(!current_user_can("edit_user", $user_id)){ + wwa_add_log($res_id, "ajax_create: (ERROR)No permission, exit"); + wwa_wp_die("Something went wrong."); + } + $user_info = get_user_by('id', $user_id); + + if($user_info === false){ + wwa_add_log($res_id, "ajax_create: (ERROR)Wrong user ID, exit"); + wwa_wp_die("Something went wrong."); + } + } + } + + // Empty authenticator name + if($wwa_get["name"] === ""){ + wwa_add_log($res_id, "ajax_create: (ERROR)Empty name, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + + // Usernameless authentication not allowed + if($wwa_get["usernameless"] === "true" && wwa_get_option("usernameless_login") !== "true"){ + wwa_add_log($res_id, "ajax_create: (ERROR)Usernameless authentication not allowed, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + + // Check authenticator type + $allow_authenticator_type = wwa_get_option("allow_authenticator_type"); + if($allow_authenticator_type !== false && $allow_authenticator_type !== "none"){ + if($allow_authenticator_type != $wwa_get["type"]){ + wwa_add_log($res_id, "ajax_create: (ERROR)Credential type error, type => \"".$wwa_get["type"]."\", allow_authenticator_type => \"".$allow_authenticator_type."\", exit"); + wwa_wp_die("Bad Request.", $client_id); + } + } + + $rpEntity = new PublicKeyCredentialRpEntity( + wwa_get_option("website_name"), + wwa_get_option("website_domain") + ); + $publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); + + $server = new Server( + $rpEntity, + $publicKeyCredentialSourceRepository, + null + ); + + wwa_add_log($res_id, "ajax_create: user => \"".$user_info->user_login."\""); + + // Get user ID or create one + $user_key = ""; + if(!isset(wwa_get_option("user_id")[$user_info->user_login])){ + wwa_add_log($res_id, "ajax_create: User not initialized, initialize"); + $user_array = wwa_get_option("user_id"); + $user_key = hash("sha256", $user_info->user_login."-".$user_info->display_name."-".wwa_generate_random_string(10)); + $user_array[$user_info->user_login] = $user_key; + wwa_update_option("user_id", $user_array); + }else{ + $user_key = wwa_get_option("user_id")[$user_info->user_login]; + } + + $user = array( + "login" => $user_info->user_login, + "id" => $user_key, + "display" => $user_info->display_name, + "icon" => get_avatar_url($user_info->user_email, array("scheme" => "https")) + ); + + $userEntity = new PublicKeyCredentialUserEntity( + $user["login"], + $user["id"], + $user["display"], + $user["icon"] + ); + + $credentialSourceRepository = new PublicKeyCredentialSourceRepository(); + + $credentialSources = $credentialSourceRepository->findAllForUserEntity($userEntity); + + // Convert the Credential Sources into Public Key Credential Descriptors for excluding + $excludeCredentials = array_map(function (PublicKeyCredentialSource $credential) { + return $credential->getPublicKeyCredentialDescriptor(); + }, $credentialSources); + + wwa_add_log($res_id, "ajax_create: excludeCredentials => ".json_encode($excludeCredentials)); + + // Set authenticator type + if($wwa_get["type"] === "platform"){ + $authenticator_type = AuthenticatorSelectionCriteria::AUTHENTICATOR_ATTACHMENT_PLATFORM; + }else if($wwa_get["type"] === "cross-platform"){ + $authenticator_type = AuthenticatorSelectionCriteria::AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM; + }else{ + $authenticator_type = AuthenticatorSelectionCriteria::AUTHENTICATOR_ATTACHMENT_NO_PREFERENCE; + } + + // Set user verification + if(wwa_get_option("user_verification") === "true"){ + wwa_add_log($res_id, "ajax_create: user_verification => \"true\""); + $user_verification = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED; + }else{ + wwa_add_log($res_id, "ajax_create: user_verification => \"false\""); + $user_verification = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED; + } + + $resident_key = false; + // Set usernameless authentication + if($wwa_get["usernameless"] === "true"){ + wwa_add_log($res_id, "ajax_create: Usernameless set, user_verification => \"true\""); + $user_verification = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED; + $resident_key = true; + } + + // Create authenticator selection + $authenticatorSelectionCriteria = new AuthenticatorSelectionCriteria( + $authenticator_type, + $resident_key, + $user_verification + ); + + // Create a creation challenge + $publicKeyCredentialCreationOptions = $server->generatePublicKeyCredentialCreationOptions( + $userEntity, + PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE, + $excludeCredentials, + $authenticatorSelectionCriteria + ); + + // Save for future use + wwa_set_temp_val("pkcco", base64_encode(serialize($publicKeyCredentialCreationOptions)), $client_id); + wwa_set_temp_val("bind_config", array("name" => $wwa_get["name"], "type" => $wwa_get["type"], "usernameless" => $resident_key), $client_id); + + header("Content-Type: application/json"); + $publicKeyCredentialCreationOptions = json_decode(json_encode($publicKeyCredentialCreationOptions), true); + $publicKeyCredentialCreationOptions["clientID"] = $client_id; + echo json_encode($publicKeyCredentialCreationOptions); + wwa_add_log($res_id, "ajax_create: Challenge sent"); + exit; + }catch(\Exception $exception){ + wwa_add_log($res_id, "ajax_create: (ERROR)".$exception->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($exception)); + wwa_add_log($res_id, "ajax_create: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + }catch(\Error $error){ + wwa_add_log($res_id, "ajax_create: (ERROR)".$error->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($error)); + wwa_add_log($res_id, "ajax_create: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } +} +add_action("wp_ajax_wwa_create" , "wwa_ajax_create"); + +// Verify the attestation +function wwa_ajax_create_response(){ + $client_id = false; + try{ + $res_id = wwa_generate_random_string(5); + + wwa_init_new_options(); + + wwa_add_log($res_id, "ajax_create_response: Client response received"); + + if(!isset($_POST["clientid"])){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Missing parameters, exit"); + wp_die("Bad Request."); + }else{ + if(strlen($_POST["clientid"]) < 34 || strlen($_POST["clientid"]) > 35){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Wrong client ID, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + // Sanitize the input + $client_id = sanitize_text_field($_POST["clientid"]); + } + + if(!current_user_can("read")){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Permission denied, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } + + // Check POST + if(!isset($_POST["data"]) || !isset($_POST["name"]) || !isset($_POST["type"]) || !isset($_POST["usernameless"])){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + }else{ + // Sanitize the input + $wwa_post = array(); + $wwa_post["name"] = sanitize_text_field($_POST["name"]); + $wwa_post["type"] = sanitize_text_field($_POST["type"]); + $wwa_post["usernameless"] = sanitize_text_field($_POST["usernameless"]); + wwa_add_log($res_id, "ajax_create_response: name => \"".$wwa_post["name"]."\", type => \"".$wwa_post["type"]."\", usernameless => \"".$wwa_post["usernameless"]."\""); + wwa_add_log($res_id, "ajax_create_response: data => ".base64_decode($_POST["data"])); + } + + if(isset($_GET["user_id"])){ + $user_id = intval(sanitize_text_field($_POST["user_id"])); + if($user_id <= 0){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request."); + } + + if(wp_get_current_user()->ID !== $user_id){ + if(!current_user_can("edit_user", $user_id)){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)No permission, exit"); + wwa_wp_die("Something went wrong."); + } + } + } + + $temp_val = array( + "pkcco" => wwa_get_temp_val("pkcco", $client_id), + "bind_config" => wwa_get_temp_val("bind_config", $client_id) + ); + + // May not get the challenge yet + if($temp_val["pkcco"] === false || $temp_val["bind_config"] === false){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Challenge not found in transient, exit"); + wwa_wp_die("Bad request.", $client_id); + } + + // Check parameters + if($temp_val["bind_config"]["type"] !== "platform" && $temp_val["bind_config"]["type"] !== "cross-platform" && $temp_val["bind_config"]["type"] !== "none"){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Wrong type, exit"); + wwa_wp_die("Bad request.", $client_id); + } + + if($temp_val["bind_config"]["type"] !== $wwa_post["type"] || $temp_val["bind_config"]["name"] !== $wwa_post["name"]){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + + // Check global unique credential ID + $credential_id = base64_decode(json_decode(base64_decode($_POST["data"]), true)["rawId"]); + $publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); + if($publicKeyCredentialSourceRepository->findOneMetaByCredentialId($credential_id) !== null){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)Credential ID not unique, ID => \"".base64_encode($credential_id)."\" , exit"); + wwa_wp_die("Something went wrong.", $client_id); + }else{ + wwa_add_log($res_id, "ajax_create_response: Credential ID unique check passed"); + } + + $psr17Factory = new Psr17Factory(); + $creator = new ServerRequestCreator( + $psr17Factory, + $psr17Factory, + $psr17Factory, + $psr17Factory + ); + + $serverRequest = $creator->fromGlobals(); + + $rpEntity = new PublicKeyCredentialRpEntity( + wwa_get_option("website_name"), + wwa_get_option("website_domain") + ); + + $server = new Server( + $rpEntity, + $publicKeyCredentialSourceRepository, + null + ); + + // Allow to bypass scheme verification when under localhost + $current_domain = wwa_get_option('website_domain'); + if($current_domain === "localhost" || $current_domain === "127.0.0.1"){ + $server->setSecuredRelyingPartyId([$current_domain]); + wwa_add_log($res_id, "ajax_create_response: Localhost, bypass HTTPS check"); + } + + // Verify + try { + $publicKeyCredentialSource = $server->loadAndCheckAttestationResponse( + base64_decode($_POST["data"]), + unserialize(base64_decode($temp_val["pkcco"])), + $serverRequest + ); + + wwa_add_log($res_id, "ajax_create_response: Challenge verified"); + + $publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource, $temp_val["bind_config"]["usernameless"]); + + if($temp_val["bind_config"]["usernameless"]){ + wwa_add_log($res_id, "ajax_create_response: Authenticator added with usernameless authentication feature"); + }else{ + wwa_add_log($res_id, "ajax_create_response: Authenticator added"); + } + + // Success + echo "true"; + }catch(\Throwable $exception){ + // Failed to verify + wwa_add_log($res_id, "ajax_create_response: (ERROR)".$exception->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($exception)); + wwa_add_log($res_id, "ajax_create_response: (ERROR)Challenge not verified, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } + + // Destroy transients + wwa_destroy_temp_val($client_id); + exit; + }catch(\Exception $exception){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)".$exception->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($exception)); + wwa_add_log($res_id, "ajax_create_response: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + }catch(\Error $error){ + wwa_add_log($res_id, "ajax_create_response: (ERROR)".$error->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($error)); + wwa_add_log($res_id, "ajax_create_response: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } +} +add_action("wp_ajax_wwa_create_response" , "wwa_ajax_create_response"); + +// Auth challenge +function wwa_ajax_auth_start(){ + try{ + $res_id = wwa_generate_random_string(5); + $client_id = strval(time()).wwa_generate_random_string(24); + + wwa_init_new_options(); + + wwa_add_log($res_id, "ajax_auth: Start"); + + // Check queries + if(!isset($_GET["type"])){ + wwa_add_log($res_id, "ajax_auth: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + }else{ + // Sanitize the input + $wwa_get = array(); + $wwa_get["type"] = sanitize_text_field($_GET["type"]); + if(isset($_GET["user"])){ + $wwa_get["user"] = sanitize_text_field($_GET["user"]); + } + if(isset($_GET["usernameless"])){ + $wwa_get["usernameless"] = sanitize_text_field($_GET["usernameless"]); + // Usernameless authentication not allowed + if($wwa_get["usernameless"] === "true" && wwa_get_option("usernameless_login") !== "true"){ + wwa_add_log($res_id, "ajax_auth: (ERROR)Usernameless authentication not allowed, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + } + } + + if($wwa_get["type"] === "test" && !current_user_can('read')){ + // Test but not logged in + wwa_add_log($res_id, "ajax_auth: (ERROR)Permission denied, exit"); + wwa_wp_die("Bad request.", $client_id); + } + + $user_key = ""; + $usernameless_flag = false; + $user_icon = null; + if($wwa_get["type"] === "test"){ + if(isset($wwa_get["usernameless"])){ + if($wwa_get["usernameless"] !== "true"){ + // Logged in and testing, if the user haven't bound any authenticator yet, exit + $user_info = wp_get_current_user(); + + if(isset($_GET["user_id"])){ + $user_id = intval(sanitize_text_field($_GET["user_id"])); + if($user_id <= 0){ + wwa_add_log($res_id, "ajax_auth: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request."); + } + + if($user_info->ID !== $user_id){ + if(!current_user_can("edit_user", $user_id)){ + wwa_add_log($res_id, "ajax_auth: (ERROR)No permission, exit"); + wwa_wp_die("Something went wrong."); + } + $user_info = get_user_by('id', $user_id); + + if($user_info === false){ + wwa_add_log($res_id, "ajax_auth: (ERROR)Wrong user ID, exit"); + wwa_wp_die("Something went wrong."); + } + } + } + + wwa_add_log($res_id, "ajax_auth: type => \"test\", user => \"".$user_info->user_login."\", usernameless => \"false\""); + + if(!isset(wwa_get_option("user_id")[$user_info->user_login])){ + wwa_add_log($res_id, "ajax_auth: (ERROR)User not initialized, exit"); + wwa_wp_die("User not inited.", $client_id); + }else{ + $user_key = wwa_get_option("user_id")[$user_info->user_login]; + $user_icon = get_avatar_url($user_info->user_email, array("scheme" => "https")); + } + }else{ + if(wwa_get_option("usernameless_login") === "true"){ + wwa_add_log($res_id, "ajax_auth: type => \"test\", usernameless => \"true\""); + $usernameless_flag = true; + }else{ + wwa_add_log($res_id, "ajax_auth: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + } + }else{ + wwa_add_log($res_id, "ajax_auth: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + }else{ + // Not testing, create a fake user ID if the user does not exist or haven't bound any authenticator yet + if(isset($wwa_get["user"]) && $wwa_get["user"] !== ""){ + if(get_user_by('login', $wwa_get["user"])){ + $user_info = get_user_by('login', $wwa_get["user"]); + $user_icon = get_avatar_url($user_info->user_email, array("scheme" => "https")); + wwa_add_log($res_id, "ajax_auth: type => \"auth\", user => \"".$user_info->user_login."\""); + if(!isset(wwa_get_option("user_id")[$user_info->user_login])){ + wwa_add_log($res_id, "ajax_auth: User not initialized, initialize"); + $user_key = hash("sha256", $wwa_get["user"]."-".$wwa_get["user"]."-".wwa_generate_random_string(10)); + }else{ + $user_key = wwa_get_option("user_id")[$user_info->user_login]; + } + }else{ + $user_info = new stdClass(); + $user_info->user_login = $wwa_get["user"]; + $user_info->display_name = $wwa_get["user"]; + $user_key = hash("sha256", $wwa_get["user"]."-".$wwa_get["user"]."-".wwa_generate_random_string(10)); + wwa_add_log($res_id, "ajax_auth: type => \"auth\", user => \"".$wwa_get["user"]."\""); + wwa_add_log($res_id, "ajax_auth: User not exists, create a fake id"); + } + }else{ + if(wwa_get_option("usernameless_login") === "true"){ + $usernameless_flag = true; + wwa_add_log($res_id, "ajax_auth: Empty username, try usernameless authentication"); + }else{ + wwa_add_log($res_id, "ajax_auth: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + } + } + + if(!$usernameless_flag){ + $userEntity = new PublicKeyCredentialUserEntity( + $user_info->user_login, + $user_key, + $user_info->display_name, + $user_icon + ); + } + + $credentialSourceRepository = new PublicKeyCredentialSourceRepository(); + $rpEntity = new PublicKeyCredentialRpEntity( + wwa_get_option('website_name'), + wwa_get_option('website_domain') + ); + + $server = new Server( + $rpEntity, + $credentialSourceRepository, + null + ); + + if($usernameless_flag){ + // Usernameless authentication, return empty allowed credentials list + wwa_add_log($res_id, "ajax_auth: Usernameless authentication, allowedCredentials => []"); + $allowedCredentials = array(); + }else{ + // Get the list of authenticators associated to the user + // $credentialSources = $credentialSourceRepository->findAllForUserEntity($userEntity); + $allow_authenticator_type = wwa_get_option('allow_authenticator_type'); + if($allow_authenticator_type === false || $allow_authenticator_type === 'none'){ + $credentialSources = $credentialSourceRepository->findAllForUserEntity($userEntity); + }else if($allow_authenticator_type !== false && $allow_authenticator_type !== 'none'){ + wwa_add_log($res_id, "ajax_auth: allow_authenticator_type => \"".$allow_authenticator_type."\", filter authenticators"); + $credentialSources = $credentialSourceRepository->findCredentialsForUserEntityByType($userEntity, $allow_authenticator_type); + } + + // Logged in and testing, if the user haven't bind a authenticator yet, exit + if(count($credentialSources) === 0 && $wwa_get["type"] === "test" && current_user_can('read')){ + wwa_add_log($res_id, "ajax_auth: (ERROR)No authenticator, exit"); + wwa_wp_die("User not inited.", $client_id); + } + + // Convert the Credential Sources into Public Key Credential Descriptors for excluding + $allowedCredentials = array_map(function(PublicKeyCredentialSource $credential){ + return $credential->getPublicKeyCredentialDescriptor(); + }, $credentialSources); + + wwa_add_log($res_id, "ajax_auth: allowedCredentials => ".json_encode($allowedCredentials)); + } + + // Set user verification + if(wwa_get_option("user_verification") === "true"){ + wwa_add_log($res_id, "ajax_auth: user_verification => \"true\""); + $user_verification = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED; + }else{ + wwa_add_log($res_id, "ajax_auth: user_verification => \"false\""); + $user_verification = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_DISCOURAGED; + } + + if($usernameless_flag){ + wwa_add_log($res_id, "ajax_auth: Usernameless authentication, user_verification => \"true\""); + $user_verification = AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED; + } + + // Create a auth challenge + $publicKeyCredentialRequestOptions = $server->generatePublicKeyCredentialRequestOptions( + $user_verification, + $allowedCredentials + ); + + // Save for future use + wwa_set_temp_val("pkcco_auth", base64_encode(serialize($publicKeyCredentialRequestOptions)), $client_id); + wwa_set_temp_val("auth_type", $wwa_get["type"], $client_id); + if(!$usernameless_flag){ + wwa_set_temp_val("user_name_auth", $user_info->user_login, $client_id); + } + wwa_set_temp_val("usernameless_auth", serialize($usernameless_flag), $client_id); + + // Save the user entity if is not logged in and not usernameless + if(!($wwa_get["type"] === "test" && current_user_can("read")) && !$usernameless_flag){ + wwa_set_temp_val("user_auth", serialize($userEntity), $client_id); + } + + header("Content-Type: application/json"); + $publicKeyCredentialRequestOptions = json_decode(json_encode($publicKeyCredentialRequestOptions), true); + $publicKeyCredentialRequestOptions["clientID"] = $client_id; + echo json_encode($publicKeyCredentialRequestOptions); + wwa_add_log($res_id, "ajax_auth: Challenge sent"); + exit; + }catch(\Exception $exception){ + wwa_add_log($res_id, "ajax_auth: (ERROR)".$exception->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($exception)); + wwa_add_log($res_id, "ajax_auth: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + }catch(\Error $error){ + wwa_add_log($res_id, "ajax_auth: (ERROR)".$error->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($error)); + wwa_add_log($res_id, "ajax_auth: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } +} +add_action("wp_ajax_wwa_auth_start" , "wwa_ajax_auth_start"); +add_action("wp_ajax_nopriv_wwa_auth_start" , "wwa_ajax_auth_start"); + +function wwa_ajax_auth(){ + $client_id = false; + try{ + $res_id = wwa_generate_random_string(5); + + wwa_init_new_options(); + + wwa_add_log($res_id, "ajax_auth_response: Client response received"); + + if(!isset($_POST["clientid"])){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Missing parameters, exit"); + wp_die("Bad Request."); + }else{ + if(strlen($_POST["clientid"]) < 34 || strlen($_POST["clientid"]) > 35){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong client ID, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + // Sanitize the input + $client_id = sanitize_text_field($_POST["clientid"]); + } + + // Check POST + if(!isset($_POST["type"]) || !isset($_POST["data"]) || !isset($_POST["remember"])){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + }else{ + // Sanitize the input + $wwa_post = array(); + $wwa_post["type"] = sanitize_text_field($_POST["type"]); + $wwa_post["remember"] = sanitize_text_field($_POST["remember"]); + } + + $temp_val = array( + "pkcco_auth" => wwa_get_temp_val("pkcco_auth", $client_id), + "auth_type" => wwa_get_temp_val("auth_type", $client_id), + "usernameless_auth" => wwa_get_temp_val("usernameless_auth", $client_id), + "user_auth" => wwa_get_temp_val("user_auth", $client_id), + "user_name_auth" => wwa_get_temp_val("user_name_auth", $client_id) + ); + + if($temp_val["auth_type"] === false || $wwa_post["type"] !== $temp_val["auth_type"]){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + + // Check remember me + if($wwa_post["remember"] !== "true" && $wwa_post["remember"] !== "false"){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + }else if(wwa_get_option('remember_me') !== 'true' && $wwa_post["remember"] === "true"){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request.", $client_id); + } + + // May not get the challenge yet + if($temp_val["pkcco_auth"] === false || $temp_val["usernameless_auth"] === false || ($wwa_post["type"] !== "test" && $wwa_post["type"] !== "auth")){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Challenge not found in transient, exit"); + wwa_wp_die("Bad request.", $client_id); + } + + $temp_val["usernameless_auth"] = unserialize($temp_val["usernameless_auth"]); + + if($temp_val["usernameless_auth"] === false && $temp_val["user_name_auth"] === false){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Username not found in transient, exit"); + wwa_wp_die("Bad request.", $client_id); + } + if($wwa_post["type"] === "test" && !current_user_can("read")){ + // Test but not logged in + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Permission denied, exit"); + wwa_wp_die("Bad request.", $client_id); + } + if(!($wwa_post["type"] === "test" && current_user_can("read")) && ($temp_val["usernameless_auth"] === false && $temp_val["user_auth"] === false)){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Permission denied, exit"); + wwa_wp_die("Bad request.", $client_id); + } + + $usernameless_flag = $temp_val["usernameless_auth"]; + + $psr17Factory = new Psr17Factory(); + $creator = new ServerRequestCreator( + $psr17Factory, + $psr17Factory, + $psr17Factory, + $psr17Factory + ); + + $serverRequest = $creator->fromGlobals(); + $publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); + + // If user entity is not saved, read from WordPress + $user_key = ""; + if($wwa_post["type"] === "test" && current_user_can('read') && !$usernameless_flag){ + $user_info = wp_get_current_user(); + + if(isset($_GET["user_id"])){ + $user_id = intval(sanitize_text_field($_POST["user_id"])); + if($user_id <= 0){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request."); + } + + if($user_info->ID !== $user_id){ + if(!current_user_can("edit_user", $user_id)){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)No permission, exit"); + wwa_wp_die("Something went wrong."); + } + $user_info = get_user_by('id', $user_id); + + if($user_info === false){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong user ID, exit"); + wwa_wp_die("Something went wrong."); + } + } + } + + if(!isset(wwa_get_option("user_id")[$user_info->user_login])){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)User not initialized, exit"); + wwa_wp_die("User not inited.", $client_id); + }else{ + $user_key = wwa_get_option("user_id")[$user_info->user_login]; + $user_icon = get_avatar_url($user_info->user_email, array("scheme" => "https")); + } + + $userEntity = new PublicKeyCredentialUserEntity( + $user_info->user_login, + $user_key, + $user_info->display_name, + $user_icon + ); + + wwa_add_log($res_id, "ajax_auth_response: type => \"test\", user => \"".$user_info->user_login."\""); + }else{ + if($usernameless_flag){ + $data_array = json_decode(base64_decode($_POST["data"]), true); + if(!isset($data_array["response"]["userHandle"]) || !isset($data_array["rawId"])){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Client data not correct, exit"); + wwa_wp_die("Bad request.", $client_id); + } + + wwa_add_log($res_id, "ajax_auth_response: type => \"".$wwa_post["type"]."\""); + wwa_add_log($res_id, "ajax_auth_response: Usernameless authentication, try to find user by credential_id => \"".$data_array["rawId"]."\", userHandle => \"".$data_array["response"]["userHandle"]."\""); + + $credential_meta = $publicKeyCredentialSourceRepository->findOneMetaByCredentialId(base64_decode($data_array["rawId"])); + + if($credential_meta !== null){ + $allow_authenticator_type = wwa_get_option("allow_authenticator_type"); + if($allow_authenticator_type !== false && $allow_authenticator_type !== 'none'){ + if($credential_meta["authenticator_type"] !== $allow_authenticator_type){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Credential type error, authenticator_type => \"".$credential_meta["authenticator_type"]."\", allow_authenticator_type => \"".$allow_authenticator_type."\", exit"); + wwa_wp_die("Bad request.", $client_id); + } + } + if($credential_meta["usernameless"] === true){ + wwa_add_log($res_id, "ajax_auth_response: Credential found, usernameless => \"true\", user_key => \"".$credential_meta["user"]."\""); + + // Try to find user + $all_user = wwa_get_option("user_id"); + $user_login_name = false; + foreach($all_user as $user => $user_id){ + if($user_id === $credential_meta["user"]){ + $user_login_name = $user; + break; + } + } + + // Match userHandle + if($credential_meta["user"] === base64_decode($data_array["response"]["userHandle"])){ + // Found user + if($user_login_name !== false){ + wwa_add_log($res_id, "ajax_auth_response: Found user => \"".$user_login_name."\", user_key => \"".$credential_meta["user"]."\""); + + // Testing, verify user + if($wwa_post["type"] === "test" && current_user_can('read')){ + $user_wp = wp_get_current_user(); + if($user_login_name !== $user_wp->user_login){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Credential found, but user not match, exit"); + wwa_wp_die("Bad request.", $client_id); + } + } + + $user_info = get_user_by('login', $user_login_name); + + if($user_info === false){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong user ID, exit"); + wwa_wp_die("Something went wrong."); + } + + $userEntity = new PublicKeyCredentialUserEntity( + $user_info->user_login, + $credential_meta["user"], + $user_info->display_name, + get_avatar_url($user_info->user_email, array("scheme" => "https")) + ); + }else{ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Credential found, but user not found, exit"); + wwa_wp_die("Bad request.", $client_id); + } + }else{ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Credential found, but userHandle not matched, exit"); + wwa_wp_die("Bad request.", $client_id); + } + }else{ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Credential found, but usernameless => \"false\", exit"); + wwa_wp_die("Bad request.", $client_id); + } + }else{ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Credential not found, exit"); + wwa_wp_die("Bad request.", $client_id); + } + }else{ + wwa_add_log($res_id, "ajax_auth_response: type => \"auth\", user => \"".$temp_val["user_name_auth"]."\""); + $userEntity = unserialize($temp_val["user_auth"]); + } + } + + wwa_add_log($res_id, "ajax_auth_response: data => ".base64_decode($_POST["data"])); + + $rpEntity = new PublicKeyCredentialRpEntity( + wwa_get_option("website_name"), + wwa_get_option("website_domain") + ); + + $server = new Server( + $rpEntity, + $publicKeyCredentialSourceRepository, + null + ); + + // Allow to bypass scheme verification when under localhost + $current_domain = wwa_get_option("website_domain"); + if($current_domain === "localhost" || $current_domain === "127.0.0.1"){ + $server->setSecuredRelyingPartyId([$current_domain]); + wwa_add_log($res_id, "ajax_auth_response: Localhost, bypass HTTPS check"); + } + + // Verify + try { + $server->loadAndCheckAssertionResponse( + base64_decode($_POST["data"]), + unserialize(base64_decode($temp_val["pkcco_auth"])), + $userEntity, + $serverRequest + ); + + wwa_add_log($res_id, "ajax_auth_response: Challenge verified"); + + // Success + $publicKeyCredentialSourceRepository->updateCredentialLastUsed(base64_decode(json_decode(base64_decode($_POST["data"]), true)["rawId"])); + if(!($wwa_post["type"] === "test" && current_user_can("read"))){ + // Log user in + if (!is_user_logged_in()) { + include("wwa-compatibility.php"); + + if(!$usernameless_flag){ + $user_login = $temp_val["user_name_auth"]; + }else{ + $user_login = $user_login_name; + } + + $user = get_user_by("login", $user_login); + + if($user_info === false){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Wrong user ID, exit"); + wwa_wp_die("Something went wrong."); + } + + $user_id = $user->ID; + + wwa_add_log($res_id, "ajax_auth_response: Log in user => \"".$user_login."\""); + + $remember_flag = false; + + if ($wwa_post["remember"] === "true" && (wwa_get_option("remember_me") === false ? "false" : wwa_get_option("remember_me")) !== "false") { + $remember_flag = true; + wwa_add_log($res_id, "ajax_auth_response: Remember login for 14 days"); + } + + wp_set_current_user($user_id, $user_login); + if(isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on"){ + wp_set_auth_cookie($user_id, $remember_flag, true); + }else{ + wp_set_auth_cookie($user_id, $remember_flag); + } + do_action("wp_login", $user_login, $user); + } + } + echo "true"; + }catch(\Throwable $exception){ + // Failed to verify + wwa_add_log($res_id, "ajax_auth_response: (ERROR)".$exception->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($exception)); + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Challenge not verified, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } + + // Destroy session + wwa_destroy_temp_val($client_id); + exit; + }catch(\Exception $exception){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)".$exception->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($exception)); + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + }catch(\Error $error){ + wwa_add_log($res_id, "ajax_auth_response: (ERROR)".$error->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($error)); + wwa_add_log($res_id, "ajax_auth_response: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong.", $client_id); + } +} +add_action("wp_ajax_wwa_auth" , "wwa_ajax_auth"); +add_action("wp_ajax_nopriv_wwa_auth" , "wwa_ajax_auth"); + +// Get authenticator list +function wwa_ajax_authenticator_list(){ + $res_id = wwa_generate_random_string(5); + + wwa_init_new_options(); + + if(!current_user_can("read")){ + wwa_add_log($res_id, "ajax_ajax_authenticator_list: (ERROR)Missing parameters, exit"); + wwa_wp_die("Something went wrong."); + } + + $user_info = wp_get_current_user(); + + if(isset($_GET["user_id"])){ + $user_id = intval(sanitize_text_field($_GET["user_id"])); + if($user_id <= 0){ + wwa_add_log($res_id, "ajax_ajax_authenticator_list: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request."); + } + + if($user_info->ID !== $user_id){ + if(!current_user_can("edit_user", $user_id)){ + wwa_add_log($res_id, "ajax_ajax_authenticator_list: (ERROR)No permission, exit"); + wwa_wp_die("Something went wrong."); + } + $user_info = get_user_by('id', $user_id); + + if($user_info === false){ + wwa_add_log($res_id, "ajax_ajax_authenticator_list: (ERROR)Wrong user ID, exit"); + wwa_wp_die("Something went wrong."); + } + } + } + + header('Content-Type: application/json'); + + $user_key = ""; + if(!isset(wwa_get_option("user_id")[$user_info->user_login])){ + wwa_add_log($res_id, "ajax_ajax_authenticator_list: Empty authenticator list"); + // The user haven't bound any authenticator, return empty list + echo "[]"; + exit; + }else{ + $user_key = wwa_get_option("user_id")[$user_info->user_login]; + } + + $userEntity = new PublicKeyCredentialUserEntity( + $user_info->user_login, + $user_key, + $user_info->display_name, + get_avatar_url($user_info->user_email, array("scheme" => "https")) + ); + + $publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); + echo json_encode($publicKeyCredentialSourceRepository->getShowList($userEntity)); + exit; +} +add_action("wp_ajax_wwa_authenticator_list" , "wwa_ajax_authenticator_list"); + +// Modify an authenticator +function wwa_ajax_modify_authenticator(){ + try{ + $res_id = wwa_generate_random_string(5); + + wwa_init_new_options(); + + wwa_add_log($res_id, "ajax_modify_authenticator: Start"); + + if(!current_user_can("read")){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Permission denied, exit"); + wwa_wp_die("Bad Request."); + } + + if(!isset($_GET["id"]) || !isset($_GET["target"])){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request."); + } + + $user_info = wp_get_current_user(); + + if(isset($_GET["user_id"])){ + $user_id = intval(sanitize_text_field($_GET["user_id"])); + if($user_id <= 0){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Wrong parameters, exit"); + wwa_wp_die("Bad Request."); + } + + if($user_info->ID !== $user_id){ + if(!current_user_can("edit_user", $user_id)){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)No permission, exit"); + wwa_wp_die("Something went wrong."); + } + $user_info = get_user_by('id', $user_id); + + if($user_info === false){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Wrong user ID, exit"); + wwa_wp_die("Something went wrong."); + } + } + } + + if($_GET["target"] !== "rename" && $_GET["target"] !== "remove"){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Wrong target, exit"); + wwa_wp_die("Bad Request."); + } + + if($_GET["target"] === "rename" && !isset($_GET["name"])){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Missing parameters, exit"); + wwa_wp_die("Bad Request."); + } + + $user_key = ""; + if(!isset(wwa_get_option("user_id")[$user_info->user_login])){ + // The user haven't bound any authenticator, exit + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)User not initialized, exit"); + wwa_wp_die("User not inited."); + }else{ + $user_key = wwa_get_option("user_id")[$user_info->user_login]; + } + + $userEntity = new PublicKeyCredentialUserEntity( + $user_info->user_login, + $user_key, + $user_info->display_name, + get_avatar_url($user_info->user_email, array("scheme" => "https")) + ); + + wwa_add_log($res_id, "ajax_modify_authenticator: user => \"".$user_info->user_login."\""); + + $publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); + + if($_GET["target"] === "rename"){ + echo $publicKeyCredentialSourceRepository->modifyAuthenticator($_GET["id"], sanitize_text_field($_GET["name"]), $userEntity, "rename", $res_id); + }else if($_GET["target"] === "remove"){ + echo $publicKeyCredentialSourceRepository->modifyAuthenticator($_GET["id"], "", $userEntity, "remove", $res_id); + } + exit; + }catch(\Exception $exception){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)".$exception->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($exception)); + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong."); + }catch(\Error $error){ + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)".$error->getMessage()); + wwa_add_log($res_id, wwa_generate_call_trace($error)); + wwa_add_log($res_id, "ajax_modify_authenticator: (ERROR)Unknown error, exit"); + wwa_wp_die("Something went wrong."); + } +} +add_action("wp_ajax_wwa_modify_authenticator" , "wwa_ajax_modify_authenticator"); + +// Print log +function wwa_ajax_get_log(){ + if(!wwa_validate_privileges()){ + wwa_wp_die("Bad Request."); + } + + header('Content-Type: application/json'); + + $log = get_option("wwa_log"); + + if($log === false){ + echo "[]"; + }else{ + echo json_encode($log); + } + + exit; +} +add_action("wp_ajax_wwa_get_log" , "wwa_ajax_get_log"); + +// Clear log +function wwa_ajax_clear_log(){ + if(!wwa_validate_privileges()){ + wwa_wp_die("Bad Request."); + } + + $log = get_option("wwa_log"); + + if($log !== false){ + update_option("wwa_log", array()); + } + + echo "true"; + exit; +} +add_action("wp_ajax_wwa_clear_log" , "wwa_ajax_clear_log"); +?> \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/wwa-compatibility.php b/wp-content/plugins/wp-webauthn/wwa-compatibility.php new file mode 100644 index 00000000..8c946c0c --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wwa-compatibility.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/wwa-functions.php b/wp-content/plugins/wp-webauthn/wwa-functions.php new file mode 100644 index 00000000..0e0b9aa4 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wwa-functions.php @@ -0,0 +1,332 @@ +getTraceAsString()); + $trace = array_reverse($trace); + array_shift($trace); + array_pop($trace); + $length = count($trace); + $result = array(); + + for($i = 0; $i < $length; $i++){ + $result[] = ($i + 1).')'.substr($trace[$i], strpos($trace[$i], ' ')); + } + + return "Traceback:\n ".implode("\n ", $result); +} + +// Delete all credentials when deleting user +function wwa_delete_user($user_id){ + $res_id = wwa_generate_random_string(5); + + $user_data = get_userdata($user_id); + $all_user_meta = wwa_get_option("user_id"); + $user_key = ""; + wwa_add_log($res_id, "Delete user => \"".$user_data->user_login."\""); + + // Delete user meta + foreach($all_user_meta as $user => $id){ + if($user === $user_data->user_login){ + $user_key = $id; + wwa_add_log($res_id, "Delete user_key => \"".$id."\""); + unset($all_user_meta[$user]); + } + } + + // Delete credentials + $all_credentials_meta = json_decode(wwa_get_option("user_credentials_meta"), true); + $all_credentials = json_decode(wwa_get_option("user_credentials"), true); + foreach($all_credentials_meta as $credential => $meta){ + if($user_key === $meta["user"]){ + wwa_add_log($res_id, "Delete credential => \"".$credential."\""); + unset($all_credentials_meta[$credential]); + unset($all_credentials[$credential]); + } + } + wwa_update_option("user_id", $all_user_meta); + wwa_update_option("user_credentials_meta", json_encode($all_credentials_meta)); + wwa_update_option("user_credentials", json_encode($all_credentials)); + wwa_add_log($res_id, "Done"); +} +add_action('delete_user', 'wwa_delete_user'); + +// Add CSS and JS in login page +function wwa_login_js(){ + $wwa_not_allowed = false; + if(!function_exists("mb_substr") || !function_exists("gmp_intval") || !wwa_check_ssl() && (parse_url(site_url(), PHP_URL_HOST) !== 'localhost' && parse_url(site_url(), PHP_URL_HOST) !== '127.0.0.1')){ + $wwa_not_allowed = true; + } + wp_enqueue_script('wwa_login', plugins_url('js/login.js', __FILE__), array(), get_option('wwa_version')['version'], true); + $first_choice = wwa_get_option('first_choice'); + wp_localize_script('wwa_login', 'php_vars', array( + 'ajax_url' => admin_url('admin-ajax.php'), + 'admin_url' => admin_url(), + 'usernameless' => (wwa_get_option('usernameless_login') === false ? 'false' : wwa_get_option('usernameless_login')), + 'remember_me' => (wwa_get_option('remember_me') === false ? 'false' : wwa_get_option('remember_me')), + 'allow_authenticator_type' => (wwa_get_option('allow_authenticator_type') === false ? "none" : wwa_get_option('allow_authenticator_type')), + 'webauthn_only' => ($first_choice === 'webauthn' && !$wwa_not_allowed) ? 'true' : 'false', + 'i18n_1' => __('Auth', 'wp-webauthn'), + 'i18n_2' => __('Authenticate with WebAuthn', 'wp-webauthn'), + 'i18n_3' => __('Hold on...', 'wp-webauthn'), + 'i18n_4' => __('Please proceed...', 'wp-webauthn'), + 'i18n_5' => __('Authenticating...', 'wp-webauthn'), + 'i18n_6' => ' '.__('Authenticated', 'wp-webauthn').'', + 'i18n_7' => ' '.__('Auth failed', 'wp-webauthn').'', + 'i18n_8' => __('It looks like your browser doesn\'t support WebAuthn, which means you may unable to login.', 'wp-webauthn'), + 'i18n_9' => __('Username', 'wp-webauthn'), + 'i18n_10' => __('Username or Email Address'), + 'i18n_11' => __('Error: The username field is empty.', 'wp-webauthn'), + 'i18n_12' => ''.__('Try to enter the username', 'wp-webauthn').'' + )); + if($first_choice === 'true' || $first_choice === 'webauthn'){ + wp_enqueue_script('wwa_default', plugins_url('js/default_wa.js', __FILE__), array(), get_option('wwa_version')['version'], true); + } + wp_enqueue_style('wwa_login_css', plugins_url('css/login.css', __FILE__), array(), get_option('wwa_version')['version']); +} +add_action('login_enqueue_scripts', 'wwa_login_js', 999); + +// Disable password login +function wwa_disable_password($user){ + if(!function_exists("mb_substr") || !function_exists("gmp_intval") || !wwa_check_ssl() && (parse_url(site_url(), PHP_URL_HOST) !== 'localhost' && parse_url(site_url(), PHP_URL_HOST) !== '127.0.0.1')){ + return $user; + } + if(wwa_get_option('first_choice') === 'webauthn'){ + return new WP_Error('wwa_password_disabled', __('Logging in with password has been disabled by the site manager.', 'wp-webauthn')); + } + if(is_wp_error($user)){ + return $user; + } + if(get_the_author_meta('webauthn_only', $user->ID) === 'true'){ + return new WP_Error('wwa_password_disabled_for_account', __('Logging in with password has been disabled for this account.', 'wp-webauthn')); + } + return $user; +} +add_filter('wp_authenticate_user', 'wwa_disable_password', 10, 1); + +// Show a notice in admin pages +function wwa_no_authenticator_warning(){ + $user_info = wp_get_current_user(); + $first_choice = wwa_get_option('first_choice'); + $check_self = true; + if($first_choice !== 'webauthn' && get_the_author_meta('webauthn_only', $user_info->ID ) !== 'true'){ + $check_self = false; + } + + if($check_self){ + // Check current user + $user_id = ''; + $show_notice_flag = false; + if(!isset(wwa_get_option('user_id')[$user_info->user_login])){ + $show_notice_flag = true; + }else{ + $user_id = wwa_get_option('user_id')[$user_info->user_login]; + } + + if(!$show_notice_flag){ + $show_notice_flag = true; + $data = json_decode(wwa_get_option('user_credentials_meta'), true); + foreach($data as $value){ + if($user_id === $value['user']){ + $show_notice_flag = false; + break; + } + } + } + + if($show_notice_flag){?> +
+

Register', 'wp-webauthn'), $first_choice === 'webauthn' ? __('the site', 'wp-webauthn') : __('your account', 'wp-webauthn'), admin_url('profile.php'));?>

+
+ ID){ + $user_id_wp = intval($_GET['user_id']); + if($user_id_wp <= 0){ + return; + } + if(!current_user_can('edit_user', $user_id_wp)){ + return; + } + $user_info = get_user_by('id', $user_id_wp); + + if($user_info === false){ + return; + } + + if($first_choice !== 'webauthn' && get_the_author_meta('webauthn_only', $user_info->ID ) !== 'true'){ + return; + } + + $user_id = ''; + $show_notice_flag = false; + if(!isset(wwa_get_option('user_id')[$user_info->user_login])){ + $show_notice_flag = true; + }else{ + $user_id = wwa_get_option('user_id')[$user_info->user_login]; + } + + if(!$show_notice_flag){ + $show_notice_flag = true; + $data = json_decode(wwa_get_option('user_credentials_meta'), true); + foreach($data as $value){ + if($user_id === $value['user']){ + $show_notice_flag = false; + break; + } + } + } + + if($show_notice_flag){ ?> +
+

this account haven\'t register any WebAuthn authenticator yet. This user may unable to login.', 'wp-webauthn'), $first_choice === 'webauthn' ? __('the site', 'wp-webauthn') : __('this account', 'wp-webauthn'));?>

+
+ '.__('Settings', 'wp-webauthn').''; + } + return $links_array; +} +add_filter('plugin_action_links', 'wwa_settings_link', 10, 2); + +function wwa_meta_link($links_array, $plugin_file_name){ + if($plugin_file_name === 'wp-webauthn/wp-webauthn.php'){ + $links_array[] = ''.__('GitHub', 'wp-webauthn').''; + $links_array[] = ''.__('Documentation', 'wp-webauthn').''; + } + return $links_array; +} +add_filter('plugin_row_meta', 'wwa_meta_link', 10, 2); + +// Check if we are under HTTPS +function wwa_check_ssl() { + if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' && $_SERVER['HTTPS'] !== '') { + return true; + } + if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'on') { + return true; + } + if (isset($_SERVER['SERVER_PROTOCOL']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/3.0') { + return true; + } + if (isset($_SERVER['REQUEST_SCHEME']) && ($_SERVER['REQUEST_SCHEME'] === 'quic' || $_SERVER['REQUEST_SCHEME'] === 'https')) { + return true; + } + return false; +} + +// Check user privileges +function wwa_validate_privileges() { + $user = wp_get_current_user(); + $allowed_roles = array( 'administrator' ); + if(array_intersect($allowed_roles, $user->roles)){ + return true; + } + return false; +} +?> diff --git a/wp-content/plugins/wp-webauthn/wwa-menus.php b/wp-content/plugins/wp-webauthn/wwa-menus.php new file mode 100644 index 00000000..83545651 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wwa-menus.php @@ -0,0 +1,50 @@ + admin_url('admin-ajax.php'), + 'user_id' => $user->ID, + 'i18n_1' => __('Initializing...', 'wp-webauthn'), + 'i18n_2' => __('Please follow instructions to finish registration...', 'wp-webauthn'), + 'i18n_3' => ''._x('Registered', 'action', 'wp-webauthn').'', + 'i18n_4' => ''.__('Registration failed', 'wp-webauthn').'', + 'i18n_5' => __('Your browser does not support WebAuthn', 'wp-webauthn'), + 'i18n_6' => __('Registrating...', 'wp-webauthn'), + 'i18n_7' => __('Please enter the authenticator identifier', 'wp-webauthn'), + 'i18n_8' => __('Loading failed, maybe try refreshing?', 'wp-webauthn'), + 'i18n_9' => __('Any', 'wp-webauthn'), + 'i18n_10' => __('Platform authenticator', 'wp-webauthn'), + 'i18n_11' => __('Roaming authenticator', 'wp-webauthn'), + 'i18n_12' => __('Remove', 'wp-webauthn'), + 'i18n_13' => __('Please follow instructions to finish verification...', 'wp-webauthn'), + 'i18n_14' => __('Verifying...', 'wp-webauthn'), + 'i18n_15' => ''.__('Verification failed', 'wp-webauthn').'', + 'i18n_16' => ''.__('Verification passed! You can now log in through WebAuthn', 'wp-webauthn').'', + 'i18n_17' => __('No registered authenticators', 'wp-webauthn'), + 'i18n_18' => __('Confirm removal of authenticator: ', 'wp-webauthn'), + 'i18n_19' => __('Removing...', 'wp-webauthn'), + 'i18n_20' => __('Rename', 'wp-webauthn'), + 'i18n_21' => __('Rename the authenticator', 'wp-webauthn'), + 'i18n_22' => __('Renaming...', 'wp-webauthn'), + 'i18n_24' => __('Ready', 'wp-webauthn'), + 'i18n_25' => __('No', 'wp-webauthn'), + 'i18n_26' => __(' (Unavailable)', 'wp-webauthn'), + 'i18n_27' => __('The site administrator has disabled usernameless login feature.', 'wp-webauthn'), + 'i18n_28' => __('After removing this authenticator, you will not be able to login with WebAuthn', 'wp-webauthn'), + 'i18n_29' => __(' (Disabled)', 'wp-webauthn'), + 'i18n_30' => __('The site administrator only allow platform authenticators currently.', 'wp-webauthn'), + 'i18n_31' => __('The site administrator only allow roaming authenticators currently.', 'wp-webauthn') +)); +wp_enqueue_style('wwa_profile', plugins_url('css/admin.css', __FILE__)); +wp_localize_script('wwa_profile', 'configs', array('usernameless' => (wwa_get_option('usernameless_login') === false ? "false" : wwa_get_option('usernameless_login')), 'allow_authenticator_type' => (wwa_get_option('allow_authenticator_type') === false ? "none" : wwa_get_option('allow_authenticator_type')))); +?> +
+

WebAuthn

+ +
+ +
+ + + + + + +
+ +


+
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+

+   +
+ +

+

%s.
You can register multiple authenticators for an account.', 'wp-webauthn'), $user->user_login);?>

+ + + + + + + + + + + + + + + +
+ + +

Regardless of the type, you can only log in with the very same authenticators you\'ve registered.', 'wp-webauthn');?>

+
+ +

DOES NOT affect the authentication process in anyway.', 'wp-webauthn');?>

+
+
+
+
+

Some authenticators like U2F-only authenticators and some browsers DO NOT support this feature.
A record will be stored in the authenticator permanently untill you reset it.', 'wp-webauthn');?>

+
+
+      +
+
+ +

+

+      + +

      + +
\ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/wwa-shortcodes.php b/wp-content/plugins/wp-webauthn/wwa-shortcodes.php new file mode 100644 index 00000000..293a92b9 --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wwa-shortcodes.php @@ -0,0 +1,181 @@ + admin_url('admin-ajax.php'), + 'admin_url' => admin_url(), + 'usernameless' => (wwa_get_option('usernameless_login') === false ? "false" : wwa_get_option('usernameless_login')), + 'remember_me' => (wwa_get_option('remember_me') === false ? "false" : wwa_get_option('remember_me')), + 'allow_authenticator_type' => (wwa_get_option('allow_authenticator_type') === false ? "none" : wwa_get_option('allow_authenticator_type')), + 'i18n_1' => __('Ready', 'wp-webauthn'), + 'i18n_2' => __('Authenticate with WebAuthn', 'wp-webauthn'), + 'i18n_3' => __('Hold on...', 'wp-webauthn'), + 'i18n_4' => __('Please proceed...', 'wp-webauthn'), + 'i18n_5' => __('Authenticating...', 'wp-webauthn'), + 'i18n_6' => ''.__('Authenticated', 'wp-webauthn'), + 'i18n_7' => ''.__('Auth failed', 'wp-webauthn').'', + 'i18n_8' => __('No', 'wp-webauthn'), + 'i18n_9' => __(' (Unavailable)', 'wp-webauthn'), + 'i18n_10' => __('The site administrator has disabled usernameless login feature.', 'wp-webauthn'), + 'i18n_11' => __('Error: The username field is empty.', 'wp-webauthn'), + 'i18n_12' => __('Please enter the authenticator identifier', 'wp-webauthn'), + 'i18n_13' => __('Please follow instructions to finish verification...', 'wp-webauthn'), + 'i18n_14' => __('Verifying...', 'wp-webauthn'), + 'i18n_15' => ''.__('Verification failed', 'wp-webauthn').'', + 'i18n_16' => ''.__('Verification passed! You can now log in through WebAuthn', 'wp-webauthn').'', + 'i18n_17' => __('Loading failed, maybe try refreshing?', 'wp-webauthn'), + 'i18n_18' => __('Confirm removal of authenticator: ', 'wp-webauthn'), + 'i18n_19' => __('Removing...', 'wp-webauthn'), + 'i18n_20' => __('Rename', 'wp-webauthn'), + 'i18n_21' => __('Rename the authenticator', 'wp-webauthn'), + 'i18n_22' => __('Renaming...', 'wp-webauthn'), + 'i18n_23' => __('No registered authenticators', 'wp-webauthn'), + 'i18n_24' => __('Any', 'wp-webauthn'), + 'i18n_25' => __('Platform authenticator', 'wp-webauthn'), + 'i18n_26' => __('Roaming authenticator', 'wp-webauthn'), + 'i18n_27' => __('Remove', 'wp-webauthn'), + 'i18n_28' => __('Please follow instructions to finish registration...', 'wp-webauthn'), + 'i18n_29' => ''._x('Registered', 'action', 'wp-webauthn').'', + 'i18n_30' => ''.__('Registration failed', 'wp-webauthn').'', + 'i18n_31' => __('Your browser does not support WebAuthn', 'wp-webauthn'), + 'i18n_32' => __('Registrating...', 'wp-webauthn'), + 'i18n_33' => ''.__('Try to enter the username', 'wp-webauthn').'', + 'i18n_34' => __('After removing this authenticator, you will not be able to login with WebAuthn', 'wp-webauthn'), + 'i18n_35' => __(' (Disabled)', 'wp-webauthn'), + 'i18n_36' => __('The site administrator only allow platform authenticators currently.', 'wp-webauthn'), + 'i18n_37' => __('The site administrator only allow roaming authenticators currently.', 'wp-webauthn') + )); +} + +// Login form +function wwa_login_form_shortcode($vals){ + extract(shortcode_atts( + array( + 'traditional' => 'true', + 'username' => '', + 'auto_hide' => 'true', + 'to' => '' + ), $vals) + ); + + if($auto_hide === "true" && current_user_can("read")){ + return ''; + } + + // Load Javascript & CSS + if(!wp_script_is('wwa_frontend_js')){ + wwa_localize_frontend(); + } + wp_enqueue_style('wwa_frondend_css', plugins_url('css/frontend.css', __FILE__), array(), get_option('wwa_version')['version']); + + $html_form = ''; + + return $html_form; +} +add_shortcode('wwa_login_form', 'wwa_login_form_shortcode'); + +// Register form +function wwa_register_form_shortcode($vals){ + extract(shortcode_atts( + array( + 'display' => 'true' + ), $vals) + ); + + // If always display + if(!current_user_can("read")){ + if($display === "true"){ + return '

'.__('You haven\'t logged in yet.', 'wp-webauthn').'

'; + }else{ + return ''; + } + } + + // Load Javascript & CSS + if(!wp_script_is('wwa_frontend_js')){ + wwa_localize_frontend(); + } + wp_enqueue_style('wwa_frondend_css', plugins_url('css/frontend.css', __FILE__), array(), get_option('wwa_version')['version']); + + $allowed_type = wwa_get_option('allow_authenticator_type') === false ? 'none' : wwa_get_option('allow_authenticator_type'); + return '

'.__('If a type is selected, the browser will only prompt for authenticators of selected type.
Regardless of the type, you can only log in with the very same authenticators you\'ve registered.', 'wp-webauthn').'

'.__('An easily identifiable name for the authenticator. DOES NOT affect the authentication process in anyway.', 'wp-webauthn').'

'.((wwa_get_option('usernameless_login') === "true") ? '

'.__('If registered authenticator with this feature, you can login without enter your username.
Some authenticators like U2F-only authenticators and some browsers DO NOT support this feature.
A record will be stored in the authenticator permanently untill you reset it.', 'wp-webauthn').'

' : '').'

     

'; +} +add_shortcode('wwa_register_form', 'wwa_register_form_shortcode'); + +// Verify button +function wwa_verify_button_shortcode($vals){ + extract(shortcode_atts( + array( + 'display' => 'true' + ), $vals) + ); + + // If always display + if(!current_user_can("read")){ + if($display === "true"){ + return '

'.__('You haven\'t logged in yet.', 'wp-webauthn').'

'; + }else{ + return ''; + } + } + + // Load Javascript + if(!wp_script_is('wwa_frontend_js')){ + wwa_localize_frontend(); + } + + return '

     '.(wwa_get_option('usernameless_login') === "true" ? '
     ' : '').'

'; +} +add_shortcode('wwa_verify_button', 'wwa_verify_button_shortcode'); + +// Authenticator list +function wwa_list_shortcode($vals){ + extract(shortcode_atts( + array( + 'display' => 'true' + ), $vals) + ); + + $thead = '
'; + $tbody = ''; + $tfoot = '
'.__('Identifier', 'wp-webauthn').''.__('Type', 'wp-webauthn').''._x('Registered', 'time', 'wp-webauthn').''.__('Last used', 'time', 'wp-webauthn').''.__('Usernameless', 'wp-webauthn').''.__('Action', 'wp-webauthn').'
'.__('Loading...', 'wp-webauthn').'
'.__('Identifier', 'wp-webauthn').''.__('Type', 'wp-webauthn').''._x('Registered', 'time', 'wp-webauthn').''.__('Last used', 'time', 'wp-webauthn').''.__('Usernameless', 'wp-webauthn').''.__('Action', 'wp-webauthn').'

'; + + // If always display + if(!current_user_can("read")){ + if($display === "true"){ + // Load CSS + wp_enqueue_style('wwa_frondend_css', plugins_url('css/frontend.css', __FILE__), array(), get_option('wwa_version')['version']); + + return $thead.''.__('You haven\'t logged in yet.', 'wp-webauthn').''.$tfoot; + }else{ + return ''; + } + } + + // Load Javascript & CSS + if(!wp_script_is('wwa_frontend_js')){ + wwa_localize_frontend(); + } + wp_enqueue_style('wwa_frondend_css', plugins_url('css/frontend.css', __FILE__), array(), get_option('wwa_version')['version']); + + return $thead.$tbody.$tfoot; +} +add_shortcode('wwa_list', 'wwa_list_shortcode'); +?> \ No newline at end of file diff --git a/wp-content/plugins/wp-webauthn/wwa-version.php b/wp-content/plugins/wp-webauthn/wwa-version.php new file mode 100644 index 00000000..3aca94cf --- /dev/null +++ b/wp-content/plugins/wp-webauthn/wwa-version.php @@ -0,0 +1,6 @@ + '1.2.8', + 'commit' => '52a8892' +); +?> \ No newline at end of file

WP-WebAuthn

+localhost
.', 'wp-webauthn')); + $wwa_not_allowed = true; +} +// Only admin can change settings +// if((isset($_POST['wwa_ref']) && $_POST['wwa_ref'] === 'true') && check_admin_referer('wwa_options_update') && wwa_validate_privileges() && ($_POST['first_choice'] === 'true' || $_POST['first_choice'] === 'false' || $_POST['first_choice'] === 'webauthn') && ($_POST['remember_me'] === 'true' || $_POST['remember_me'] === 'false') && ($_POST['user_verification'] === 'true' || $_POST['user_verification'] === 'false') && ($_POST['usernameless_login'] === 'true' || $_POST['usernameless_login'] === 'false') && ($_POST['allow_authenticator_type'] === 'none' || $_POST['allow_authenticator_type'] === 'platform' || $_POST['allow_authenticator_type'] === 'cross-platform') && ($_POST['after_user_registration'] === 'none' || $_POST['after_user_registration'] === 'login' || $_POST['after_user_registration'] === 'guide') && ($_POST['logging'] === 'true' || $_POST['logging'] === 'false')){ +if((isset($_POST['wwa_ref']) && $_POST['wwa_ref'] === 'true') && check_admin_referer('wwa_options_update') && wwa_validate_privileges() && ($_POST['first_choice'] === 'true' || $_POST['first_choice'] === 'false' || $_POST['first_choice'] === 'webauthn') && ($_POST['remember_me'] === 'true' || $_POST['remember_me'] === 'false') && ($_POST['user_verification'] === 'true' || $_POST['user_verification'] === 'false') && ($_POST['usernameless_login'] === 'true' || $_POST['usernameless_login'] === 'false') && ($_POST['allow_authenticator_type'] === 'none' || $_POST['allow_authenticator_type'] === 'platform' || $_POST['allow_authenticator_type'] === 'cross-platform') && ($_POST['logging'] === 'true' || $_POST['logging'] === 'false')){ + $res_id = wwa_generate_random_string(5); + if(sanitize_text_field($_POST['logging']) === 'true' && wwa_get_option('logging') === 'false'){ + // Initialize log + if(!function_exists('gmp_intval')){ + wwa_add_log($res_id, 'Warning: PHP extension gmp not found', true); + } + if(!function_exists('mb_substr')){ + wwa_add_log($res_id, 'Warning: PHP extension mbstring not found', true); + } + if(!function_exists('sodium_crypto_sign_detached')){ + wwa_add_log($res_id, 'Warning: PHP extension sodium not found', true); + } + if(!wwa_check_ssl() && (parse_url(site_url(), PHP_URL_HOST) !== 'localhost' && parse_url(site_url(), PHP_URL_HOST) !== '127.0.0.1')){ + wwa_add_log($res_id, 'Warning: Not in security context', true); + } + wwa_add_log($res_id, 'PHP Version => '.phpversion().', WordPress Version => '.get_bloginfo('version').', WP-WebAuthn Version => '.get_option('wwa_version')['version'], true); + // wwa_add_log($res_id, 'Current config: first_choice => "'.wwa_get_option('first_choice').'", website_name => "'.wwa_get_option('website_name').'", website_domain => "'.wwa_get_option('website_domain').'", remember_me => "'.wwa_get_option('remember_me').'", user_verification => "'.wwa_get_option('user_verification').'", allow_authenticator_type => "'.wwa_get_option('allow_authenticator_type').'", usernameless_login => "'.wwa_get_option('usernameless_login').'", after_user_registration => "'.wwa_get_option('after_user_registration').'"', true); + wwa_add_log($res_id, 'Current config: first_choice => "'.wwa_get_option('first_choice').'", website_name => "'.wwa_get_option('website_name').'", website_domain => "'.wwa_get_option('website_domain').'", remember_me => "'.wwa_get_option('remember_me').'", user_verification => "'.wwa_get_option('user_verification').'", allow_authenticator_type => "'.wwa_get_option('allow_authenticator_type').'", usernameless_login => "'.wwa_get_option('usernameless_login').'"', true); + wwa_add_log($res_id, 'Logger initialized', true); + } + wwa_update_option('logging', sanitize_text_field($_POST['logging'])); + + $post_first_choice = sanitize_text_field($_POST['first_choice']); + if($post_first_choice !== wwa_get_option('first_choice')){ + wwa_add_log($res_id, 'first_choice: "'.wwa_get_option('first_choice').'"->"'.$post_first_choice.'"'); + } + wwa_update_option('first_choice', $post_first_choice); + + $post_website_name = sanitize_text_field($_POST['website_name']); + if($post_website_name !== wwa_get_option('website_name')){ + wwa_add_log($res_id, 'website_name: "'.wwa_get_option('website_name').'"->"'.$post_website_name.'"'); + } + wwa_update_option('website_name', $post_website_name); + + $post_website_domain = str_replace('https:', '', str_replace('/', '', sanitize_text_field($_POST['website_domain']))); + if($post_website_domain !== wwa_get_option('website_domain')){ + wwa_add_log($res_id, 'website_domain: "'.wwa_get_option('website_domain').'"->"'.$post_website_domain.'"'); + } + wwa_update_option('website_domain', $post_website_domain); + + $post_remember_me = sanitize_text_field($_POST['remember_me']); + if($post_remember_me !== wwa_get_option('remember_me')){ + wwa_add_log($res_id, 'remember_me: "'.wwa_get_option('remember_me').'"->"'.$post_remember_me.'"'); + } + wwa_update_option('remember_me', $post_remember_me); + + $post_user_verification = sanitize_text_field($_POST['user_verification']); + if($post_user_verification !== wwa_get_option('user_verification')){ + wwa_add_log($res_id, 'user_verification: "'.wwa_get_option('user_verification').'"->"'.$post_user_verification.'"'); + } + wwa_update_option('user_verification', $post_user_verification); + + $post_allow_authenticator_type = sanitize_text_field($_POST['allow_authenticator_type']); + if($post_allow_authenticator_type !== wwa_get_option('allow_authenticator_type')){ + wwa_add_log($res_id, 'allow_authenticator_type: "'.wwa_get_option('allow_authenticator_type').'"->"'.$post_allow_authenticator_type.'"'); + } + wwa_update_option('allow_authenticator_type', $post_allow_authenticator_type); + + $post_usernameless_login = sanitize_text_field($_POST['usernameless_login']); + if($post_usernameless_login !== wwa_get_option('usernameless_login')){ + wwa_add_log($res_id, 'usernameless_login: "'.wwa_get_option('usernameless_login').'"->"'.$post_usernameless_login.'"'); + } + wwa_update_option('usernameless_login', $post_usernameless_login); + + // $post_after_user_registration = sanitize_text_field($_POST['after_user_registration']); + // if($post_after_user_registration !== wwa_get_option('after_user_registration')){ + // wwa_add_log($res_id, 'after_user_registration: "'.wwa_get_option('after_user_registration').'"->"'.$post_after_user_registration.'"'); + // } + // wwa_update_option('after_user_registration', $post_after_user_registration); + + add_settings_error('wwa_settings', 'save_success', __('Settings saved.', 'wp-webauthn'), 'success'); +}elseif((isset($_POST['wwa_ref']) && $_POST['wwa_ref'] === 'true')){ + add_settings_error('wwa_settings', 'save_error', __('Settings NOT saved.', 'wp-webauthn')); +} +settings_errors('wwa_settings'); + +wp_localize_script('wwa_admin', 'configs', array('usernameless' => (wwa_get_option('usernameless_login') === false ? 'false' : wwa_get_option('usernameless_login')), 'allow_authenticator_type' => (wwa_get_option('allow_authenticator_type') === false ? 'none' : wwa_get_option('allow_authenticator_type')))); + +// Only admin can change settings +if(wwa_validate_privileges()){ ?> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

User that doesn\'t have any registered authenticator (e.g. new user) will unable to login when using "WebAuthn Only".
When the browser does not support WebAuthn, the login method will default to password if password login is not disabled.', 'wp-webauthn');?>

+
+ +

DOES NOT affect the authentication process in anyway.', 'wp-webauthn');?>

+
+ +

MUST be exactly the same with the current domain or parent domain.', 'wp-webauthn');?>

+
+ +
+
+
+

+
+
+ +
+
+
+

If you cannot register or verify your authenticators, please consider disabling user verification.', 'wp-webauthn');?>

+
+
+ +
+
+
+

User verification will be enabled automatically when authenticating with usernameless authentication feature.
Some authenticators and some browsers DO NOT support this feature.', 'wp-webauthn');?>

+
+
+ + +

+
+ +
+
+
+

+       +

+

Note: Logs may contain sensitive information.', 'wp-webauthn');?>

+
+
+ 0)){ +?> + id="wwa-remove-log"> +

+ +

+
+