installed plugin `WP-WebAuthn` version 1.2.8

This commit is contained in:
KawaiiPunk 2022-10-08 02:41:03 +00:00 committed by Gitium
parent 15c71c7c0f
commit 7b1024e711
923 changed files with 124568 additions and 0 deletions

View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 <https://www.gnu.org/licenses/>.
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:
<program> Copyright (C) <year> <name of author>
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
<https://www.gnu.org/licenses/>.
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
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -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}]);

View File

@ -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"]}}}

View File

@ -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"]}}}

View File

@ -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"]}}}

View File

@ -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"]}}}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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(`<div class="notice notice-warning" role="alert" id="wp-webauthn-uv-warning"><p>${php_vars.i18n_1}</p></div>`);
} else {
jQuery('#wp-webauthn-uv-warning').remove();
}
});
setTimeout(() => {
if (jQuery('input[name=user_verification]:checked').val() === 'false') {
jQuery('#wwa-uv-field').after(`<div class="notice notice-warning" role="alert" id="wp-webauthn-uv-warning"><p>${php_vars.i18n_1}</p></div>`);
}
}, 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();
}
})
})

View File

@ -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 = `<span id="wwa-username-label">${php_vars.i18n_9}</span>${dom[0].innerHTML.split('<br>')[1]}`;
} else {
dom[0].innerText = php_vars.i18n_9;
}
}
}
})

View File

@ -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 = `<tr><td colspan="${document.getElementsByClassName('wwa-usernameless-th')[0].style.display === 'none' ? '5' : '6'}">${wwa_php_vars.i18n_17}</td></tr>` }, '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 = `<tr><td colspan="${document.getElementsByClassName('wwa-usernameless-th')[0].style.display === 'none' ? '5' : '6'}">${wwa_php_vars.i18n_23}</td></tr>` }, '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 += `<tr><td>${item.name}</td><td>${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 : ''}</td><td>${item.added}</td><td>${item.last_used}</td><td class="wwa-usernameless-td">${item.usernameless ? wwa_php_vars.i18n_1 + (wwa_php_vars.usernameless === 'true' ? '' : wwa_php_vars.i18n_9) : wwa_php_vars.i18n_8}</td><td class="wwa-key-${item.key}"><a href="javascript:renameAuthenticator('${item.key}', '${item.name}')">${wwa_php_vars.i18n_20}</a> | <a href="javascript:removeAuthenticator('${item.key}', '${item.name}')">${wwa_php_vars.i18n_27}</a></td></tr>`;
}
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 = `<tr><td colspan="${document.getElementsByClassName('wwa-usernameless-th')[0].style.display === 'none' ? '5' : '6'}">${wwa_php_vars.i18n_17}</td></tr>` }, '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();
}
})
}
}

View File

@ -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 = '<span class="dashicons dashicons-update-alt"></span>';
}
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 = `<span><span class="dashicons dashicons-shield-alt"></span> ${php_vars.i18n_2}<span>`;
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 = `<span><span class="dashicons dashicons-shield-alt"></span> ${php_vars.i18n_2}</span>` }, '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 = `<span><span class="dashicons dashicons-shield-alt"></span> ${php_vars.i18n_2}</span>` }, '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 });
}
})
}
}

View File

@ -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(`<tr><td colspan="${jQuery('.wwa-usernameless-th').css('display') === 'none' ? '5' : '6'}">${php_vars.i18n_8}</td></tr>`);
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(`<tr><td colspan="${jQuery('.wwa-usernameless-th').css('display') === 'none' ? '5' : '6'}">${php_vars.i18n_17}</td></tr>`);
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 += `<tr><td>${item.name}</td><td>${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 : ''}</td><td>${item.added}</td><td>${item.last_used}</td><td class="wwa-usernameless-td">${item.usernameless ? php_vars.i18n_24 + (configs.usernameless === 'true' ? '' : php_vars.i18n_26) : php_vars.i18n_25}</td><td id="${item.key}"><a href="javascript:renameAuthenticator('${item.key}', '${item.name}')">${php_vars.i18n_20}</a> | <a href="javascript:removeAuthenticator('${item.key}', '${item.name}')">${php_vars.i18n_12}</a></td></tr>`;
}
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(`<tr><td colspan="${jQuery('.wwa-usernameless-th').css('display') === 'none' ? '5' : '6'}">${php_vars.i18n_8}</td></tr>`);
}
})
}
/** 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();
}
})
}
}

View File

@ -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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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 <code>localhost</code>."
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.<br>User that doesn't have any registered authenticator (e.g. new user) will unable to login when using \"WebAuthn Only\".<br>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 <strong>DOES NOT</strong> affect the authentication process in anyway."
msgstr ""
#: wwa-admin-content.php:123
msgid "Website domain"
msgstr ""
#: wwa-admin-content.php:126
msgid "This field <strong>MUST</strong> 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. <br> 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.<br><strong>User verification will be enabled automatically when authenticating with usernameless authentication feature.</strong><br>Some authenticators and some browsers <strong>DO NOT</strong> 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.<br><strong>Note: Logs may contain sensitive information.</strong>"
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 <a href=\"%s#wwa-webauthn-start\">your profile</a>."
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 "<strong>Error</strong>: 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. <a href=\"%s#wwa-webauthn-start\">Register</a>"
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 <strong>this account</strong> 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 <strong>%s</strong>.<br>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. <br> 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. <strong>DOES NOT</strong> 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.<br>Some authenticators like U2F-only authenticators and some browsers <strong>DO NOT</strong> support this feature.<br>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 ""

View File

@ -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 lenregistrement"
#: 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 lenregistrement"
#: 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 lidentifiant 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 dactualiser ?"
#: 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 ""
"Ladministrateur du site a désactivé la fonctionnalité permettant les "
"connexions sans nom dutilisateur."
#: 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 ""
"Lextension 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 ""
"Lextension 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 <code>localhost</code>"
"."
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 <code>localhost</code>."
#: 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 dutilisateur + 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 <strong>CANNOT completely "
"disable the traditional Username+Password method</strong><br>Regardless of "
"the preferred method, you will be able to switch to the other with a switch "
"button at the login page. <br> 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 "
"<strong>NE POUVEZ PAS désactiver complètement la méthode traditionnelle du "
"nom d'utilisateur + mot de passe</strong><br>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.<br>Lorsque le navigateur ne prend pas en charge Webauthn, "
"la méthode de connexion sera par défaut le nom dutilisateur + 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 <strong>DOES "
"NOT</strong> affect the authentication process in anyway."
msgstr ""
"Cet identifiant est utilisé seulement à des fins d'identification et <strong>"
"NA PAS</strong> d'incidence sur le processus dauthentification."
#: wwa-admin-content.php:97
msgid "Website domain"
msgstr "Domaine du site web"
#: wwa-admin-content.php:100
msgid ""
"This field <strong>MUST</strong> be exactly the same with the current domain "
"or parent domain."
msgstr ""
"Ce champs <strong>DOIT</strong> ê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 lutilisateur 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. <br> 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 nest pas "
"entièrement prise en charge par certains périphériques.<br>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 dutilisateur"
#: wwa-admin-content.php:126
msgid ""
"Allow users to register authenticator with usernameless authentication "
"feature and login without username.<br><strong>User verification will be "
"enabled automatically when registering authenticator with usernameless "
"authentication feature.</strong><br>Some authenticators and some browsers "
"<strong>DO NOT</strong> support this feature."
msgstr ""
"Autoriser les utilisateurs à enregistrer un périphérique avec cette fonction "
"leur permettra de se connecter sans nom d'utilisateur.<br><strong>La "
"vérification de l'utilisateur sera activée automatiquement lors de "
"l'enregistrement du périphérique.</strong><br>Certains dentre eux et "
"certains navigateurs <strong>NE SUPPORTENT PAS</strong> 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.<br><strong>Note: Logs may "
"contain sensitive information.</strong>"
msgstr ""
"Pour le débogage uniquement. Activer lorsque cela est nécessaire.<br><strong>"
"Remarque : les registres peuvent contenir des informations sensibles."
"</strong>"
#: 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 <strong>the current "
"account</strong>. You can register multiple authenticators for an account. "
"<br> If you want to register authenticators for other users, please log in "
"using that account."
msgstr ""
"Vous êtes sur le point dassocier un périphérique au <strong>compte "
"actuel</strong>. Vous pouvez enregistrer plusieurs périphérique pour un même "
"compte.<br>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 dempreinte 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. <br> 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é.<br>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. <strong>DOES NOT</strong> "
"affect the authentication process in anyway."
msgstr ""
"Un nom facilement identifiable pour le périphérique. Cela na <strong>"
"AUCUNE</strong> incidence sur le processus d'authentification."
#: wwa-admin-content.php:184, wwa-shortcodes.php:75
msgid "Login without username"
msgstr "Connexion sur nom dutilisateur"
#: wwa-admin-content.php:189, wwa-shortcodes.php:75
msgid ""
"If registered authenticator with this feature, you can login without enter "
"your username.<br>Some authenticators like U2F-only authenticators and some "
"browsers <strong>DO NOT</strong> support this feature.<br>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 dutilisateur.<br>Certains "
"périphériques tels que les anciens modèles FIDO-U2F et certains navigateurs "
"<strong>NE SONT PAS</strong> compatible avec cette fonctionnalité.<br>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 lenregistrement"
#: 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 dutilisateur"
#: 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 lenregistrement"
#: 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 dutilisateur)"
#: 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 dauthentification"
#: wwa-functions.php:120, wwa-shortcodes.php:46
msgid "Username"
msgstr "Nom dutilisateur"
#: wwa-functions.php:120
msgid "Username or Email Address"
msgstr "Nom dutilisateur ou adresse email"
#: wwa-functions.php:120
msgid "<strong>Error</strong>: The username field is empty."
msgstr "<strong>Erreur</strong>: Le nom dutilisateur est vide."
#: wwa-functions.php:120, wwa-shortcodes.php:4
msgid "Try to enter the username"
msgstr "Essayez de saisir le nom dutilisateur"
#: 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 dutilisateur 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."

View File

@ -0,0 +1,644 @@
# 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"
"Language-Team: \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-SourceCharset: UTF-8\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"X-Generator: Poedit 2.4.2\n"
"Last-Translator: \n"
"Language: tr_TR\n"
"X-Poedit-SearchPath-0: .\n"
"X-Poedit-SearchPathExcluded-0: *.js\n"
#. 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, WordPress sitenize şifre olmadan güvenle giriş yapmanızı sağlar."
#. 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:6 wwa-admin-content.php:202
msgid "Log count: "
msgstr "Günlük sayısı: "
#: wwa-admin-content.php:14
msgid ""
"PHP extension gmp doesn't seem to exist, rendering WP-WebAuthn unable to "
"function."
msgstr ""
"PHP uzantısı gmp yok gibi görünüyor ve WP-WebAuthn işlevini yerine "
"getiremiyor."
#: wwa-admin-content.php:18
msgid ""
"PHP extension mbstring doesn't seem to exist, rendering WP-WebAuthn unable "
"to function."
msgstr ""
"PHP uzantısı mbstring mevcut görünmüyor ve WP-WebAuthn işlevini yerine "
"getiremiyor."
#: 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 <code>localhost</"
"code>."
msgstr ""
"WebAuthn özellikleri, güvenli bağlamlardaki web siteleriyle sınırlıdır. "
"Lütfen web sitenizin HTTPS üzerinden veya yerel olarak <code>localhost</"
"code> 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.<br>User that doesn't have any registered authenticator (e.g. new "
"user) will unable to login when using \"WebAuthn Only\".<br>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. <br> Kayıtlı bir kimlik "
"doğrulayıcısı olmayan kullanıcılar (ör. Yeni kullanıcı) \"Yalnızca WebAuthn"
"\" kullanırken oturum açamaz. <br> 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 <strong>DOES NOT</"
"strong> 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 <strong>ETKİLEMEZ</strong>."
#: wwa-admin-content.php:123
msgid "Website domain"
msgstr "Web sitesi domaini"
#: wwa-admin-content.php:126
msgid ""
"This field <strong>MUST</strong> 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ı "
"<strong>OLMALIDIR</strong>."
#: 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. <br> 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. <br> 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.<br><strong>User verification will be "
"enabled automatically when authenticating with usernameless authentication "
"feature.</strong><br>Some authenticators and some browsers <strong>DO NOT</"
"strong> 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. <br> "
"<strong> Kullanılmayan kimlik doğrulama özelliği ile kimlik doğrulaması "
"yapılırken kullanıcı doğrulama otomatik olarak etkinleştirilecektir. </"
"strong> <br> 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.<br><strong>Note: Logs may "
"contain sensitive information.</strong>"
msgstr ""
"Yalnızca hata ayıklama için. Yalnızca gerektiğinde etkinleştirin. "
"<br><strong>Not: Günlükler hassas bilgiler içerebilir.</strong>"
#: 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 <a "
"href=\"%s#wwa-webauthn-start\">your profile</a>."
msgstr ""
"Yeni bir kimlik doğrulayıcı kaydettirmek veya kimlik doğrulayıcılarınızı "
"düzenlemek için lütfen <a href=\"%s#wwa-webauthn-start\"> profilinize </a> "
"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 "<strong>Error</strong>: The username field is empty."
msgstr "<strong>Hata</strong>: 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. <a href=\"%s#wwa-webauthn-start\">Register</a>"
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. <a href=\"%s#wwa-webauthn-start\"> Kaydolun </a>"
#: 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 <strong>this account</"
"strong> 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 <strong>bu hesap</"
"strong> 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 <strong>"
"%s</strong>.<br>You can register multiple authenticators for an account."
msgstr ""
"Bir doğrulayıcıyı geçerli hesapla <strong>%s</strong> ilişkilendirmek "
"üzeresiniz. <br> 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. <br> 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. <br> 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. <strong>DOES NOT</strong> "
"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 <strong>ETKİLEMEZ</strong>."
#: 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.<br>Some authenticators like U2F-only authenticators and some "
"browsers <strong>DO NOT</strong> support this feature.<br>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. <br> Yalnızca U2F kimlik doğrulayıcıları gibi bazı "
"kimlik doğrulayıcılar ve bazı tarayıcılar bu özelliği <strong>DESTEKLEMEZ</"
"strong>. <br> 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"

View File

@ -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

View File

@ -0,0 +1,12 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
exit(1);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit8c7684b956de574bcb0eefe2be31e0ab::getLoader();

View File

@ -0,0 +1,64 @@
on: [push, pull_request]
name: CI
jobs:
tests:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: "cs2pr"
- name: "Cache dependencies installed with composer"
uses: "actions/cache@v1"
with:
path: "~/.composer/cache"
key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
restore-keys: "php-${{ matrix.php-version }}-composer-locked-"
- name: "Composer"
run: "composer update --prefer-stable"
- name: "PHPUnit"
run: "php vendor/bin/phpunit"
# lint:
# name: Lint
# runs-on: ubuntu-latest
# steps:
# - name: Checkout
# uses: actions/checkout@v1
# - name: Setup PHP
# uses: shivammathur/setup-php@v2
# with:
# php-version: 7.4
# - name: "Cache dependencies installed with composer"
# uses: "actions/cache@v1"
# with:
# path: "~/.composer/cache"
# key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
# restore-keys: "php-${{ matrix.php-version }}-composer-locked-"
# - name: "Composer"
# run: "composer update --prefer-stable"
# - name: "assert:cs-lint"
# run: "composer assert:cs-lint"
# - name: "assert:sa-code"
# run: "composer assert:sa-code"
# - name: "assert:sa-tests"
# run: "composer assert:sa-tests"

View File

@ -0,0 +1,11 @@
Copyright (c) 2011-2013, Benjamin Eberlei
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

View File

@ -0,0 +1,64 @@
{
"name": "beberlei/assert",
"description": "Thin assertion library for input validation in business models.",
"authors": [
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de",
"role": "Lead Developer"
},
{
"name": "Richard Quadling",
"email": "rquadling@gmail.com",
"role": "Collaborator"
}
],
"license": "BSD-2-Clause",
"keywords": [
"assert",
"assertion",
"validation"
],
"config": {
"sort-packages": true
},
"require": {
"php": "^7.0 || ^8.0",
"ext-simplexml": "*",
"ext-mbstring": "*",
"ext-ctype": "*",
"ext-json": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "*",
"phpstan/phpstan": "*",
"phpunit/phpunit": ">=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"
}
}

View File

@ -0,0 +1,85 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
/**
* AssertionChain factory.
*/
abstract class Assert
{
/** @var string */
protected static $lazyAssertionExceptionClass = LazyAssertionException::class;
/** @var string */
protected static $assertionClass = Assertion::class;
/**
* Start validation on a value, returns {@link AssertionChain}.
*
* The invocation of this method starts an assertion chain
* that is happening on the passed value.
*
* @param mixed $value
* @param string|callable|null $defaultMessage
*
* @example
*
* Assert::that($value)->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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,247 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
use LogicException;
/**
* Chaining builder for assertions.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*
* @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;
}
}

View File

@ -0,0 +1,32 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
use Throwable;
interface AssertionFailedException extends Throwable
{
/**
* @return string|null
*/
public function getPropertyPath();
/**
* @return mixed
*/
public function getValue();
public function getConstraints(): array;
}

View File

@ -0,0 +1,74 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
class InvalidArgumentException extends \InvalidArgumentException implements AssertionFailedException
{
/**
* @var string|null
*/
private $propertyPath;
/**
* @var mixed
*/
private $value;
/**
* @var array
*/
private $constraints;
public function __construct($message, $code, string $propertyPath = null, $value = null, array $constraints = [])
{
parent::__construct($message, $code);
$this->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;
}
}

View File

@ -0,0 +1,228 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
use LogicException;
/**
* Chaining builder for lazy assertions.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*
* @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;
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
class LazyAssertionException extends InvalidArgumentException
{
/**
* @var InvalidArgumentException[]
*/
private $errors = [];
/**
* @param InvalidArgumentException[] $errors
*/
public static function fromErrors(array $errors): self
{
$message = \sprintf('The following %d assertions failed:', \count($errors))."\n";
$i = 1;
foreach ($errors as $error) {
$message .= \sprintf("%d) %s: %s\n", $i++, $error->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;
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
/**
* Start validation on a value, returns {@link AssertionChain}.
*
* The invocation of this method starts an assertion chain
* that is happening on the passed value.
*
* @param mixed $value
* @param string|callable|null $defaultMessage
* @param string $defaultPropertyPath
*
* @example
*
* \Assert\that($value)->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();
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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/"
}
}
}

View File

@ -0,0 +1,895 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NegativeNumberException;
use Brick\Math\Internal\Calculator;
/**
* Immutable, arbitrary-precision signed decimal numbers.
*
* @psalm-immutable
*/
final class BigDecimal extends BigNumber
{
/**
* The unscaled value of this decimal number.
*
* This is a string of digits with an optional leading minus sign.
* No leading zero must be present.
* No leading minus sign must be present if the value is 0.
*
* @var string
*/
private $value;
/**
* The scale (number of digits after the decimal point) of this decimal number.
*
* This must be zero or more.
*
* @var int
*/
private $scale;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param string $value The unscaled value, validated.
* @param int $scale The scale, validated.
*/
protected function __construct(string $value, int $scale = 0)
{
$this->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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,572 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
/**
* Common interface for arbitrary-precision rational numbers.
*
* @psalm-immutable
*/
abstract class BigNumber implements \Serializable, \JsonSerializable
{
/**
* The regular expression used to parse integer, decimal and rational numbers.
*/
private const PARSE_REGEXP =
'/^' .
'(?<sign>[\-\+])?' .
'(?:' .
'(?:' .
'(?<integral>[0-9]+)?' .
'(?<point>\.)?' .
'(?<fractional>[0-9]+)?' .
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
')|(?:' .
'(?<numerator>[0-9]+)' .
'\/?' .
'(?<denominator>[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();
}
}

View File

@ -0,0 +1,523 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
/**
* An arbitrarily large rational number.
*
* This class is immutable.
*
* @psalm-immutable
*/
final class BigRational extends BigNumber
{
/**
* The numerator.
*
* @var BigInteger
*/
private $numerator;
/**
* The denominator. Always strictly positive.
*
* @var BigInteger
*/
private $denominator;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param BigInteger $numerator The numerator.
* @param BigInteger $denominator The denominator.
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
*
* @throws DivisionByZeroException If the denominator is zero.
*/
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
{
if ($checkDenominator) {
if ($denominator->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);
}
}

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when a division by zero occurs.
*/
class DivisionByZeroException extends MathException
{
/**
* @return DivisionByZeroException
*
* @psalm-pure
*/
public static function divisionByZero() : DivisionByZeroException
{
return new self('Division by zero.');
}
/**
* @return DivisionByZeroException
*
* @psalm-pure
*/
public static function modulusMustNotBeZero() : DivisionByZeroException
{
return new self('The modulus must not be zero.');
}
/**
* @return DivisionByZeroException
*
* @psalm-pure
*/
public static function denominatorMustNotBeZero() : DivisionByZeroException
{
return new self('The denominator of a rational number cannot be zero.');
}
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
use Brick\Math\BigInteger;
/**
* Exception thrown when an integer overflow occurs.
*/
class IntegerOverflowException extends MathException
{
/**
* @param BigInteger $value
*
* @return IntegerOverflowException
*
* @psalm-pure
*/
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
{
$message = '%s is out of range %d to %d and cannot be represented as an integer.';
return new self(\sprintf($message, (string) $value, PHP_INT_MIN, PHP_INT_MAX));
}
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Base class for all math exceptions.
*
* This class is abstract to ensure that only fine-grained exceptions are thrown throughout the code.
*/
class MathException extends \RuntimeException
{
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
*/
class NegativeNumberException extends MathException
{
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to create a number from a string with an invalid format.
*/
class NumberFormatException extends MathException
{
/**
* @param string $char The failing character.
*
* @return NumberFormatException
*
* @psalm-pure
*/
public static function charNotInAlphabet(string $char) : self
{
$ord = \ord($char);
if ($ord < 32 || $ord > 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));
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when a number cannot be represented at the requested scale without rounding.
*/
class RoundingNecessaryException extends MathException
{
/**
* @return RoundingNecessaryException
*
* @psalm-pure
*/
public static function roundingNecessary() : RoundingNecessaryException
{
return new self('Rounding is necessary to represent the result of the operation at this scale.');
}
}

View File

@ -0,0 +1,756 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal;
use Brick\Math\Exception\RoundingNecessaryException;
use Brick\Math\RoundingMode;
/**
* Performs basic operations on arbitrary size integers.
*
* Unless otherwise specified, all parameters must be validated as non-empty strings of digits,
* without leading zero, and with an optional leading minus sign if the number is not zero.
*
* Any other parameter format will lead to undefined behaviour.
* All methods must return strings respecting this format, unless specified otherwise.
*
* @internal
*
* @psalm-immutable
*/
abstract class Calculator
{
/**
* The maximum exponent value allowed for the pow() method.
*/
public const MAX_POWER = 1000000;
/**
* The alphabet for converting from and to base 2 to 36, lowercase.
*/
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
/**
* The Calculator instance in use.
*
* @var Calculator|null
*/
private static $instance;
/**
* Sets the Calculator instance to use.
*
* An instance is typically set only in unit tests: the autodetect is usually the best option.
*
* @param Calculator|null $calculator The calculator instance, or NULL to revert to autodetect.
*
* @return void
*/
final public static function set(?Calculator $calculator) : void
{
self::$instance = $calculator;
}
/**
* Returns the Calculator instance to use.
*
* If none has been explicitly set, the fastest available implementation will be returned.
*
* @return Calculator
*
* @psalm-pure
* @psalm-suppress ImpureStaticProperty
*/
final public static function get() : Calculator
{
if (self::$instance === null) {
/** @psalm-suppress ImpureMethodCall */
self::$instance = self::detect();
}
return self::$instance;
}
/**
* Returns the fastest available Calculator implementation.
*
* @codeCoverageIgnore
*
* @return Calculator
*/
private static function detect() : Calculator
{
if (\extension_loaded('gmp')) {
return new Calculator\GmpCalculator();
}
if (\extension_loaded('bcmath')) {
return new Calculator\BcMathCalculator();
}
return new Calculator\NativeCalculator();
}
/**
* Extracts the sign & digits of the operands.
*
* @param string $a The first operand.
* @param string $b The second operand.
*
* @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
*/
final protected function init(string $a, string $b) : array
{
return [
$aNeg = ($a[0] === '-'),
$bNeg = ($b[0] === '-'),
$aNeg ? \substr($a, 1) : $a,
$bNeg ? \substr($b, 1) : $b,
];
}
/**
* Returns the absolute value of a number.
*
* @param string $n The number.
*
* @return string The absolute value.
*/
final public function abs(string $n) : string
{
return ($n[0] === '-') ? \substr($n, 1) : $n;
}
/**
* Negates a number.
*
* @param string $n The number.
*
* @return string The negated value.
*/
final public function neg(string $n) : string
{
if ($n === '0') {
return '0';
}
if ($n[0] === '-') {
return \substr($n, 1);
}
return '-' . $n;
}
/**
* Compares two numbers.
*
* @param string $a The first number.
* @param string $b The second number.
*
* @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
*/
final public function cmp(string $a, string $b) : int
{
[$aNeg, $bNeg, $aDig, $bDig] = $this->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 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;
}
}

View File

@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
/**
* Calculator implementation built around the bcmath library.
*
* @internal
*
* @psalm-immutable
*/
class BcMathCalculator extends Calculator
{
/**
* {@inheritdoc}
*/
public function add(string $a, string $b) : string
{
return \bcadd($a, $b, 0);
}
/**
* {@inheritdoc}
*/
public function sub(string $a, string $b) : string
{
return \bcsub($a, $b, 0);
}
/**
* {@inheritdoc}
*/
public function mul(string $a, string $b) : string
{
return \bcmul($a, $b, 0);
}
/**
* {@inheritdoc}
*
* @psalm-suppress InvalidNullableReturnType
* @psalm-suppress NullableReturnStatement
*/
public function divQ(string $a, string $b) : string
{
return \bcdiv($a, $b, 0);
}
/**
* {@inheritdoc}
*
* @psalm-suppress InvalidNullableReturnType
* @psalm-suppress NullableReturnStatement
*/
public function divR(string $a, string $b) : string
{
if (version_compare(PHP_VERSION, '7.2') >= 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);
}
}

View File

@ -0,0 +1,156 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
/**
* Calculator implementation built around the GMP library.
*
* @internal
*
* @psalm-immutable
*/
class GmpCalculator extends Calculator
{
/**
* {@inheritdoc}
*/
public function add(string $a, string $b) : string
{
return \gmp_strval(\gmp_add($a, $b));
}
/**
* {@inheritdoc}
*/
public function sub(string $a, string $b) : string
{
return \gmp_strval(\gmp_sub($a, $b));
}
/**
* {@inheritdoc}
*/
public function mul(string $a, string $b) : string
{
return \gmp_strval(\gmp_mul($a, $b));
}
/**
* {@inheritdoc}
*/
public function divQ(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_q($a, $b));
}
/**
* {@inheritdoc}
*/
public function divR(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_r($a, $b));
}
/**
* {@inheritdoc}
*/
public function divQR(string $a, string $b) : array
{
[$q, $r] = \gmp_div_qr($a, $b);
return [
\gmp_strval($q),
\gmp_strval($r)
];
}
/**
* {@inheritdoc}
*/
public function pow(string $a, int $e) : string
{
return \gmp_strval(\gmp_pow($a, $e));
}
/**
* {@inheritdoc}
*/
public function modInverse(string $x, string $m) : ?string
{
$result = \gmp_invert($x, $m);
if ($result === false) {
return null;
}
return \gmp_strval($result);
}
/**
* {@inheritdoc}
*/
public function modPow(string $base, string $exp, string $mod) : string
{
return \gmp_strval(\gmp_powm($base, $exp, $mod));
}
/**
* {@inheritdoc}
*/
public function gcd(string $a, string $b) : string
{
return \gmp_strval(\gmp_gcd($a, $b));
}
/**
* {@inheritdoc}
*/
public function fromBase(string $number, int $base) : string
{
return \gmp_strval(\gmp_init($number, $base));
}
/**
* {@inheritdoc}
*/
public function toBase(string $number, int $base) : string
{
return \gmp_strval($number, $base);
}
/**
* {@inheritdoc}
*/
public function and(string $a, string $b) : string
{
return \gmp_strval(\gmp_and($a, $b));
}
/**
* {@inheritdoc}
*/
public function or(string $a, string $b) : string
{
return \gmp_strval(\gmp_or($a, $b));
}
/**
* {@inheritdoc}
*/
public function xor(string $a, string $b) : string
{
return \gmp_strval(\gmp_xor($a, $b));
}
/**
* {@inheritDoc}
*/
public function sqrt(string $n) : string
{
return \gmp_strval(\gmp_sqrt($n));
}
}

View File

@ -0,0 +1,634 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
/**
* Calculator implementation using only native PHP code.
*
* @internal
*
* @psalm-immutable
*/
class NativeCalculator extends Calculator
{
/**
* The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
* For multiplication, this represents the max sum of the lengths of both operands.
*
* For addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
* Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
*
* @var int
*/
private $maxDigits;
/**
* Class constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
switch (PHP_INT_SIZE) {
case 4:
$this->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];
}
}

View File

@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
/**
* Specifies a rounding behavior for numerical operations capable of discarding precision.
*
* Each rounding mode indicates how the least significant returned digit of a rounded result
* is to be calculated. If fewer digits are returned than the digits needed to represent the
* exact numerical result, the discarded digits will be referred to as the discarded fraction
* regardless the digits' contribution to the value of the number. In other words, considered
* as a numerical value, the discarded fraction could have an absolute value greater than one.
*/
final class RoundingMode
{
/**
* Private constructor. This class is not instantiable.
*
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Asserts that the requested operation has an exact result, hence no rounding is necessary.
*
* If this rounding mode is specified on an operation that yields a result that
* cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
*/
public const UNNECESSARY = 0;
/**
* Rounds away from zero.
*
* Always increments the digit prior to a nonzero discarded fraction.
* Note that this rounding mode never decreases the magnitude of the calculated value.
*/
public const UP = 1;
/**
* Rounds towards zero.
*
* Never increments the digit prior to a discarded fraction (i.e., truncates).
* Note that this rounding mode never increases the magnitude of the calculated value.
*/
public const DOWN = 2;
/**
* Rounds towards positive infinity.
*
* If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
* Note that this rounding mode never decreases the calculated value.
*/
public const CEILING = 3;
/**
* Rounds towards negative infinity.
*
* If the result is positive, behave as for DOWN; if negative, behave as for UP.
* Note that this rounding mode never increases the calculated value.
*/
public const FLOOR = 4;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
*
* Behaves as for UP if the discarded fraction is >= 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;
}

View File

@ -0,0 +1,572 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* 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 <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @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<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
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<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $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;
}

View File

@ -0,0 +1,352 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* 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<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
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<string>
*/
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<string>
*/
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<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
*/
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<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
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<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
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;
}
}

View File

@ -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.

View File

@ -0,0 +1,673 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Assert\\Assert' => $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',
);

View File

@ -0,0 +1,103 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'a4ecaeafb8cfb009ad0e052c90355e98' => $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',
);

View File

@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@ -0,0 +1,35 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Webauthn\\MetadataService\\' => 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'),
);

View File

@ -0,0 +1,55 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit8c7684b956de574bcb0eefe2be31e0ab
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit8c7684b956de574bcb0eefe2be31e0ab', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit8c7684b956de574bcb0eefe2be31e0ab', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit8c7684b956de574bcb0eefe2be31e0ab::getInitializer($loader));
$loader->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;
}
}

View File

@ -0,0 +1,960 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit8c7684b956de574bcb0eefe2be31e0ab
{
public static $files = array (
'a4ecaeafb8cfb009ad0e052c90355e98' => __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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,311 @@
<?php return array(
'root' => 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,
),
),
);

View File

@ -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

View File

@ -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]

View File

@ -0,0 +1,19 @@
Copyright (c) 2012-2015 Friedrich Große <friedrich.grosse@gmail.com>
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.

View File

@ -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

View File

@ -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"
}
}
}

View File

@ -0,0 +1,355 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,136 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace FG\ASN1;
use FG\Utility\BigInteger;
use InvalidArgumentException;
/**
* A base-128 decoder.
*/
class Base128
{
/**
* @param int $value
*
* @return string
*/
public static function encode($value)
{
$value = BigInteger::create($value);
$octets = chr($value->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;
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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];
}
}

View File

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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);
}
}

View File

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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();
}
}

View File

@ -0,0 +1,202 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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);
}
}

View File

@ -0,0 +1,15 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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
{
}

View File

@ -0,0 +1,29 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,131 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,339 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}
}

View File

@ -0,0 +1,199 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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('#<tt>(.+)\(\d+\)</tt>#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})";
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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);
}

View File

@ -0,0 +1,70 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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");
}
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,88 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,75 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,134 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,130 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,54 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,26 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,138 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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) ?: '';
}
}

View File

@ -0,0 +1,91 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,53 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* 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;
}
}

Some files were not shown because too many files have changed in this diff Show More