first commit
This commit is contained in:
505
libraries/vendor/algo26-matthias/idna-convert/LICENSE
vendored
Normal file
505
libraries/vendor/algo26-matthias/idna-convert/LICENSE
vendored
Normal file
@ -0,0 +1,505 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
(This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.)
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
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 this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
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
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser 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 Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "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
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY 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
|
||||
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random
|
||||
Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
51
libraries/vendor/algo26-matthias/idna-convert/src/AbstractIdnaConvert.php
vendored
Normal file
51
libraries/vendor/algo26-matthias/idna-convert/src/AbstractIdnaConvert.php
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
abstract class AbstractIdnaConvert
|
||||
{
|
||||
abstract public function convert(string $host): string;
|
||||
|
||||
/**
|
||||
* @param string $emailAddress
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertEmailAddress(string $emailAddress): string
|
||||
{
|
||||
if (strpos($emailAddress, '@') === false) {
|
||||
throw new InvalidArgumentException('The given string does not look like an email address', 206);
|
||||
}
|
||||
|
||||
$parts = explode('@', $emailAddress);
|
||||
|
||||
return sprintf(
|
||||
'%s@%s',
|
||||
$parts[0],
|
||||
$this->convert($parts[1])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convertUrl(string $url): string
|
||||
{
|
||||
$parsed = parse_url($url);
|
||||
if ($parsed === false) {
|
||||
throw new InvalidArgumentException('The given string does not look like a URL', 206);
|
||||
}
|
||||
|
||||
// Nothing to do
|
||||
if (!isset($parsed['host']) || $parsed['host'] === null) {
|
||||
return $url;
|
||||
}
|
||||
$parsed['host'] = $this->convert($parsed['host']);
|
||||
|
||||
return http_build_url($parsed);
|
||||
}
|
||||
}
|
||||
12
libraries/vendor/algo26-matthias/idna-convert/src/EncodingHelper/EncodingHelperInterface.php
vendored
Normal file
12
libraries/vendor/algo26-matthias/idna-convert/src/EncodingHelper/EncodingHelperInterface.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\EncodingHelper;
|
||||
|
||||
interface EncodingHelperInterface
|
||||
{
|
||||
public function convert(
|
||||
string $sourceString,
|
||||
string $encoding = 'ISO-8859-1',
|
||||
bool $safeMode = false
|
||||
);
|
||||
}
|
||||
117
libraries/vendor/algo26-matthias/idna-convert/src/EncodingHelper/FromUtf8.php
vendored
Normal file
117
libraries/vendor/algo26-matthias/idna-convert/src/EncodingHelper/FromUtf8.php
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\EncodingHelper;
|
||||
|
||||
class FromUtf8 implements EncodingHelperInterface
|
||||
{
|
||||
private const DEFAULT_ENCODING = 'ISO-8859-1';
|
||||
|
||||
private $encoding = self::DEFAULT_ENCODING;
|
||||
|
||||
public function convert(
|
||||
string $sourceString,
|
||||
?string $encoding = self::DEFAULT_ENCODING,
|
||||
?bool $safeMode = false
|
||||
) {
|
||||
$safe = ($safeMode) ? $sourceString : false;
|
||||
|
||||
if ($encoding !== null) {
|
||||
$this->encoding = strtoupper($encoding);
|
||||
} else {
|
||||
$this->encoding = 'ISO-8859-1';
|
||||
}
|
||||
|
||||
if ($this->encoding === 'UTF-8' || $this->encoding === 'UTF8') {
|
||||
return $sourceString;
|
||||
}
|
||||
|
||||
if ($this->encoding === 'ISO-8859-1') {
|
||||
return utf8_decode($sourceString);
|
||||
}
|
||||
|
||||
if ($this->encoding === 'WINDOWS-1252') {
|
||||
return self::mapIso8859_1ToWindows1252(utf8_decode($sourceString));
|
||||
}
|
||||
|
||||
if ($this->encoding === 'UNICODE-1-1-UTF-7') {
|
||||
$this->encoding = 'UTF-7';
|
||||
}
|
||||
|
||||
$converted = $this->convertWithLibraries($sourceString);
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
|
||||
return $safe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special treatment for our guys in Redmond
|
||||
* Windows-1252 is basically ISO-8859-1 -- with some exceptions, which get dealt with here
|
||||
*
|
||||
* @param string $string Your input in ISO-8859-1
|
||||
*
|
||||
* @return string The resulting Win1252 string
|
||||
* @since 0.0.1
|
||||
*/
|
||||
private function mapIso8859_1ToWindows1252($string = '')
|
||||
{
|
||||
$return = '';
|
||||
for ($i = 0; $i < strlen($string); ++$i) {
|
||||
$codePoint = ord($string[$i]);
|
||||
switch ($codePoint) {
|
||||
case 196:
|
||||
$return .= chr(142);
|
||||
break;
|
||||
case 214:
|
||||
$return .= chr(153);
|
||||
break;
|
||||
case 220:
|
||||
$return .= chr(154);
|
||||
break;
|
||||
case 223:
|
||||
$return .= chr(225);
|
||||
break;
|
||||
case 228:
|
||||
$return .= chr(132);
|
||||
break;
|
||||
case 246:
|
||||
$return .= chr(148);
|
||||
break;
|
||||
case 252:
|
||||
$return .= chr(129);
|
||||
break;
|
||||
default:
|
||||
$return .= chr($codePoint);
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function convertWithLibraries(string $string): ?string
|
||||
{
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
$converted = @mb_convert_encoding($string, $this->encoding, 'UTF-8');
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('iconv')) {
|
||||
$converted = @iconv('UTF-8', $this->encoding, $string);
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('libiconv')) {
|
||||
$converted = @libiconv('UTF-8', $this->encoding, $string);
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
117
libraries/vendor/algo26-matthias/idna-convert/src/EncodingHelper/ToUtf8.php
vendored
Normal file
117
libraries/vendor/algo26-matthias/idna-convert/src/EncodingHelper/ToUtf8.php
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\EncodingHelper;
|
||||
|
||||
class ToUtf8 implements EncodingHelperInterface
|
||||
{
|
||||
private const DEFAULT_ENCODING = 'ISO-8859-1';
|
||||
|
||||
private $encoding = self::DEFAULT_ENCODING;
|
||||
|
||||
public function convert(
|
||||
string $sourceString,
|
||||
?string $encoding = self::DEFAULT_ENCODING,
|
||||
?bool $safeMode = false
|
||||
) {
|
||||
$safe = ($safeMode) ? $sourceString : false;
|
||||
|
||||
if ($encoding !== null) {
|
||||
$this->encoding = strtoupper($encoding);
|
||||
} else {
|
||||
$this->encoding = 'ISO-8859-1';
|
||||
}
|
||||
|
||||
if ($this->encoding === 'UTF-8' || $this->encoding === 'UTF8') {
|
||||
return $sourceString;
|
||||
}
|
||||
|
||||
if ($this->encoding === 'ISO-8859-1') {
|
||||
return utf8_encode($sourceString);
|
||||
}
|
||||
|
||||
if ($this->encoding === 'WINDOWS-1252') {
|
||||
return utf8_encode($this->mapWindows1252ToIso8859_1($sourceString));
|
||||
}
|
||||
|
||||
if ($this->encoding === 'UNICODE-1-1-UTF-7') {
|
||||
$this->encoding = 'UTF-7';
|
||||
}
|
||||
|
||||
$converted = $this->convertWithLibraries($sourceString);
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
|
||||
return $safe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special treatment for our guys in Redmond
|
||||
* Windows-1252 is basically ISO-8859-1 -- with some exceptions, which get dealt with here
|
||||
*
|
||||
* @param string $string Your input in Win1252
|
||||
*
|
||||
* @return string The resulting ISO-8859-1 string
|
||||
* @since 0.0.1
|
||||
*/
|
||||
private function mapWindows1252ToIso8859_1($string = '')
|
||||
{
|
||||
$return = '';
|
||||
for ($i = 0; $i < strlen($string); ++$i) {
|
||||
$codePoint = ord($string[$i]);
|
||||
switch ($codePoint) {
|
||||
case 129:
|
||||
$return .= chr(252);
|
||||
break;
|
||||
case 132:
|
||||
$return .= chr(228);
|
||||
break;
|
||||
case 142:
|
||||
$return .= chr(196);
|
||||
break;
|
||||
case 148:
|
||||
$return .= chr(246);
|
||||
break;
|
||||
case 153:
|
||||
$return .= chr(214);
|
||||
break;
|
||||
case 154:
|
||||
$return .= chr(220);
|
||||
break;
|
||||
case 225:
|
||||
$return .= chr(223);
|
||||
break;
|
||||
default:
|
||||
$return .= chr($codePoint);
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function convertWithLibraries(string $string): ?string
|
||||
{
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
$converted = @mb_convert_encoding($string, 'UTF-8', $this->encoding);
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('iconv')) {
|
||||
$converted = @iconv($this->encoding, 'UTF-8', $string);
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('libiconv')) {
|
||||
$converted = @libiconv($this->encoding, 'UTF-8', $string);
|
||||
if (false !== $converted) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
10
libraries/vendor/algo26-matthias/idna-convert/src/Exception/AlreadyPunycodeException.php
vendored
Normal file
10
libraries/vendor/algo26-matthias/idna-convert/src/Exception/AlreadyPunycodeException.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class AlreadyPunycodeException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
10
libraries/vendor/algo26-matthias/idna-convert/src/Exception/InvalidCharacterException.php
vendored
Normal file
10
libraries/vendor/algo26-matthias/idna-convert/src/Exception/InvalidCharacterException.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidCharacterException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
10
libraries/vendor/algo26-matthias/idna-convert/src/Exception/InvalidIdnVersionException.php
vendored
Normal file
10
libraries/vendor/algo26-matthias/idna-convert/src/Exception/InvalidIdnVersionException.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidIdnVersionException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
11
libraries/vendor/algo26-matthias/idna-convert/src/IdnaConvertInterface.php
vendored
Normal file
11
libraries/vendor/algo26-matthias/idna-convert/src/IdnaConvertInterface.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
namespace Algo26\IdnaConvert;
|
||||
|
||||
interface IdnaConvertInterface
|
||||
{
|
||||
public function convert(string $host): string;
|
||||
|
||||
public function convertEmailAddress(string $emailAddress): string;
|
||||
|
||||
public function convertUrl(string $url): string;
|
||||
}
|
||||
316
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrep.php
vendored
Normal file
316
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrep.php
vendored
Normal file
@ -0,0 +1,316 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\NamePrep;
|
||||
|
||||
use Algo26\IdnaConvert\Exception\InvalidCharacterException;
|
||||
use Algo26\IdnaConvert\Exception\InvalidIdnVersionException;
|
||||
|
||||
class NamePrep implements NamePrepInterface
|
||||
{
|
||||
const sBase = 0xAC00;
|
||||
const lBase = 0x1100;
|
||||
const vBase = 0x1161;
|
||||
const tBase = 0x11A7;
|
||||
const lCount = 19;
|
||||
const vCount = 21;
|
||||
const tCount = 28;
|
||||
const nCount = 588; // vCount * tCount
|
||||
const sCount = 11172; // lCount * tCount * vCount
|
||||
const sLast = self::sBase + self::lCount * self::vCount * self::tCount;
|
||||
|
||||
/** @var NamePrepDataInterface */
|
||||
private $namePrepData;
|
||||
|
||||
/**
|
||||
* @param string|null $idnVersion
|
||||
*
|
||||
* @throws InvalidIdnVersionException
|
||||
*/
|
||||
public function __construct(?string $idnVersion = null)
|
||||
{
|
||||
if ($idnVersion === null || $idnVersion == 2008) {
|
||||
$this->namePrepData = new NamePrepData2008();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($idnVersion == 2003) {
|
||||
$this->namePrepData = new NamePrepData2003();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidIdnVersionException('IDN version must bei either 2003 or 2008');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $inputArray
|
||||
*
|
||||
* @return array
|
||||
* @throws InvalidCharacterException
|
||||
*/
|
||||
public function do(array $inputArray): array
|
||||
{
|
||||
$outputArray = $this->applyCharacterMaps($inputArray);
|
||||
$outputArray = $this->hangulCompose($outputArray);
|
||||
$outputArray = $this->combineCodePoints($outputArray);
|
||||
|
||||
return $outputArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $inputArray
|
||||
*
|
||||
* @return array
|
||||
* @throws InvalidCharacterException
|
||||
*/
|
||||
private function applyCharacterMaps(array $inputArray): array
|
||||
{
|
||||
$outputArray = [];
|
||||
foreach ($inputArray as $codePoint) {
|
||||
// Map to nothing == skip that code point
|
||||
if (in_array($codePoint, $this->namePrepData->mapToNothing)) {
|
||||
continue;
|
||||
}
|
||||
// Try to find prohibited input
|
||||
if (in_array($codePoint, $this->namePrepData->prohibit)
|
||||
|| in_array($codePoint, $this->namePrepData->generalProhibited)
|
||||
) {
|
||||
throw new InvalidCharacterException(sprintf('Prohibited input U+%08X', $codePoint), 101);
|
||||
}
|
||||
foreach ($this->namePrepData->prohibitRanges as $range) {
|
||||
if ($range[0] <= $codePoint && $codePoint <= $range[1]) {
|
||||
throw new InvalidCharacterException(sprintf('Prohibited input U+%08X', $codePoint), 102);
|
||||
}
|
||||
}
|
||||
|
||||
if (0xAC00 <= $codePoint && $codePoint <= 0xD7AF) {
|
||||
// Hangul syllable decomposition
|
||||
foreach ($this->hangulDecompose($codePoint) as $decomposed) {
|
||||
$outputArray[] = (int) $decomposed;
|
||||
}
|
||||
} elseif (isset($this->namePrepData->replaceMaps[$codePoint])) {
|
||||
foreach ($this->applyCanonicalOrdering($this->namePrepData->replaceMaps[$codePoint]) as $reordered) {
|
||||
$outputArray[] = (int) $reordered;
|
||||
}
|
||||
} else {
|
||||
$outputArray[] = (int) $codePoint;
|
||||
}
|
||||
}
|
||||
|
||||
return $outputArray;
|
||||
}
|
||||
|
||||
private function combineCodePoints(array $codePoints): array
|
||||
{
|
||||
$previousClass = 0;
|
||||
$previousStarter = 0;
|
||||
$outputLength = count($codePoints);
|
||||
for ($outerIndex = 0; $outerIndex < $outputLength; ++$outerIndex) {
|
||||
$combiningClass = $this->getCombiningClass($codePoints[$outerIndex]);
|
||||
if (
|
||||
($previousClass === 0 || $previousClass > $combiningClass)
|
||||
&& $combiningClass !== 0
|
||||
) {
|
||||
// Try to match
|
||||
$sequenceLength = $outerIndex - $previousStarter;
|
||||
$combined = $this->combine(array_slice($codePoints, $previousStarter, $sequenceLength));
|
||||
// On match: Replace the last starter with the composed character and remove
|
||||
// the now redundant non-starter(s)
|
||||
if (false !== $combined) {
|
||||
$codePoints[$previousStarter] = $combined;
|
||||
if ($sequenceLength > 1) {
|
||||
for ($innerIndex = $outerIndex + 1; $innerIndex < $outputLength; ++$innerIndex) {
|
||||
$codePoints[$innerIndex - 1] = $codePoints[$innerIndex];
|
||||
}
|
||||
unset($codePoints[$outputLength]);
|
||||
}
|
||||
// Rewind the for loop by one, since there can be more possible compositions
|
||||
$outerIndex--;
|
||||
$outputLength--;
|
||||
$previousClass = 0;
|
||||
if ($outerIndex !== $previousStarter) {
|
||||
$this->getCombiningClass($codePoints[$outerIndex - 1]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($combiningClass === 0) {
|
||||
$previousStarter = $outerIndex;
|
||||
}
|
||||
$previousClass = $combiningClass;
|
||||
}
|
||||
|
||||
return $codePoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decomposes a Hangul syllable
|
||||
* (see http://www.unicode.org/unicode/reports/tr15/#Hangul
|
||||
* @param integer 32bit UCS4 code point
|
||||
* @return array Either Hangul Syllable decomposed or original 32bit value as one value array
|
||||
*/
|
||||
private function hangulDecompose(int $codePoint): array
|
||||
{
|
||||
$sIndex = (int) $codePoint - self::sBase;
|
||||
if ($sIndex < 0 || $sIndex >= self::sCount) {
|
||||
return [$codePoint];
|
||||
}
|
||||
|
||||
$result = [
|
||||
(int) self::lBase + $sIndex / self::nCount,
|
||||
(int) self::vBase + ($sIndex % self::nCount) / self::tCount,
|
||||
];
|
||||
$T = intval(self::tBase + $sIndex % self::tCount);
|
||||
if ($T != self::tBase) {
|
||||
$result[] = $T;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a Hangul syllable
|
||||
* (see http://www.unicode.org/unicode/reports/tr15/#Hangul
|
||||
*
|
||||
* @param array $input Decomposed UCS4 sequence
|
||||
* @return array UCS4 sequence with syllables composed
|
||||
*/
|
||||
private function hangulCompose(array $input): array
|
||||
{
|
||||
$inputLength = count($input);
|
||||
if ($inputLength === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$previousCharCode = (int) $input[0];
|
||||
|
||||
// copy first codepoint from input to output
|
||||
$result = [
|
||||
$previousCharCode,
|
||||
];
|
||||
|
||||
for ($i = 1; $i < $inputLength; ++$i) {
|
||||
$charCode = (int) $input[$i];
|
||||
$sIndex = $previousCharCode - self::sBase;
|
||||
$lIndex = $previousCharCode - self::lBase;
|
||||
$vIndex = $charCode - self::vBase;
|
||||
$tIndex = $charCode - self::tBase;
|
||||
|
||||
// Find out, whether two current characters are LV and T
|
||||
if (0 <= $sIndex
|
||||
&& $sIndex < self::sCount
|
||||
&& ($sIndex % self::tCount == 0)
|
||||
&& 0 <= $tIndex
|
||||
&& $tIndex <= self::tCount
|
||||
) {
|
||||
// create syllable of form LVT
|
||||
$previousCharCode += $tIndex;
|
||||
$result[(count($result) - 1)] = $previousCharCode; // reset last
|
||||
|
||||
continue; // discard char
|
||||
}
|
||||
|
||||
// Find out, whether two current characters form L and V
|
||||
if (0 <= $lIndex
|
||||
&& $lIndex < self::lCount
|
||||
&& 0 <= $vIndex
|
||||
&& $vIndex < self::vCount
|
||||
) {
|
||||
// create syllable of form LV
|
||||
$previousCharCode = (int) self::sBase + ($lIndex * self::vCount + $vIndex) * self::tCount;
|
||||
$result[(count($result) - 1)] = $previousCharCode; // reset last
|
||||
|
||||
continue; // discard char
|
||||
}
|
||||
// if neither case was true, just add the character
|
||||
$previousCharCode = $charCode;
|
||||
$result[] = $charCode;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the combining class of a certain wide char
|
||||
* @param integer $char Wide char to check (32bit integer)
|
||||
* @return integer Combining class if found, else 0
|
||||
*/
|
||||
private function getCombiningClass(int $char): int
|
||||
{
|
||||
return $this->namePrepData->normalizeCombiningClasses[$char] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the canonical ordering of a decomposed UCS4 sequence
|
||||
* @param array $input Decomposed UCS4 sequence
|
||||
* @return array Ordered USC4 sequence
|
||||
*/
|
||||
private function applyCanonicalOrdering(array $input): array
|
||||
{
|
||||
$needsSwapping = true;
|
||||
$inputLength = count($input);
|
||||
while ($needsSwapping) {
|
||||
$needsSwapping = false;
|
||||
$previousClass = $this->getCombiningClass(intval($input[0]));
|
||||
for ($outerIndex = 0; $outerIndex < $inputLength - 1; ++$outerIndex) {
|
||||
$nextClass = $this->getCombiningClass(intval($input[$outerIndex + 1]));
|
||||
if ($nextClass !== 0 && $previousClass > $nextClass) {
|
||||
// Move item leftward until it fits
|
||||
for ($innerIndex = $outerIndex + 1; $innerIndex > 0; --$innerIndex) {
|
||||
if ($this->getCombiningClass(intval($input[$innerIndex - 1])) <= $nextClass) {
|
||||
break;
|
||||
}
|
||||
$charToMove = intval($input[$innerIndex]);
|
||||
$input[$innerIndex] = intval($input[$innerIndex - 1]);
|
||||
$input[$innerIndex - 1] = $charToMove;
|
||||
$needsSwapping = true;
|
||||
}
|
||||
// Reentering the loop looking at the old character again
|
||||
$nextClass = $previousClass;
|
||||
}
|
||||
$previousClass = $nextClass;
|
||||
}
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do composition of a sequence of starter and non-starter
|
||||
* @param array $input UCS4 Decomposed sequence
|
||||
* @return array|false Ordered USC4 sequence
|
||||
*/
|
||||
private function combine(array $input)
|
||||
{
|
||||
$inputLength = count($input);
|
||||
if (0 === $inputLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->namePrepData->replaceMaps as $namePrepSource => $namePrepTarget) {
|
||||
if ($namePrepTarget[0] !== $input[0]) {
|
||||
continue;
|
||||
}
|
||||
if (count($namePrepTarget) !== $inputLength) {
|
||||
continue;
|
||||
}
|
||||
$hit = false;
|
||||
foreach ($input as $k2 => $v2) {
|
||||
if ($v2 === $namePrepTarget[$k2]) {
|
||||
$hit = true;
|
||||
} else {
|
||||
$hit = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($hit) {
|
||||
return $namePrepSource;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
504
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepData2003.php
vendored
Normal file
504
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepData2003.php
vendored
Normal file
@ -0,0 +1,504 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\NamePrep;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore character mapss
|
||||
*/
|
||||
class NamePrepData2003 extends NamePrepData2008 implements NamePrepDataInterface
|
||||
{
|
||||
public $replaceMaps = [
|
||||
0x41 => [0x61], 0x42 => [0x62], 0x43 => [0x63],
|
||||
0x44 => [0x64], 0x45 => [0x65], 0x46 => [0x66], 0x47 => [0x67],
|
||||
0x48 => [0x68], 0x49 => [0x69], 0x4A => [0x6A], 0x4B => [0x6B],
|
||||
0x4C => [0x6C], 0x4D => [0x6D], 0x4E => [0x6E], 0x4F => [0x6F],
|
||||
0x50 => [0x70], 0x51 => [0x71], 0x52 => [0x72], 0x53 => [0x73],
|
||||
0x54 => [0x74], 0x55 => [0x75], 0x56 => [0x76], 0x57 => [0x77],
|
||||
0x58 => [0x78], 0x59 => [0x79], 0x5A => [0x7A], 0xB5 => [0x3BC],
|
||||
0xC0 => [0xE0], 0xC1 => [0xE1], 0xC2 => [0xE2], 0xC3 => [0xE3],
|
||||
0xC4 => [0xE4], 0xC5 => [0xE5], 0xC6 => [0xE6], 0xC7 => [0xE7],
|
||||
0xC8 => [0xE8], 0xC9 => [0xE9], 0xCA => [0xEA], 0xCB => [0xEB],
|
||||
0xCC => [0xEC], 0xCD => [0xED], 0xCE => [0xEE], 0xCF => [0xEF],
|
||||
0xD0 => [0xF0], 0xD1 => [0xF1], 0xD2 => [0xF2], 0xD3 => [0xF3],
|
||||
0xD4 => [0xF4], 0xD5 => [0xF5], 0xD6 => [0xF6], 0xD8 => [0xF8],
|
||||
0xD9 => [0xF9], 0xDA => [0xFA], 0xDB => [0xFB], 0xDC => [0xFC],
|
||||
0xDD => [0xFD], 0xDE => [0xFE], 0xDF => [0x73, 0x73],
|
||||
0x100 => [0x101], 0x102 => [0x103], 0x104 => [0x105],
|
||||
0x106 => [0x107], 0x108 => [0x109], 0x10A => [0x10B],
|
||||
0x10C => [0x10D], 0x10E => [0x10F], 0x110 => [0x111],
|
||||
0x112 => [0x113], 0x114 => [0x115], 0x116 => [0x117],
|
||||
0x118 => [0x119], 0x11A => [0x11B], 0x11C => [0x11D],
|
||||
0x11E => [0x11F], 0x120 => [0x121], 0x122 => [0x123],
|
||||
0x124 => [0x125], 0x126 => [0x127], 0x128 => [0x129],
|
||||
0x12A => [0x12B], 0x12C => [0x12D], 0x12E => [0x12F],
|
||||
0x130 => [0x69, 0x307], 0x132 => [0x133], 0x134 => [0x135],
|
||||
0x136 => [0x137], 0x139 => [0x13A], 0x13B => [0x13C],
|
||||
0x13D => [0x13E], 0x13F => [0x140], 0x141 => [0x142],
|
||||
0x143 => [0x144], 0x145 => [0x146], 0x147 => [0x148],
|
||||
0x149 => [0x2BC, 0x6E], 0x14A => [0x14B], 0x14C => [0x14D],
|
||||
0x14E => [0x14F], 0x150 => [0x151], 0x152 => [0x153],
|
||||
0x154 => [0x155], 0x156 => [0x157], 0x158 => [0x159],
|
||||
0x15A => [0x15B], 0x15C => [0x15D], 0x15E => [0x15F],
|
||||
0x160 => [0x161], 0x162 => [0x163], 0x164 => [0x165],
|
||||
0x166 => [0x167], 0x168 => [0x169], 0x16A => [0x16B],
|
||||
0x16C => [0x16D], 0x16E => [0x16F], 0x170 => [0x171],
|
||||
0x172 => [0x173], 0x174 => [0x175], 0x176 => [0x177],
|
||||
0x178 => [0xFF], 0x179 => [0x17A], 0x17B => [0x17C],
|
||||
0x17D => [0x17E], 0x17F => [0x73], 0x181 => [0x253],
|
||||
0x182 => [0x183], 0x184 => [0x185], 0x186 => [0x254],
|
||||
0x187 => [0x188], 0x189 => [0x256], 0x18A => [0x257],
|
||||
0x18B => [0x18C], 0x18E => [0x1DD], 0x18F => [0x259],
|
||||
0x190 => [0x25B], 0x191 => [0x192], 0x193 => [0x260],
|
||||
0x194 => [0x263], 0x196 => [0x269], 0x197 => [0x268],
|
||||
0x198 => [0x199], 0x19C => [0x26F], 0x19D => [0x272],
|
||||
0x19F => [0x275], 0x1A0 => [0x1A1], 0x1A2 => [0x1A3],
|
||||
0x1A4 => [0x1A5], 0x1A6 => [0x280], 0x1A7 => [0x1A8],
|
||||
0x1A9 => [0x283], 0x1AC => [0x1AD], 0x1AE => [0x288],
|
||||
0x1AF => [0x1B0], 0x1B1 => [0x28A], 0x1B2 => [0x28B],
|
||||
0x1B3 => [0x1B4], 0x1B5 => [0x1B6], 0x1B7 => [0x292],
|
||||
0x1B8 => [0x1B9], 0x1BC => [0x1BD], 0x1C4 => [0x1C6],
|
||||
0x1C5 => [0x1C6], 0x1C7 => [0x1C9], 0x1C8 => [0x1C9],
|
||||
0x1CA => [0x1CC], 0x1CB => [0x1CC], 0x1CD => [0x1CE],
|
||||
0x1CF => [0x1D0], 0x1D1 => [0x1D2], 0x1D3 => [0x1D4],
|
||||
0x1D5 => [0x1D6], 0x1D7 => [0x1D8], 0x1D9 => [0x1DA],
|
||||
0x1DB => [0x1DC], 0x1DE => [0x1DF], 0x1E0 => [0x1E1],
|
||||
0x1E2 => [0x1E3], 0x1E4 => [0x1E5], 0x1E6 => [0x1E7],
|
||||
0x1E8 => [0x1E9], 0x1EA => [0x1EB], 0x1EC => [0x1ED],
|
||||
0x1EE => [0x1EF], 0x1F0 => [0x6A, 0x30C], 0x1F1 => [0x1F3],
|
||||
0x1F2 => [0x1F3], 0x1F4 => [0x1F5], 0x1F6 => [0x195],
|
||||
0x1F7 => [0x1BF], 0x1F8 => [0x1F9], 0x1FA => [0x1FB],
|
||||
0x1FC => [0x1FD], 0x1FE => [0x1FF], 0x200 => [0x201],
|
||||
0x202 => [0x203], 0x204 => [0x205], 0x206 => [0x207],
|
||||
0x208 => [0x209], 0x20A => [0x20B], 0x20C => [0x20D],
|
||||
0x20E => [0x20F], 0x210 => [0x211], 0x212 => [0x213],
|
||||
0x214 => [0x215], 0x216 => [0x217], 0x218 => [0x219],
|
||||
0x21A => [0x21B], 0x21C => [0x21D], 0x21E => [0x21F],
|
||||
0x220 => [0x19E], 0x222 => [0x223], 0x224 => [0x225],
|
||||
0x226 => [0x227], 0x228 => [0x229], 0x22A => [0x22B],
|
||||
0x22C => [0x22D], 0x22E => [0x22F], 0x230 => [0x231],
|
||||
0x232 => [0x233], 0x345 => [0x3B9], 0x37A => [0x20, 0x3B9],
|
||||
0x386 => [0x3AC], 0x388 => [0x3AD], 0x389 => [0x3AE],
|
||||
0x38A => [0x3AF], 0x38C => [0x3CC], 0x38E => [0x3CD],
|
||||
0x38F => [0x3CE], 0x390 => [0x3B9, 0x308, 0x301],
|
||||
0x391 => [0x3B1], 0x392 => [0x3B2], 0x393 => [0x3B3],
|
||||
0x394 => [0x3B4], 0x395 => [0x3B5], 0x396 => [0x3B6],
|
||||
0x397 => [0x3B7], 0x398 => [0x3B8], 0x399 => [0x3B9],
|
||||
0x39A => [0x3BA], 0x39B => [0x3BB], 0x39C => [0x3BC],
|
||||
0x39D => [0x3BD], 0x39E => [0x3BE], 0x39F => [0x3BF],
|
||||
0x3A0 => [0x3C0], 0x3A1 => [0x3C1], 0x3A3 => [0x3C3],
|
||||
0x3A4 => [0x3C4], 0x3A5 => [0x3C5], 0x3A6 => [0x3C6],
|
||||
0x3A7 => [0x3C7], 0x3A8 => [0x3C8], 0x3A9 => [0x3C9],
|
||||
0x3AA => [0x3CA], 0x3AB => [0x3CB], 0x3B0 => [0x3C5, 0x308, 0x301],
|
||||
0x3C2 => [0x3C3], 0x3D0 => [0x3B2], 0x3D1 => [0x3B8],
|
||||
0x3D2 => [0x3C5], 0x3D3 => [0x3CD], 0x3D4 => [0x3CB],
|
||||
0x3D5 => [0x3C6], 0x3D6 => [0x3C0], 0x3D8 => [0x3D9],
|
||||
0x3DA => [0x3DB], 0x3DC => [0x3DD], 0x3DE => [0x3DF],
|
||||
0x3E0 => [0x3E1], 0x3E2 => [0x3E3], 0x3E4 => [0x3E5],
|
||||
0x3E6 => [0x3E7], 0x3E8 => [0x3E9], 0x3EA => [0x3EB],
|
||||
0x3EC => [0x3ED], 0x3EE => [0x3EF], 0x3F0 => [0x3BA],
|
||||
0x3F1 => [0x3C1], 0x3F2 => [0x3C3], 0x3F4 => [0x3B8],
|
||||
0x3F5 => [0x3B5], 0x400 => [0x450], 0x401 => [0x451],
|
||||
0x402 => [0x452], 0x403 => [0x453], 0x404 => [0x454],
|
||||
0x405 => [0x455], 0x406 => [0x456], 0x407 => [0x457],
|
||||
0x408 => [0x458], 0x409 => [0x459], 0x40A => [0x45A],
|
||||
0x40B => [0x45B], 0x40C => [0x45C], 0x40D => [0x45D],
|
||||
0x40E => [0x45E], 0x40F => [0x45F], 0x410 => [0x430],
|
||||
0x411 => [0x431], 0x412 => [0x432], 0x413 => [0x433],
|
||||
0x414 => [0x434], 0x415 => [0x435], 0x416 => [0x436],
|
||||
0x417 => [0x437], 0x418 => [0x438], 0x419 => [0x439],
|
||||
0x41A => [0x43A], 0x41B => [0x43B], 0x41C => [0x43C],
|
||||
0x41D => [0x43D], 0x41E => [0x43E], 0x41F => [0x43F],
|
||||
0x420 => [0x440], 0x421 => [0x441], 0x422 => [0x442],
|
||||
0x423 => [0x443], 0x424 => [0x444], 0x425 => [0x445],
|
||||
0x426 => [0x446], 0x427 => [0x447], 0x428 => [0x448],
|
||||
0x429 => [0x449], 0x42A => [0x44A], 0x42B => [0x44B],
|
||||
0x42C => [0x44C], 0x42D => [0x44D], 0x42E => [0x44E],
|
||||
0x42F => [0x44F], 0x460 => [0x461], 0x462 => [0x463],
|
||||
0x464 => [0x465], 0x466 => [0x467], 0x468 => [0x469],
|
||||
0x46A => [0x46B], 0x46C => [0x46D], 0x46E => [0x46F],
|
||||
0x470 => [0x471], 0x472 => [0x473], 0x474 => [0x475],
|
||||
0x476 => [0x477], 0x478 => [0x479], 0x47A => [0x47B],
|
||||
0x47C => [0x47D], 0x47E => [0x47F], 0x480 => [0x481],
|
||||
0x48A => [0x48B], 0x48C => [0x48D], 0x48E => [0x48F],
|
||||
0x490 => [0x491], 0x492 => [0x493], 0x494 => [0x495],
|
||||
0x496 => [0x497], 0x498 => [0x499], 0x49A => [0x49B],
|
||||
0x49C => [0x49D], 0x49E => [0x49F], 0x4A0 => [0x4A1],
|
||||
0x4A2 => [0x4A3], 0x4A4 => [0x4A5], 0x4A6 => [0x4A7],
|
||||
0x4A8 => [0x4A9], 0x4AA => [0x4AB], 0x4AC => [0x4AD],
|
||||
0x4AE => [0x4AF], 0x4B0 => [0x4B1], 0x4B2 => [0x4B3],
|
||||
0x4B4 => [0x4B5], 0x4B6 => [0x4B7], 0x4B8 => [0x4B9],
|
||||
0x4BA => [0x4BB], 0x4BC => [0x4BD], 0x4BE => [0x4BF],
|
||||
0x4C1 => [0x4C2], 0x4C3 => [0x4C4], 0x4C5 => [0x4C6],
|
||||
0x4C7 => [0x4C8], 0x4C9 => [0x4CA], 0x4CB => [0x4CC],
|
||||
0x4CD => [0x4CE], 0x4D0 => [0x4D1], 0x4D2 => [0x4D3],
|
||||
0x4D4 => [0x4D5], 0x4D6 => [0x4D7], 0x4D8 => [0x4D9],
|
||||
0x4DA => [0x4DB], 0x4DC => [0x4DD], 0x4DE => [0x4DF],
|
||||
0x4E0 => [0x4E1], 0x4E2 => [0x4E3], 0x4E4 => [0x4E5],
|
||||
0x4E6 => [0x4E7], 0x4E8 => [0x4E9], 0x4EA => [0x4EB],
|
||||
0x4EC => [0x4ED], 0x4EE => [0x4EF], 0x4F0 => [0x4F1],
|
||||
0x4F2 => [0x4F3], 0x4F4 => [0x4F5], 0x4F8 => [0x4F9],
|
||||
0x500 => [0x501], 0x502 => [0x503], 0x504 => [0x505],
|
||||
0x506 => [0x507], 0x508 => [0x509], 0x50A => [0x50B],
|
||||
0x50C => [0x50D], 0x50E => [0x50F], 0x531 => [0x561],
|
||||
0x532 => [0x562], 0x533 => [0x563], 0x534 => [0x564],
|
||||
0x535 => [0x565], 0x536 => [0x566], 0x537 => [0x567],
|
||||
0x538 => [0x568], 0x539 => [0x569], 0x53A => [0x56A],
|
||||
0x53B => [0x56B], 0x53C => [0x56C], 0x53D => [0x56D],
|
||||
0x53E => [0x56E], 0x53F => [0x56F], 0x540 => [0x570],
|
||||
0x541 => [0x571], 0x542 => [0x572], 0x543 => [0x573],
|
||||
0x544 => [0x574], 0x545 => [0x575], 0x546 => [0x576],
|
||||
0x547 => [0x577], 0x548 => [0x578], 0x549 => [0x579],
|
||||
0x54A => [0x57A], 0x54B => [0x57B], 0x54C => [0x57C],
|
||||
0x54D => [0x57D], 0x54E => [0x57E], 0x54F => [0x57F],
|
||||
0x550 => [0x580], 0x551 => [0x581], 0x552 => [0x582],
|
||||
0x553 => [0x583], 0x554 => [0x584], 0x555 => [0x585],
|
||||
0x556 => [0x586], 0x587 => [0x565, 0x582], 0xE33 => [0xE4D, 0xE32],
|
||||
0x1E00 => [0x1E01], 0x1E02 => [0x1E03], 0x1E04 => [0x1E05],
|
||||
0x1E06 => [0x1E07], 0x1E08 => [0x1E09], 0x1E0A => [0x1E0B],
|
||||
0x1E0C => [0x1E0D], 0x1E0E => [0x1E0F], 0x1E10 => [0x1E11],
|
||||
0x1E12 => [0x1E13], 0x1E14 => [0x1E15], 0x1E16 => [0x1E17],
|
||||
0x1E18 => [0x1E19], 0x1E1A => [0x1E1B], 0x1E1C => [0x1E1D],
|
||||
0x1E1E => [0x1E1F], 0x1E20 => [0x1E21], 0x1E22 => [0x1E23],
|
||||
0x1E24 => [0x1E25], 0x1E26 => [0x1E27], 0x1E28 => [0x1E29],
|
||||
0x1E2A => [0x1E2B], 0x1E2C => [0x1E2D], 0x1E2E => [0x1E2F],
|
||||
0x1E30 => [0x1E31], 0x1E32 => [0x1E33], 0x1E34 => [0x1E35],
|
||||
0x1E36 => [0x1E37], 0x1E38 => [0x1E39], 0x1E3A => [0x1E3B],
|
||||
0x1E3C => [0x1E3D], 0x1E3E => [0x1E3F], 0x1E40 => [0x1E41],
|
||||
0x1E42 => [0x1E43], 0x1E44 => [0x1E45], 0x1E46 => [0x1E47],
|
||||
0x1E48 => [0x1E49], 0x1E4A => [0x1E4B], 0x1E4C => [0x1E4D],
|
||||
0x1E4E => [0x1E4F], 0x1E50 => [0x1E51], 0x1E52 => [0x1E53],
|
||||
0x1E54 => [0x1E55], 0x1E56 => [0x1E57], 0x1E58 => [0x1E59],
|
||||
0x1E5A => [0x1E5B], 0x1E5C => [0x1E5D], 0x1E5E => [0x1E5F],
|
||||
0x1E60 => [0x1E61], 0x1E62 => [0x1E63], 0x1E64 => [0x1E65],
|
||||
0x1E66 => [0x1E67], 0x1E68 => [0x1E69], 0x1E6A => [0x1E6B],
|
||||
0x1E6C => [0x1E6D], 0x1E6E => [0x1E6F], 0x1E70 => [0x1E71],
|
||||
0x1E72 => [0x1E73], 0x1E74 => [0x1E75], 0x1E76 => [0x1E77],
|
||||
0x1E78 => [0x1E79], 0x1E7A => [0x1E7B], 0x1E7C => [0x1E7D],
|
||||
0x1E7E => [0x1E7F], 0x1E80 => [0x1E81], 0x1E82 => [0x1E83],
|
||||
0x1E84 => [0x1E85], 0x1E86 => [0x1E87], 0x1E88 => [0x1E89],
|
||||
0x1E8A => [0x1E8B], 0x1E8C => [0x1E8D], 0x1E8E => [0x1E8F],
|
||||
0x1E90 => [0x1E91], 0x1E92 => [0x1E93], 0x1E94 => [0x1E95],
|
||||
0x1E96 => [0x68, 0x331], 0x1E97 => [0x74, 0x308], 0x1E98 => [0x77, 0x30A],
|
||||
0x1E99 => [0x79, 0x30A], 0x1E9A => [0x61, 0x2BE], 0x1E9B => [0x1E61],
|
||||
0x1EA0 => [0x1EA1], 0x1EA2 => [0x1EA3], 0x1EA4 => [0x1EA5],
|
||||
0x1EA6 => [0x1EA7], 0x1EA8 => [0x1EA9], 0x1EAA => [0x1EAB],
|
||||
0x1EAC => [0x1EAD], 0x1EAE => [0x1EAF], 0x1EB0 => [0x1EB1],
|
||||
0x1EB2 => [0x1EB3], 0x1EB4 => [0x1EB5], 0x1EB6 => [0x1EB7],
|
||||
0x1EB8 => [0x1EB9], 0x1EBA => [0x1EBB], 0x1EBC => [0x1EBD],
|
||||
0x1EBE => [0x1EBF], 0x1EC0 => [0x1EC1], 0x1EC2 => [0x1EC3],
|
||||
0x1EC4 => [0x1EC5], 0x1EC6 => [0x1EC7], 0x1EC8 => [0x1EC9],
|
||||
0x1ECA => [0x1ECB], 0x1ECC => [0x1ECD], 0x1ECE => [0x1ECF],
|
||||
0x1ED0 => [0x1ED1], 0x1ED2 => [0x1ED3], 0x1ED4 => [0x1ED5],
|
||||
0x1ED6 => [0x1ED7], 0x1ED8 => [0x1ED9], 0x1EDA => [0x1EDB],
|
||||
0x1EDC => [0x1EDD], 0x1EDE => [0x1EDF], 0x1EE0 => [0x1EE1],
|
||||
0x1EE2 => [0x1EE3], 0x1EE4 => [0x1EE5], 0x1EE6 => [0x1EE7],
|
||||
0x1EE8 => [0x1EE9], 0x1EEA => [0x1EEB], 0x1EEC => [0x1EED],
|
||||
0x1EEE => [0x1EEF], 0x1EF0 => [0x1EF1], 0x1EF2 => [0x1EF3],
|
||||
0x1EF4 => [0x1EF5], 0x1EF6 => [0x1EF7], 0x1EF8 => [0x1EF9],
|
||||
0x1F08 => [0x1F00], 0x1F09 => [0x1F01], 0x1F0A => [0x1F02],
|
||||
0x1F0B => [0x1F03], 0x1F0C => [0x1F04], 0x1F0D => [0x1F05],
|
||||
0x1F0E => [0x1F06], 0x1F0F => [0x1F07], 0x1F18 => [0x1F10],
|
||||
0x1F19 => [0x1F11], 0x1F1A => [0x1F12], 0x1F1B => [0x1F13],
|
||||
0x1F1C => [0x1F14], 0x1F1D => [0x1F15], 0x1F28 => [0x1F20],
|
||||
0x1F29 => [0x1F21], 0x1F2A => [0x1F22], 0x1F2B => [0x1F23],
|
||||
0x1F2C => [0x1F24], 0x1F2D => [0x1F25], 0x1F2E => [0x1F26],
|
||||
0x1F2F => [0x1F27], 0x1F38 => [0x1F30], 0x1F39 => [0x1F31],
|
||||
0x1F3A => [0x1F32], 0x1F3B => [0x1F33], 0x1F3C => [0x1F34],
|
||||
0x1F3D => [0x1F35], 0x1F3E => [0x1F36], 0x1F3F => [0x1F37],
|
||||
0x1F48 => [0x1F40], 0x1F49 => [0x1F41], 0x1F4A => [0x1F42],
|
||||
0x1F4B => [0x1F43], 0x1F4C => [0x1F44], 0x1F4D => [0x1F45],
|
||||
0x1F50 => [0x3C5, 0x313], 0x1F52 => [0x3C5, 0x313, 0x300],
|
||||
0x1F54 => [0x3C5, 0x313, 0x301], 0x1F56 => [0x3C5, 0x313, 0x342],
|
||||
0x1F59 => [0x1F51], 0x1F5B => [0x1F53], 0x1F5D => [0x1F55],
|
||||
0x1F5F => [0x1F57], 0x1F68 => [0x1F60], 0x1F69 => [0x1F61],
|
||||
0x1F6A => [0x1F62], 0x1F6B => [0x1F63], 0x1F6C => [0x1F64],
|
||||
0x1F6D => [0x1F65], 0x1F6E => [0x1F66], 0x1F6F => [0x1F67],
|
||||
0x1F80 => [0x1F00, 0x3B9], 0x1F81 => [0x1F01, 0x3B9],
|
||||
0x1F82 => [0x1F02, 0x3B9], 0x1F83 => [0x1F03, 0x3B9],
|
||||
0x1F84 => [0x1F04, 0x3B9], 0x1F85 => [0x1F05, 0x3B9],
|
||||
0x1F86 => [0x1F06, 0x3B9], 0x1F87 => [0x1F07, 0x3B9],
|
||||
0x1F88 => [0x1F00, 0x3B9], 0x1F89 => [0x1F01, 0x3B9],
|
||||
0x1F8A => [0x1F02, 0x3B9], 0x1F8B => [0x1F03, 0x3B9],
|
||||
0x1F8C => [0x1F04, 0x3B9], 0x1F8D => [0x1F05, 0x3B9],
|
||||
0x1F8E => [0x1F06, 0x3B9], 0x1F8F => [0x1F07, 0x3B9],
|
||||
0x1F90 => [0x1F20, 0x3B9], 0x1F91 => [0x1F21, 0x3B9],
|
||||
0x1F92 => [0x1F22, 0x3B9], 0x1F93 => [0x1F23, 0x3B9],
|
||||
0x1F94 => [0x1F24, 0x3B9], 0x1F95 => [0x1F25, 0x3B9],
|
||||
0x1F96 => [0x1F26, 0x3B9], 0x1F97 => [0x1F27, 0x3B9],
|
||||
0x1F98 => [0x1F20, 0x3B9], 0x1F99 => [0x1F21, 0x3B9],
|
||||
0x1F9A => [0x1F22, 0x3B9], 0x1F9B => [0x1F23, 0x3B9],
|
||||
0x1F9C => [0x1F24, 0x3B9], 0x1F9D => [0x1F25, 0x3B9],
|
||||
0x1F9E => [0x1F26, 0x3B9], 0x1F9F => [0x1F27, 0x3B9],
|
||||
0x1FA0 => [0x1F60, 0x3B9], 0x1FA1 => [0x1F61, 0x3B9],
|
||||
0x1FA2 => [0x1F62, 0x3B9], 0x1FA3 => [0x1F63, 0x3B9],
|
||||
0x1FA4 => [0x1F64, 0x3B9], 0x1FA5 => [0x1F65, 0x3B9],
|
||||
0x1FA6 => [0x1F66, 0x3B9], 0x1FA7 => [0x1F67, 0x3B9],
|
||||
0x1FA8 => [0x1F60, 0x3B9], 0x1FA9 => [0x1F61, 0x3B9],
|
||||
0x1FAA => [0x1F62, 0x3B9], 0x1FAB => [0x1F63, 0x3B9],
|
||||
0x1FAC => [0x1F64, 0x3B9], 0x1FAD => [0x1F65, 0x3B9],
|
||||
0x1FAE => [0x1F66, 0x3B9], 0x1FAF => [0x1F67, 0x3B9],
|
||||
0x1FB2 => [0x1F70, 0x3B9], 0x1FB3 => [0x3B1, 0x3B9],
|
||||
0x1FB4 => [0x3AC, 0x3B9], 0x1FB6 => [0x3B1, 0x342],
|
||||
0x1FB7 => [0x3B1, 0x342, 0x3B9], 0x1FB8 => [0x1FB0],
|
||||
0x1FB9 => [0x1FB1], 0x1FBA => [0x1F70], 0x1FBB => [0x1F71],
|
||||
0x1FBC => [0x3B1, 0x3B9], 0x1FBE => [0x3B9],
|
||||
0x1FC2 => [0x1F74, 0x3B9], 0x1FC3 => [0x3B7, 0x3B9],
|
||||
0x1FC4 => [0x3AE, 0x3B9], 0x1FC6 => [0x3B7, 0x342],
|
||||
0x1FC7 => [0x3B7, 0x342, 0x3B9], 0x1FC8 => [0x1F72],
|
||||
0x1FC9 => [0x1F73], 0x1FCA => [0x1F74], 0x1FCB => [0x1F75],
|
||||
0x1FCC => [0x3B7, 0x3B9], 0x1FD2 => [0x3B9, 0x308, 0x300],
|
||||
0x1FD3 => [0x3B9, 0x308, 0x301], 0x1FD6 => [0x3B9, 0x342],
|
||||
0x1FD7 => [0x3B9, 0x308, 0x342], 0x1FD8 => [0x1FD0],
|
||||
0x1FD9 => [0x1FD1], 0x1FDA => [0x1F76],
|
||||
0x1FDB => [0x1F77], 0x1FE2 => [0x3C5, 0x308, 0x300],
|
||||
0x1FE3 => [0x3C5, 0x308, 0x301], 0x1FE4 => [0x3C1, 0x313],
|
||||
0x1FE6 => [0x3C5, 0x342], 0x1FE7 => [0x3C5, 0x308, 0x342],
|
||||
0x1FE8 => [0x1FE0], 0x1FE9 => [0x1FE1],
|
||||
0x1FEA => [0x1F7A], 0x1FEB => [0x1F7B],
|
||||
0x1FEC => [0x1FE5], 0x1FF2 => [0x1F7C, 0x3B9],
|
||||
0x1FF3 => [0x3C9, 0x3B9], 0x1FF4 => [0x3CE, 0x3B9],
|
||||
0x1FF6 => [0x3C9, 0x342], 0x1FF7 => [0x3C9, 0x342, 0x3B9],
|
||||
0x1FF8 => [0x1F78], 0x1FF9 => [0x1F79], 0x1FFA => [0x1F7C],
|
||||
0x1FFB => [0x1F7D], 0x1FFC => [0x3C9, 0x3B9],
|
||||
0x20A8 => [0x72, 0x73], 0x2102 => [0x63], 0x2103 => [0xB0, 0x63],
|
||||
0x2107 => [0x25B], 0x2109 => [0xB0, 0x66], 0x210B => [0x68],
|
||||
0x210C => [0x68], 0x210D => [0x68], 0x2110 => [0x69],
|
||||
0x2111 => [0x69], 0x2112 => [0x6C], 0x2115 => [0x6E],
|
||||
0x2116 => [0x6E, 0x6F], 0x2119 => [0x70], 0x211A => [0x71],
|
||||
0x211B => [0x72], 0x211C => [0x72], 0x211D => [0x72],
|
||||
0x2120 => [0x73, 0x6D], 0x2121 => [0x74, 0x65, 0x6C],
|
||||
0x2122 => [0x74, 0x6D], 0x2124 => [0x7A], 0x2126 => [0x3C9],
|
||||
0x2128 => [0x7A], 0x212A => [0x6B], 0x212B => [0xE5],
|
||||
0x212C => [0x62], 0x212D => [0x63], 0x2130 => [0x65],
|
||||
0x2131 => [0x66], 0x2133 => [0x6D], 0x213E => [0x3B3],
|
||||
0x213F => [0x3C0], 0x2145 => [0x64], 0x2160 => [0x2170],
|
||||
0x2161 => [0x2171], 0x2162 => [0x2172], 0x2163 => [0x2173],
|
||||
0x2164 => [0x2174], 0x2165 => [0x2175], 0x2166 => [0x2176],
|
||||
0x2167 => [0x2177], 0x2168 => [0x2178], 0x2169 => [0x2179],
|
||||
0x216A => [0x217A], 0x216B => [0x217B], 0x216C => [0x217C],
|
||||
0x216D => [0x217D], 0x216E => [0x217E], 0x216F => [0x217F],
|
||||
0x24B6 => [0x24D0], 0x24B7 => [0x24D1], 0x24B8 => [0x24D2],
|
||||
0x24B9 => [0x24D3], 0x24BA => [0x24D4], 0x24BB => [0x24D5],
|
||||
0x24BC => [0x24D6], 0x24BD => [0x24D7], 0x24BE => [0x24D8],
|
||||
0x24BF => [0x24D9], 0x24C0 => [0x24DA], 0x24C1 => [0x24DB],
|
||||
0x24C2 => [0x24DC], 0x24C3 => [0x24DD], 0x24C4 => [0x24DE],
|
||||
0x24C5 => [0x24DF], 0x24C6 => [0x24E0], 0x24C7 => [0x24E1],
|
||||
0x24C8 => [0x24E2], 0x24C9 => [0x24E3], 0x24CA => [0x24E4],
|
||||
0x24CB => [0x24E5], 0x24CC => [0x24E6], 0x24CD => [0x24E7],
|
||||
0x24CE => [0x24E8], 0x24CF => [0x24E9], 0x3371 => [0x68, 0x70, 0x61],
|
||||
0x3373 => [0x61, 0x75], 0x3375 => [0x6F, 0x76],
|
||||
0x3380 => [0x70, 0x61], 0x3381 => [0x6E, 0x61],
|
||||
0x3382 => [0x3BC, 0x61], 0x3383 => [0x6D, 0x61],
|
||||
0x3384 => [0x6B, 0x61], 0x3385 => [0x6B, 0x62],
|
||||
0x3386 => [0x6D, 0x62], 0x3387 => [0x67, 0x62],
|
||||
0x338A => [0x70, 0x66], 0x338B => [0x6E, 0x66],
|
||||
0x338C => [0x3BC, 0x66], 0x3390 => [0x68, 0x7A],
|
||||
0x3391 => [0x6B, 0x68, 0x7A], 0x3392 => [0x6D, 0x68, 0x7A],
|
||||
0x3393 => [0x67, 0x68, 0x7A], 0x3394 => [0x74, 0x68, 0x7A],
|
||||
0x33A9 => [0x70, 0x61], 0x33AA => [0x6B, 0x70, 0x61],
|
||||
0x33AB => [0x6D, 0x70, 0x61], 0x33AC => [0x67, 0x70, 0x61],
|
||||
0x33B4 => [0x70, 0x76], 0x33B5 => [0x6E, 0x76],
|
||||
0x33B6 => [0x3BC, 0x76], 0x33B7 => [0x6D, 0x76],
|
||||
0x33B8 => [0x6B, 0x76], 0x33B9 => [0x6D, 0x76],
|
||||
0x33BA => [0x70, 0x77], 0x33BB => [0x6E, 0x77],
|
||||
0x33BC => [0x3BC, 0x77], 0x33BD => [0x6D, 0x77],
|
||||
0x33BE => [0x6B, 0x77], 0x33BF => [0x6D, 0x77],
|
||||
0x33C0 => [0x6B, 0x3C9], 0x33C1 => [0x6D, 0x3C9], /*
|
||||
0x33C2 => array(0x61, 0x2E, 0x6D, 0x2E), */
|
||||
0x33C3 => [0x62, 0x71], 0x33C6 => [0x63, 0x2215, 0x6B, 0x67],
|
||||
0x33C7 => [0x63, 0x6F, 0x2E], 0x33C8 => [0x64, 0x62],
|
||||
0x33C9 => [0x67, 0x79], 0x33CB => [0x68, 0x70],
|
||||
0x33CD => [0x6B, 0x6B], 0x33CE => [0x6B, 0x6D],
|
||||
0x33D7 => [0x70, 0x68], 0x33D9 => [0x70, 0x70, 0x6D],
|
||||
0x33DA => [0x70, 0x72], 0x33DC => [0x73, 0x76],
|
||||
0x33DD => [0x77, 0x62], 0xFB00 => [0x66, 0x66],
|
||||
0xFB01 => [0x66, 0x69], 0xFB02 => [0x66, 0x6C],
|
||||
0xFB03 => [0x66, 0x66, 0x69], 0xFB04 => [0x66, 0x66, 0x6C],
|
||||
0xFB05 => [0x73, 0x74], 0xFB06 => [0x73, 0x74],
|
||||
0xFB13 => [0x574, 0x576], 0xFB14 => [0x574, 0x565],
|
||||
0xFB15 => [0x574, 0x56B], 0xFB16 => [0x57E, 0x576],
|
||||
0xFB17 => [0x574, 0x56D], 0xFF21 => [0xFF41],
|
||||
0xFF22 => [0xFF42], 0xFF23 => [0xFF43], 0xFF24 => [0xFF44],
|
||||
0xFF25 => [0xFF45], 0xFF26 => [0xFF46], 0xFF27 => [0xFF47],
|
||||
0xFF28 => [0xFF48], 0xFF29 => [0xFF49], 0xFF2A => [0xFF4A],
|
||||
0xFF2B => [0xFF4B], 0xFF2C => [0xFF4C], 0xFF2D => [0xFF4D],
|
||||
0xFF2E => [0xFF4E], 0xFF2F => [0xFF4F], 0xFF30 => [0xFF50],
|
||||
0xFF31 => [0xFF51], 0xFF32 => [0xFF52], 0xFF33 => [0xFF53],
|
||||
0xFF34 => [0xFF54], 0xFF35 => [0xFF55], 0xFF36 => [0xFF56],
|
||||
0xFF37 => [0xFF57], 0xFF38 => [0xFF58], 0xFF39 => [0xFF59],
|
||||
0xFF3A => [0xFF5A], 0x10400 => [0x10428], 0x10401 => [0x10429],
|
||||
0x10402 => [0x1042A], 0x10403 => [0x1042B], 0x10404 => [0x1042C],
|
||||
0x10405 => [0x1042D], 0x10406 => [0x1042E], 0x10407 => [0x1042F],
|
||||
0x10408 => [0x10430], 0x10409 => [0x10431], 0x1040A => [0x10432],
|
||||
0x1040B => [0x10433], 0x1040C => [0x10434], 0x1040D => [0x10435],
|
||||
0x1040E => [0x10436], 0x1040F => [0x10437], 0x10410 => [0x10438],
|
||||
0x10411 => [0x10439], 0x10412 => [0x1043A], 0x10413 => [0x1043B],
|
||||
0x10414 => [0x1043C], 0x10415 => [0x1043D], 0x10416 => [0x1043E],
|
||||
0x10417 => [0x1043F], 0x10418 => [0x10440], 0x10419 => [0x10441],
|
||||
0x1041A => [0x10442], 0x1041B => [0x10443], 0x1041C => [0x10444],
|
||||
0x1041D => [0x10445], 0x1041E => [0x10446], 0x1041F => [0x10447],
|
||||
0x10420 => [0x10448], 0x10421 => [0x10449], 0x10422 => [0x1044A],
|
||||
0x10423 => [0x1044B], 0x10424 => [0x1044C], 0x10425 => [0x1044D],
|
||||
0x1D400 => [0x61], 0x1D401 => [0x62], 0x1D402 => [0x63],
|
||||
0x1D403 => [0x64], 0x1D404 => [0x65], 0x1D405 => [0x66],
|
||||
0x1D406 => [0x67], 0x1D407 => [0x68], 0x1D408 => [0x69],
|
||||
0x1D409 => [0x6A], 0x1D40A => [0x6B], 0x1D40B => [0x6C],
|
||||
0x1D40C => [0x6D], 0x1D40D => [0x6E], 0x1D40E => [0x6F],
|
||||
0x1D40F => [0x70], 0x1D410 => [0x71], 0x1D411 => [0x72],
|
||||
0x1D412 => [0x73], 0x1D413 => [0x74], 0x1D414 => [0x75],
|
||||
0x1D415 => [0x76], 0x1D416 => [0x77], 0x1D417 => [0x78],
|
||||
0x1D418 => [0x79], 0x1D419 => [0x7A], 0x1D434 => [0x61],
|
||||
0x1D435 => [0x62], 0x1D436 => [0x63], 0x1D437 => [0x64],
|
||||
0x1D438 => [0x65], 0x1D439 => [0x66], 0x1D43A => [0x67],
|
||||
0x1D43B => [0x68], 0x1D43C => [0x69], 0x1D43D => [0x6A],
|
||||
0x1D43E => [0x6B], 0x1D43F => [0x6C], 0x1D440 => [0x6D],
|
||||
0x1D441 => [0x6E], 0x1D442 => [0x6F], 0x1D443 => [0x70],
|
||||
0x1D444 => [0x71], 0x1D445 => [0x72], 0x1D446 => [0x73],
|
||||
0x1D447 => [0x74], 0x1D448 => [0x75], 0x1D449 => [0x76],
|
||||
0x1D44A => [0x77], 0x1D44B => [0x78], 0x1D44C => [0x79],
|
||||
0x1D44D => [0x7A], 0x1D468 => [0x61], 0x1D469 => [0x62],
|
||||
0x1D46A => [0x63], 0x1D46B => [0x64], 0x1D46C => [0x65],
|
||||
0x1D46D => [0x66], 0x1D46E => [0x67], 0x1D46F => [0x68],
|
||||
0x1D470 => [0x69], 0x1D471 => [0x6A], 0x1D472 => [0x6B],
|
||||
0x1D473 => [0x6C], 0x1D474 => [0x6D], 0x1D475 => [0x6E],
|
||||
0x1D476 => [0x6F], 0x1D477 => [0x70], 0x1D478 => [0x71],
|
||||
0x1D479 => [0x72], 0x1D47A => [0x73], 0x1D47B => [0x74],
|
||||
0x1D47C => [0x75], 0x1D47D => [0x76], 0x1D47E => [0x77],
|
||||
0x1D47F => [0x78], 0x1D480 => [0x79], 0x1D481 => [0x7A],
|
||||
0x1D49C => [0x61], 0x1D49E => [0x63], 0x1D49F => [0x64],
|
||||
0x1D4A2 => [0x67], 0x1D4A5 => [0x6A], 0x1D4A6 => [0x6B],
|
||||
0x1D4A9 => [0x6E], 0x1D4AA => [0x6F], 0x1D4AB => [0x70],
|
||||
0x1D4AC => [0x71], 0x1D4AE => [0x73], 0x1D4AF => [0x74],
|
||||
0x1D4B0 => [0x75], 0x1D4B1 => [0x76], 0x1D4B2 => [0x77],
|
||||
0x1D4B3 => [0x78], 0x1D4B4 => [0x79], 0x1D4B5 => [0x7A],
|
||||
0x1D4D0 => [0x61], 0x1D4D1 => [0x62], 0x1D4D2 => [0x63],
|
||||
0x1D4D3 => [0x64], 0x1D4D4 => [0x65], 0x1D4D5 => [0x66],
|
||||
0x1D4D6 => [0x67], 0x1D4D7 => [0x68], 0x1D4D8 => [0x69],
|
||||
0x1D4D9 => [0x6A], 0x1D4DA => [0x6B], 0x1D4DB => [0x6C],
|
||||
0x1D4DC => [0x6D], 0x1D4DD => [0x6E], 0x1D4DE => [0x6F],
|
||||
0x1D4DF => [0x70], 0x1D4E0 => [0x71], 0x1D4E1 => [0x72],
|
||||
0x1D4E2 => [0x73], 0x1D4E3 => [0x74], 0x1D4E4 => [0x75],
|
||||
0x1D4E5 => [0x76], 0x1D4E6 => [0x77], 0x1D4E7 => [0x78],
|
||||
0x1D4E8 => [0x79], 0x1D4E9 => [0x7A], 0x1D504 => [0x61],
|
||||
0x1D505 => [0x62], 0x1D507 => [0x64], 0x1D508 => [0x65],
|
||||
0x1D509 => [0x66], 0x1D50A => [0x67], 0x1D50D => [0x6A],
|
||||
0x1D50E => [0x6B], 0x1D50F => [0x6C], 0x1D510 => [0x6D],
|
||||
0x1D511 => [0x6E], 0x1D512 => [0x6F], 0x1D513 => [0x70],
|
||||
0x1D514 => [0x71], 0x1D516 => [0x73], 0x1D517 => [0x74],
|
||||
0x1D518 => [0x75], 0x1D519 => [0x76], 0x1D51A => [0x77],
|
||||
0x1D51B => [0x78], 0x1D51C => [0x79], 0x1D538 => [0x61],
|
||||
0x1D539 => [0x62], 0x1D53B => [0x64], 0x1D53C => [0x65],
|
||||
0x1D53D => [0x66], 0x1D53E => [0x67], 0x1D540 => [0x69],
|
||||
0x1D541 => [0x6A], 0x1D542 => [0x6B], 0x1D543 => [0x6C],
|
||||
0x1D544 => [0x6D], 0x1D546 => [0x6F], 0x1D54A => [0x73],
|
||||
0x1D54B => [0x74], 0x1D54C => [0x75], 0x1D54D => [0x76],
|
||||
0x1D54E => [0x77], 0x1D54F => [0x78], 0x1D550 => [0x79],
|
||||
0x1D56C => [0x61], 0x1D56D => [0x62], 0x1D56E => [0x63],
|
||||
0x1D56F => [0x64], 0x1D570 => [0x65], 0x1D571 => [0x66],
|
||||
0x1D572 => [0x67], 0x1D573 => [0x68], 0x1D574 => [0x69],
|
||||
0x1D575 => [0x6A], 0x1D576 => [0x6B], 0x1D577 => [0x6C],
|
||||
0x1D578 => [0x6D], 0x1D579 => [0x6E], 0x1D57A => [0x6F],
|
||||
0x1D57B => [0x70], 0x1D57C => [0x71], 0x1D57D => [0x72],
|
||||
0x1D57E => [0x73], 0x1D57F => [0x74], 0x1D580 => [0x75],
|
||||
0x1D581 => [0x76], 0x1D582 => [0x77], 0x1D583 => [0x78],
|
||||
0x1D584 => [0x79], 0x1D585 => [0x7A], 0x1D5A0 => [0x61],
|
||||
0x1D5A1 => [0x62], 0x1D5A2 => [0x63], 0x1D5A3 => [0x64],
|
||||
0x1D5A4 => [0x65], 0x1D5A5 => [0x66], 0x1D5A6 => [0x67],
|
||||
0x1D5A7 => [0x68], 0x1D5A8 => [0x69], 0x1D5A9 => [0x6A],
|
||||
0x1D5AA => [0x6B], 0x1D5AB => [0x6C], 0x1D5AC => [0x6D],
|
||||
0x1D5AD => [0x6E], 0x1D5AE => [0x6F], 0x1D5AF => [0x70],
|
||||
0x1D5B0 => [0x71], 0x1D5B1 => [0x72], 0x1D5B2 => [0x73],
|
||||
0x1D5B3 => [0x74], 0x1D5B4 => [0x75], 0x1D5B5 => [0x76],
|
||||
0x1D5B6 => [0x77], 0x1D5B7 => [0x78], 0x1D5B8 => [0x79],
|
||||
0x1D5B9 => [0x7A], 0x1D5D4 => [0x61], 0x1D5D5 => [0x62],
|
||||
0x1D5D6 => [0x63], 0x1D5D7 => [0x64], 0x1D5D8 => [0x65],
|
||||
0x1D5D9 => [0x66], 0x1D5DA => [0x67], 0x1D5DB => [0x68],
|
||||
0x1D5DC => [0x69], 0x1D5DD => [0x6A], 0x1D5DE => [0x6B],
|
||||
0x1D5DF => [0x6C], 0x1D5E0 => [0x6D], 0x1D5E1 => [0x6E],
|
||||
0x1D5E2 => [0x6F], 0x1D5E3 => [0x70], 0x1D5E4 => [0x71],
|
||||
0x1D5E5 => [0x72], 0x1D5E6 => [0x73], 0x1D5E7 => [0x74],
|
||||
0x1D5E8 => [0x75], 0x1D5E9 => [0x76], 0x1D5EA => [0x77],
|
||||
0x1D5EB => [0x78], 0x1D5EC => [0x79], 0x1D5ED => [0x7A],
|
||||
0x1D608 => [0x61], 0x1D609 => [0x62], 0x1D60A => [0x63],
|
||||
0x1D60B => [0x64], 0x1D60C => [0x65], 0x1D60D => [0x66],
|
||||
0x1D60E => [0x67], 0x1D60F => [0x68], 0x1D610 => [0x69],
|
||||
0x1D611 => [0x6A], 0x1D612 => [0x6B], 0x1D613 => [0x6C],
|
||||
0x1D614 => [0x6D], 0x1D615 => [0x6E], 0x1D616 => [0x6F],
|
||||
0x1D617 => [0x70], 0x1D618 => [0x71], 0x1D619 => [0x72],
|
||||
0x1D61A => [0x73], 0x1D61B => [0x74], 0x1D61C => [0x75],
|
||||
0x1D61D => [0x76], 0x1D61E => [0x77], 0x1D61F => [0x78],
|
||||
0x1D620 => [0x79], 0x1D621 => [0x7A], 0x1D63C => [0x61],
|
||||
0x1D63D => [0x62], 0x1D63E => [0x63], 0x1D63F => [0x64],
|
||||
0x1D640 => [0x65], 0x1D641 => [0x66], 0x1D642 => [0x67],
|
||||
0x1D643 => [0x68], 0x1D644 => [0x69], 0x1D645 => [0x6A],
|
||||
0x1D646 => [0x6B], 0x1D647 => [0x6C], 0x1D648 => [0x6D],
|
||||
0x1D649 => [0x6E], 0x1D64A => [0x6F], 0x1D64B => [0x70],
|
||||
0x1D64C => [0x71], 0x1D64D => [0x72], 0x1D64E => [0x73],
|
||||
0x1D64F => [0x74], 0x1D650 => [0x75], 0x1D651 => [0x76],
|
||||
0x1D652 => [0x77], 0x1D653 => [0x78], 0x1D654 => [0x79],
|
||||
0x1D655 => [0x7A], 0x1D670 => [0x61], 0x1D671 => [0x62],
|
||||
0x1D672 => [0x63], 0x1D673 => [0x64], 0x1D674 => [0x65],
|
||||
0x1D675 => [0x66], 0x1D676 => [0x67], 0x1D677 => [0x68],
|
||||
0x1D678 => [0x69], 0x1D679 => [0x6A], 0x1D67A => [0x6B],
|
||||
0x1D67B => [0x6C], 0x1D67C => [0x6D], 0x1D67D => [0x6E],
|
||||
0x1D67E => [0x6F], 0x1D67F => [0x70], 0x1D680 => [0x71],
|
||||
0x1D681 => [0x72], 0x1D682 => [0x73], 0x1D683 => [0x74],
|
||||
0x1D684 => [0x75], 0x1D685 => [0x76], 0x1D686 => [0x77],
|
||||
0x1D687 => [0x78], 0x1D688 => [0x79], 0x1D689 => [0x7A],
|
||||
0x1D6A8 => [0x3B1], 0x1D6A9 => [0x3B2], 0x1D6AA => [0x3B3],
|
||||
0x1D6AB => [0x3B4], 0x1D6AC => [0x3B5], 0x1D6AD => [0x3B6],
|
||||
0x1D6AE => [0x3B7], 0x1D6AF => [0x3B8], 0x1D6B0 => [0x3B9],
|
||||
0x1D6B1 => [0x3BA], 0x1D6B2 => [0x3BB], 0x1D6B3 => [0x3BC],
|
||||
0x1D6B4 => [0x3BD], 0x1D6B5 => [0x3BE], 0x1D6B6 => [0x3BF],
|
||||
0x1D6B7 => [0x3C0], 0x1D6B8 => [0x3C1], 0x1D6B9 => [0x3B8],
|
||||
0x1D6BA => [0x3C3], 0x1D6BB => [0x3C4], 0x1D6BC => [0x3C5],
|
||||
0x1D6BD => [0x3C6], 0x1D6BE => [0x3C7], 0x1D6BF => [0x3C8],
|
||||
0x1D6C0 => [0x3C9], 0x1D6D3 => [0x3C3], 0x1D6E2 => [0x3B1],
|
||||
0x1D6E3 => [0x3B2], 0x1D6E4 => [0x3B3], 0x1D6E5 => [0x3B4],
|
||||
0x1D6E6 => [0x3B5], 0x1D6E7 => [0x3B6], 0x1D6E8 => [0x3B7],
|
||||
0x1D6E9 => [0x3B8], 0x1D6EA => [0x3B9], 0x1D6EB => [0x3BA],
|
||||
0x1D6EC => [0x3BB], 0x1D6ED => [0x3BC], 0x1D6EE => [0x3BD],
|
||||
0x1D6EF => [0x3BE], 0x1D6F0 => [0x3BF], 0x1D6F1 => [0x3C0],
|
||||
0x1D6F2 => [0x3C1], 0x1D6F3 => [0x3B8], 0x1D6F4 => [0x3C3],
|
||||
0x1D6F5 => [0x3C4], 0x1D6F6 => [0x3C5], 0x1D6F7 => [0x3C6],
|
||||
0x1D6F8 => [0x3C7], 0x1D6F9 => [0x3C8], 0x1D6FA => [0x3C9],
|
||||
0x1D70D => [0x3C3], 0x1D71C => [0x3B1], 0x1D71D => [0x3B2],
|
||||
0x1D71E => [0x3B3], 0x1D71F => [0x3B4], 0x1D720 => [0x3B5],
|
||||
0x1D721 => [0x3B6], 0x1D722 => [0x3B7], 0x1D723 => [0x3B8],
|
||||
0x1D724 => [0x3B9], 0x1D725 => [0x3BA], 0x1D726 => [0x3BB],
|
||||
0x1D727 => [0x3BC], 0x1D728 => [0x3BD], 0x1D729 => [0x3BE],
|
||||
0x1D72A => [0x3BF], 0x1D72B => [0x3C0], 0x1D72C => [0x3C1],
|
||||
0x1D72D => [0x3B8], 0x1D72E => [0x3C3], 0x1D72F => [0x3C4],
|
||||
0x1D730 => [0x3C5], 0x1D731 => [0x3C6], 0x1D732 => [0x3C7],
|
||||
0x1D733 => [0x3C8], 0x1D734 => [0x3C9], 0x1D747 => [0x3C3],
|
||||
0x1D756 => [0x3B1], 0x1D757 => [0x3B2], 0x1D758 => [0x3B3],
|
||||
0x1D759 => [0x3B4], 0x1D75A => [0x3B5], 0x1D75B => [0x3B6],
|
||||
0x1D75C => [0x3B7], 0x1D75D => [0x3B8], 0x1D75E => [0x3B9],
|
||||
0x1D75F => [0x3BA], 0x1D760 => [0x3BB], 0x1D761 => [0x3BC],
|
||||
0x1D762 => [0x3BD], 0x1D763 => [0x3BE], 0x1D764 => [0x3BF],
|
||||
0x1D765 => [0x3C0], 0x1D766 => [0x3C1], 0x1D767 => [0x3B8],
|
||||
0x1D768 => [0x3C3], 0x1D769 => [0x3C4], 0x1D76A => [0x3C5],
|
||||
0x1D76B => [0x3C6], 0x1D76C => [0x3C7], 0x1D76D => [0x3C8],
|
||||
0x1D76E => [0x3C9], 0x1D781 => [0x3C3], 0x1D790 => [0x3B1],
|
||||
0x1D791 => [0x3B2], 0x1D792 => [0x3B3], 0x1D793 => [0x3B4],
|
||||
0x1D794 => [0x3B5], 0x1D795 => [0x3B6], 0x1D796 => [0x3B7],
|
||||
0x1D797 => [0x3B8], 0x1D798 => [0x3B9], 0x1D799 => [0x3BA],
|
||||
0x1D79A => [0x3BB], 0x1D79B => [0x3BC], 0x1D79C => [0x3BD],
|
||||
0x1D79D => [0x3BE], 0x1D79E => [0x3BF], 0x1D79F => [0x3C0],
|
||||
0x1D7A0 => [0x3C1], 0x1D7A1 => [0x3B8], 0x1D7A2 => [0x3C3],
|
||||
0x1D7A3 => [0x3C4], 0x1D7A4 => [0x3C5], 0x1D7A5 => [0x3C6],
|
||||
0x1D7A6 => [0x3C7], 0x1D7A7 => [0x3C8], 0x1D7A8 => [0x3C9],
|
||||
0x1D7BB => [0x3C3], 0x3F9 => [0x3C3], 0x1D2C => [0x61],
|
||||
0x1D2D => [0xE6], 0x1D2E => [0x62], 0x1D30 => [0x64],
|
||||
0x1D31 => [0x65], 0x1D32 => [0x1DD], 0x1D33 => [0x67],
|
||||
0x1D34 => [0x68], 0x1D35 => [0x69], 0x1D36 => [0x6A],
|
||||
0x1D37 => [0x6B], 0x1D38 => [0x6C], 0x1D39 => [0x6D],
|
||||
0x1D3A => [0x6E], 0x1D3C => [0x6F], 0x1D3D => [0x223],
|
||||
0x1D3E => [0x70], 0x1D3F => [0x72], 0x1D40 => [0x74],
|
||||
0x1D41 => [0x75], 0x1D42 => [0x77], 0x213B => [0x66, 0x61, 0x78],
|
||||
0x3250 => [0x70, 0x74, 0x65], 0x32CC => [0x68, 0x67],
|
||||
0x32CE => [0x65, 0x76], 0x32CF => [0x6C, 0x74, 0x64],
|
||||
0x337A => [0x69, 0x75], 0x33DE => [0x76, 0x2215, 0x6D],
|
||||
0x33DF => [0x61, 0x2215, 0x6D]
|
||||
];
|
||||
}
|
||||
1924
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepData2008.php
vendored
Normal file
1924
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepData2008.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepDataInterface.php
vendored
Normal file
7
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepDataInterface.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\NamePrep;
|
||||
|
||||
interface NamePrepDataInterface
|
||||
{
|
||||
}
|
||||
12
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepInterface.php
vendored
Normal file
12
libraries/vendor/algo26-matthias/idna-convert/src/NamePrep/NamePrepInterface.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace Algo26\IdnaConvert\NamePrep;
|
||||
|
||||
interface NamePrepInterface
|
||||
{
|
||||
/**
|
||||
* @param array $inputArray
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function do(array $inputArray): array;
|
||||
}
|
||||
86
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/AbstractPunycode.php
vendored
Normal file
86
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/AbstractPunycode.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\Punycode;
|
||||
|
||||
use Algo26\IdnaConvert\TranscodeUnicode\TranscodeUnicode;
|
||||
|
||||
abstract class AbstractPunycode
|
||||
{
|
||||
const punycodePrefix = 'xn--';
|
||||
const invalidUcs = 0x80000000;
|
||||
const maxUcs = 0x10FFFF;
|
||||
const base = 36;
|
||||
const tMin = 1;
|
||||
const tMax = 26;
|
||||
const skew = 38;
|
||||
const damp = 700;
|
||||
const initialBias = 72;
|
||||
const initialN = 0x80;
|
||||
|
||||
protected static $isMbStringOverload;
|
||||
protected static $prefixAsArray;
|
||||
protected static $prefixLength;
|
||||
|
||||
/** @var TranscodeUnicode */
|
||||
protected $unicodeTransCoder;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->unicodeTransCoder = new TranscodeUnicode();
|
||||
|
||||
// populate mbstring overloading cache if not set
|
||||
if (self::$isMbStringOverload === null) {
|
||||
self::$isMbStringOverload = (extension_loaded('mbstring')
|
||||
&& (ini_get('mbstring.func_overload') & 0x02) === 0x02);
|
||||
}
|
||||
|
||||
if (self::$prefixAsArray === null) {
|
||||
self::$prefixAsArray = $this->unicodeTransCoder->convert(
|
||||
self::punycodePrefix,
|
||||
$this->unicodeTransCoder::FORMAT_UTF8,
|
||||
$this->unicodeTransCoder::FORMAT_UCS4_ARRAY
|
||||
);
|
||||
self::$prefixLength = $this->byteLength(self::punycodePrefix);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPunycodePrefix(): string
|
||||
{
|
||||
return self::punycodePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of a string in bytes even if mbstring function
|
||||
* overloading is turned on
|
||||
*
|
||||
* @param string $string the string for which to get the length.
|
||||
* @return integer the length of the string in bytes.
|
||||
*/
|
||||
protected function byteLength($string): int
|
||||
{
|
||||
if (self::$isMbStringOverload) {
|
||||
return mb_strlen($string, '8bit');
|
||||
}
|
||||
|
||||
return strlen((binary) $string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapt the bias according to the current code point and position
|
||||
* @param int $delta
|
||||
* @param int $nPoints
|
||||
* @param int $isFirst
|
||||
* @return int
|
||||
*/
|
||||
protected function adapt($delta, $nPoints, $isFirst): int
|
||||
{
|
||||
$delta = intval($isFirst ? ($delta / self::damp) : ($delta / 2));
|
||||
$delta += intval($delta / $nPoints);
|
||||
for ($k = 0; $delta > ((self::base - self::tMin) * self::tMax) / 2; $k += self::base) {
|
||||
$delta = intval($delta / (self::base - self::tMin));
|
||||
}
|
||||
|
||||
return intval($k + (self::base - self::tMin + 1) * $delta / ($delta + self::skew));
|
||||
}
|
||||
}
|
||||
114
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/FromPunycode.php
vendored
Normal file
114
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/FromPunycode.php
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\Punycode;
|
||||
|
||||
class FromPunycode extends AbstractPunycode implements PunycodeInterface
|
||||
{
|
||||
public function __construct(?string $idnVersion = null)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual decoding algorithm
|
||||
* @param string
|
||||
* @return mixed
|
||||
*/
|
||||
public function convert($encoded)
|
||||
{
|
||||
if (!$this->validate($encoded)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$decoded = [];
|
||||
// Find last occurrence of the delimiter
|
||||
$delimiterPosition = strrpos($encoded, '-');
|
||||
if ($delimiterPosition > self::byteLength(self::punycodePrefix)) {
|
||||
for ($k = $this->byteLength(self::punycodePrefix); $k < $delimiterPosition; ++$k) {
|
||||
$decoded[] = ord($encoded[$k]);
|
||||
}
|
||||
}
|
||||
$decodedLength = count($decoded);
|
||||
$encodedLength = $this->byteLength($encoded);
|
||||
|
||||
// Wandering through the strings; init
|
||||
$isFirst = true;
|
||||
$bias = self::initialBias;
|
||||
$currentIndex = 0;
|
||||
$char = self::initialN;
|
||||
|
||||
for ($encodedIndex = ($delimiterPosition) ? ($delimiterPosition + 1) : 0; $encodedIndex < $encodedLength; ++$decodedLength) {
|
||||
for ($oldIndex = $currentIndex, $w = 1, $k = self::base; 1; $k += self::base) {
|
||||
$digit = $this->decodeDigit($encoded[$encodedIndex++]);
|
||||
$currentIndex += $digit * $w;
|
||||
$t = ($k <= $bias)
|
||||
? self::tMin
|
||||
: (
|
||||
($k >= $bias + self::tMax)
|
||||
? self::tMax
|
||||
: ($k - $bias)
|
||||
);
|
||||
if ($digit < $t) {
|
||||
break;
|
||||
}
|
||||
$w = (int) ($w * (self::base - $t));
|
||||
}
|
||||
$bias = $this->adapt($currentIndex - $oldIndex, $decodedLength + 1, $isFirst);
|
||||
$isFirst = false;
|
||||
$char += (int) ($currentIndex / ($decodedLength + 1));
|
||||
$currentIndex %= ($decodedLength + 1);
|
||||
if ($decodedLength > 0) {
|
||||
// Make room for the decoded char
|
||||
for ($i = $decodedLength; $i > $currentIndex; $i--) {
|
||||
$decoded[$i] = $decoded[($i - 1)];
|
||||
}
|
||||
}
|
||||
$decoded[$currentIndex++] = $char;
|
||||
}
|
||||
|
||||
return $this->unicodeTransCoder->convert(
|
||||
$decoded,
|
||||
$this->unicodeTransCoder::FORMAT_UCS4_ARRAY,
|
||||
$this->unicodeTransCoder::FORMAT_UTF8
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks, whether or not the provided string is a valid punycode string
|
||||
* @param string $encoded
|
||||
* @return boolean
|
||||
*/
|
||||
private function validate($encoded): bool
|
||||
{
|
||||
// Check for existence of the prefix
|
||||
if (strpos($encoded, self::punycodePrefix) !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If nothing is left after the prefix, it is hopeless
|
||||
if (strlen(trim($encoded)) <= strlen(self::punycodePrefix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function decodeDigit(string $cp): int
|
||||
{
|
||||
$cp = ord($cp);
|
||||
if ($cp - 48 < 10) {
|
||||
return $cp - 22;
|
||||
}
|
||||
|
||||
if ($cp - 65 < 26) {
|
||||
return $cp - 65;
|
||||
}
|
||||
|
||||
if ($cp - 97 < 26) {
|
||||
return $cp - 97;
|
||||
}
|
||||
|
||||
return self::base;
|
||||
}
|
||||
}
|
||||
9
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/PunycodeInterface.php
vendored
Normal file
9
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/PunycodeInterface.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace Algo26\IdnaConvert\Punycode;
|
||||
|
||||
interface PunycodeInterface
|
||||
{
|
||||
public function __construct(string $idnVersion = null);
|
||||
|
||||
public function getPunycodePrefix();
|
||||
}
|
||||
147
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/ToPunycode.php
vendored
Normal file
147
libraries/vendor/algo26-matthias/idna-convert/src/Punycode/ToPunycode.php
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Algo26\IdnaConvert\Punycode;
|
||||
|
||||
use Algo26\IdnaConvert\Exception\AlreadyPunycodeException;
|
||||
use Algo26\IdnaConvert\Exception\InvalidCharacterException;
|
||||
use Algo26\IdnaConvert\Exception\InvalidIdnVersionException;
|
||||
use Algo26\IdnaConvert\NamePrep\NamePrep;
|
||||
|
||||
class ToPunycode extends AbstractPunycode implements PunycodeInterface
|
||||
{
|
||||
/** @var NamePrep */
|
||||
private $namePrep;
|
||||
|
||||
/**
|
||||
* @throws InvalidIdnVersionException
|
||||
*/
|
||||
public function __construct(?string $idnVersion = null)
|
||||
{
|
||||
$this->namePrep = new NamePrep($idnVersion);
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $decoded
|
||||
*
|
||||
* @return string
|
||||
* @throws AlreadyPunycodeException
|
||||
* @throws InvalidCharacterException
|
||||
*/
|
||||
public function convert(array $decoded): string
|
||||
{
|
||||
// We cannot encode a domain name containing the Punycode prefix
|
||||
$checkForPrefix = array_slice($decoded, 0, self::$prefixLength);
|
||||
if (self::$prefixAsArray === $checkForPrefix) {
|
||||
throw new AlreadyPunycodeException('This is already a Punycode string', 100);
|
||||
}
|
||||
// We will not try to encode strings consisting of basic code points only
|
||||
$canEncode = false;
|
||||
foreach ($decoded as $k => $v) {
|
||||
if ($v > 0x7a) {
|
||||
$canEncode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$canEncode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do NAMEPREP
|
||||
$decoded = $this->namePrep->do($decoded);
|
||||
if (!$decoded || !is_array($decoded)) {
|
||||
return false; // NAMEPREP failed
|
||||
}
|
||||
|
||||
$decodedLength = count($decoded);
|
||||
if (!$decodedLength) {
|
||||
return false; // Empty array
|
||||
}
|
||||
|
||||
$codeCount = 0; // How many chars have been consumed
|
||||
$encoded = '';
|
||||
// Copy all basic code points to output
|
||||
for ($i = 0; $i < $decodedLength; ++$i) {
|
||||
$test = $decoded[$i];
|
||||
if (0x01 <= $test && $test <= 0x7f) {
|
||||
$encoded .= chr($decoded[$i]);
|
||||
$codeCount++;
|
||||
}
|
||||
}
|
||||
if ($codeCount === $decodedLength) {
|
||||
return $encoded; // All codepoints were basic ones
|
||||
}
|
||||
|
||||
// Start with the prefix; copy it to output
|
||||
$encoded = self::punycodePrefix . $encoded;
|
||||
// If we have basic code points in output, add a hyphen to the end
|
||||
if ($codeCount > 0) {
|
||||
$encoded .= '-';
|
||||
}
|
||||
|
||||
// Now find and encode all non-basic code points
|
||||
$isFirst = true;
|
||||
$currentCode = self::initialN;
|
||||
$bias = self::initialBias;
|
||||
$delta = 0;
|
||||
|
||||
while ($codeCount < $decodedLength) {
|
||||
$nextCode = self::maxUcs;
|
||||
// Find the next largest code point to $currentCode
|
||||
foreach ($decoded as $nextLargestCandidate) {
|
||||
if ($nextLargestCandidate >= $currentCode && $nextLargestCandidate <= $nextCode) {
|
||||
$nextCode = $nextLargestCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
$codeCountPlusOne = $codeCount + 1;
|
||||
|
||||
$delta += ($nextCode - $currentCode) * $codeCountPlusOne;
|
||||
$currentCode = $nextCode;
|
||||
|
||||
// Scan input again and encode all characters whose code point is $currentCode
|
||||
for ($i = 0; $i < $decodedLength; $i++) {
|
||||
if ($decoded[$i] < $currentCode) {
|
||||
$delta++;
|
||||
}
|
||||
|
||||
if ($decoded[$i] === $currentCode) {
|
||||
for ($q = $delta, $k = self::base; 1; $k += self::base) {
|
||||
$t = ($k <= $bias)
|
||||
? self::tMin
|
||||
: (($k >= $bias + self::tMax)
|
||||
? self::tMax
|
||||
: $k - $bias
|
||||
);
|
||||
if ($q < $t) {
|
||||
break;
|
||||
}
|
||||
|
||||
$encoded .= $this->encodeDigit(intval($t + (($q - $t) % (self::base - $t))));
|
||||
$q = (int) (($q - $t) / (self::base - $t));
|
||||
}
|
||||
$encoded .= $this->encodeDigit($q);
|
||||
$bias = $this->adapt($delta, $codeCountPlusOne, $isFirst);
|
||||
$codeCount++;
|
||||
$delta = 0;
|
||||
$isFirst = false;
|
||||
}
|
||||
}
|
||||
|
||||
$delta++;
|
||||
$currentCode++;
|
||||
}
|
||||
|
||||
return $encoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding a certain digit
|
||||
* @param int $d
|
||||
* @return string
|
||||
*/
|
||||
private function encodeDigit($d): string
|
||||
{
|
||||
return chr($d + 22 + 75 * ($d < 26));
|
||||
}
|
||||
}
|
||||
66
libraries/vendor/algo26-matthias/idna-convert/src/ToIdn.php
vendored
Normal file
66
libraries/vendor/algo26-matthias/idna-convert/src/ToIdn.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace Algo26\IdnaConvert;
|
||||
|
||||
use Algo26\IdnaConvert\Exception\InvalidCharacterException;
|
||||
use Algo26\IdnaConvert\Exception\InvalidIdnVersionException;
|
||||
use Algo26\IdnaConvert\Punycode\ToPunycode;
|
||||
use Algo26\IdnaConvert\TranscodeUnicode\TranscodeUnicode;
|
||||
|
||||
class ToIdn extends AbstractIdnaConvert implements IdnaConvertInterface
|
||||
{
|
||||
/** @var TranscodeUnicode */
|
||||
private $unicodeTransCoder;
|
||||
|
||||
/** @var ToPunycode */
|
||||
private $punycodeEncoder;
|
||||
|
||||
/**
|
||||
* @throws InvalidIdnVersionException
|
||||
*/
|
||||
public function __construct($idnVersion = null)
|
||||
{
|
||||
$this->unicodeTransCoder = new TranscodeUnicode();
|
||||
$this->punycodeEncoder = new ToPunycode($idnVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
*
|
||||
* @return string
|
||||
* @throws InvalidCharacterException
|
||||
* @throws Exception\AlreadyPunycodeException
|
||||
*/
|
||||
public function convert(string $host): string
|
||||
{
|
||||
if (strlen($host) === 0) {
|
||||
return $host;
|
||||
}
|
||||
|
||||
if (strpos('/', $host) !== false
|
||||
|| strpos(':', $host) !== false
|
||||
|| strpos('?', $host) !== false
|
||||
|| strpos('@', $host) !== false
|
||||
) {
|
||||
throw new InvalidCharacterException('Neither email addresses nor URLs are allowed', 205);
|
||||
}
|
||||
|
||||
// These three punctuation characters are treated like the dot
|
||||
$host = str_replace(['。', '.', '。'], '.', $host);
|
||||
|
||||
// Operate per label
|
||||
$hostLabels = explode('.', $host);
|
||||
foreach ($hostLabels as $index => $label) {
|
||||
$asUcs4Array = $this->unicodeTransCoder->convert(
|
||||
$label,
|
||||
$this->unicodeTransCoder::FORMAT_UTF8,
|
||||
$this->unicodeTransCoder::FORMAT_UCS4_ARRAY
|
||||
);
|
||||
$encoded = $this->punycodeEncoder->convert($asUcs4Array);
|
||||
if ($encoded) {
|
||||
$hostLabels[$index] = $encoded;
|
||||
}
|
||||
}
|
||||
|
||||
return implode('.', $hostLabels);
|
||||
}
|
||||
}
|
||||
37
libraries/vendor/algo26-matthias/idna-convert/src/ToUnicode.php
vendored
Normal file
37
libraries/vendor/algo26-matthias/idna-convert/src/ToUnicode.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace Algo26\IdnaConvert;
|
||||
|
||||
use Algo26\IdnaConvert\Punycode\FromPunycode;
|
||||
use Algo26\IdnaConvert\TranscodeUnicode\TranscodeUnicode;
|
||||
|
||||
class ToUnicode extends AbstractIdnaConvert implements IdnaConvertInterface
|
||||
{
|
||||
/** @var TranscodeUnicode */
|
||||
private $unicodeTransCoder;
|
||||
|
||||
/** @var FromPunycode */
|
||||
private $punycodeEncoder;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->unicodeTransCoder = new TranscodeUnicode();
|
||||
$this->punycodeEncoder = new FromPunycode();
|
||||
}
|
||||
|
||||
public function convert(string $host): string
|
||||
{
|
||||
// Drop any whitespace around
|
||||
$input = trim($host);
|
||||
|
||||
$hostLabels = explode('.', $input);
|
||||
foreach ($hostLabels as $index => $label) {
|
||||
$return = $this->punycodeEncoder->convert($label);
|
||||
if (!$return) {
|
||||
$return = $label;
|
||||
}
|
||||
$hostLabels[$index] = $return;
|
||||
}
|
||||
|
||||
return implode('.', $hostLabels);
|
||||
}
|
||||
}
|
||||
437
libraries/vendor/algo26-matthias/idna-convert/src/TranscodeUnicode/TranscodeUnicode.php
vendored
Normal file
437
libraries/vendor/algo26-matthias/idna-convert/src/TranscodeUnicode/TranscodeUnicode.php
vendored
Normal file
@ -0,0 +1,437 @@
|
||||
<?php
|
||||
/**
|
||||
* Converts between various flavours of Unicode representations like UCS-4 or UTF-8
|
||||
* Supported schemes:
|
||||
* - UCS-4 Little Endian / Big Endian / Array (partially)
|
||||
* - UTF-16 Little Endian / Big Endian (not yet)
|
||||
* - UTF-8
|
||||
* - UTF-7
|
||||
* - UTF-7 IMAP (modified UTF-7)
|
||||
*
|
||||
* @package IdnaConvert
|
||||
* @author Matthias Sommerfeld <matthias.sommerfeld@algo26.de>
|
||||
* @copyright 2003-2019 algo26 Beratungs GmbH, Berlin, https://www.algo26.de
|
||||
*/
|
||||
|
||||
namespace Algo26\IdnaConvert\TranscodeUnicode;
|
||||
|
||||
use Algo26\IdnaConvert\Exception\InvalidCharacterException;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class TranscodeUnicode implements TranscodeUnicodeInterface
|
||||
{
|
||||
public const FORMAT_UCS4 = 'ucs4';
|
||||
public const FORMAT_UCS4_ARRAY = 'ucs4array';
|
||||
public const FORMAT_UTF8 = 'utf8';
|
||||
public const FORMAT_UTF7 = 'utf7';
|
||||
public const FORMAT_UTF7_IMAP = 'utf7imap';
|
||||
|
||||
private const encodings = [
|
||||
self::FORMAT_UCS4,
|
||||
self::FORMAT_UCS4_ARRAY,
|
||||
self::FORMAT_UTF8,
|
||||
self::FORMAT_UTF7,
|
||||
self::FORMAT_UTF7_IMAP
|
||||
];
|
||||
|
||||
private $safeMode;
|
||||
private $safeCodepoint = 0xFFFC;
|
||||
|
||||
public function convert(
|
||||
$data,
|
||||
string $fromEncoding,
|
||||
string $toEncoding,
|
||||
bool $safeMode = false,
|
||||
?int $safeCodepoint = null
|
||||
) {
|
||||
$this->safeMode = $safeMode;
|
||||
if ($safeCodepoint !== null) {
|
||||
$this->safeCodepoint = $safeCodepoint;
|
||||
}
|
||||
|
||||
$fromEncoding = strtolower($fromEncoding);
|
||||
$toEncoding = strtolower($toEncoding);
|
||||
|
||||
if ($fromEncoding === $toEncoding) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (!in_array($fromEncoding, self::encodings)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid input format %s', $fromEncoding), 300);
|
||||
}
|
||||
if (!in_array($toEncoding, self::encodings)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid output format %s', $toEncoding), 301);
|
||||
}
|
||||
|
||||
if ($fromEncoding !== self::FORMAT_UCS4_ARRAY) {
|
||||
$methodName = sprintf('%s_%s', $fromEncoding, self::FORMAT_UCS4_ARRAY);
|
||||
$data = $this->$methodName($data);
|
||||
}
|
||||
if ($toEncoding !== self::FORMAT_UCS4_ARRAY) {
|
||||
$methodName = sprintf('%s_%s', self::FORMAT_UCS4_ARRAY, $toEncoding);
|
||||
$data = $this->$methodName($data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* This converts an UTF-8 encoded string to its UCS-4 representation
|
||||
*
|
||||
* @param string $input The UTF-8 string to convert
|
||||
*
|
||||
* @return array Array of 32bit values representing each codepoint
|
||||
* @throws InvalidCharacterException
|
||||
* @access public
|
||||
*/
|
||||
private function utf8_ucs4array($input)
|
||||
{
|
||||
$startByte = 0;
|
||||
$nextByte = 0;
|
||||
|
||||
$output = [];
|
||||
$outputLength = 0;
|
||||
$inputLength = $this->byteLength($input);
|
||||
$mode = 'next';
|
||||
$test = 'none';
|
||||
for ($k = 0; $k < $inputLength; ++$k) {
|
||||
$v = ord($input[$k]); // Extract byte from input string
|
||||
|
||||
if ($v < 128) { // We found an ASCII char - put into string as is
|
||||
$output[$outputLength] = $v;
|
||||
++$outputLength;
|
||||
if ('add' === $mode) {
|
||||
if ($this->safeMode) {
|
||||
$output[$outputLength - 2] = $this->safeCodepoint;
|
||||
$mode = 'next';
|
||||
} else {
|
||||
throw new InvalidCharacterException(
|
||||
sprintf(
|
||||
'Conversion from UTF-8 to UCS-4 failed: malformed input at byte %d',
|
||||
$k
|
||||
),
|
||||
302
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('next' === $mode) { // Try to find the next start byte; determine the width of the Unicode char
|
||||
$startByte = $v;
|
||||
$mode = 'add';
|
||||
$test = 'range';
|
||||
if ($v >> 5 === 6) { // &110xxxxx 10xxxxx
|
||||
$nextByte = 0; // How many times subsequent bit masks must rotate 6bits to the left
|
||||
$v = ($v - 192) << 6;
|
||||
} elseif ($v >> 4 === 14) { // &1110xxxx 10xxxxxx 10xxxxxx
|
||||
$nextByte = 1;
|
||||
$v = ($v - 224) << 12;
|
||||
} elseif ($v >> 3 === 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
$nextByte = 2;
|
||||
$v = ($v - 240) << 18;
|
||||
} elseif ($this->safeMode) {
|
||||
$mode = 'next';
|
||||
$output[$outputLength] = $this->safeCodepoint;
|
||||
++$outputLength;
|
||||
|
||||
continue;
|
||||
} else {
|
||||
throw new InvalidCharacterException(
|
||||
sprintf('This might be UTF-8, but I don\'t understand it at byte %d', $k),
|
||||
303
|
||||
);
|
||||
}
|
||||
if (($inputLength - $k - $nextByte) < 2) {
|
||||
$output[$outputLength] = $this->safeCodepoint;
|
||||
$mode = 'no';
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('add' === $mode) {
|
||||
$output[$outputLength] = (int)$v;
|
||||
++$outputLength;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ('add' == $mode) {
|
||||
if (!$this->safeMode && $test === 'range') {
|
||||
$test = 'none';
|
||||
if (($v < 0xA0 && $startByte === 0xE0)
|
||||
|| ($v < 0x90 && $startByte === 0xF0)
|
||||
|| ($v > 0x8F && $startByte === 0xF4)
|
||||
) {
|
||||
throw new InvalidCharacterException(
|
||||
sprintf('Bogus UTF-8 character (out of legal range) at byte %d', $k),
|
||||
304
|
||||
);
|
||||
}
|
||||
}
|
||||
if ($v >> 6 === 2) { // Bit mask must be 10xxxxxx
|
||||
$v = ($v - 128) << ($nextByte * 6);
|
||||
$output[($outputLength - 1)] += $v;
|
||||
--$nextByte;
|
||||
} else {
|
||||
if ($this->safeMode) {
|
||||
$output[$outputLength - 1] = ord($this->safeCodepoint);
|
||||
$k--;
|
||||
$mode = 'next';
|
||||
|
||||
continue;
|
||||
} else {
|
||||
throw new InvalidCharacterException(
|
||||
sprintf('Conversion from UTF-8 to UCS-4 failed: malformed input at byte %d', $k),
|
||||
302
|
||||
);
|
||||
}
|
||||
}
|
||||
if ($nextByte < 0) {
|
||||
$mode = 'next';
|
||||
}
|
||||
}
|
||||
} // for
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UCS-4 arary into UTF-8 string
|
||||
* See utf8_ucs4array() for details
|
||||
*
|
||||
* @param $input array Array of UCS-4 codepoints
|
||||
*
|
||||
* @return string
|
||||
* @access public
|
||||
* @throws InvalidCharacterException
|
||||
*/
|
||||
private function ucs4array_utf8($input)
|
||||
{
|
||||
$output = '';
|
||||
foreach ($input as $k => $v) {
|
||||
if ($v < 128) { // 7bit are transferred literally
|
||||
$output .= chr($v);
|
||||
} elseif ($v < (1 << 11)) { // 2 bytes
|
||||
$output .= sprintf(
|
||||
'%s%s',
|
||||
chr(192 + ($v >> 6)),
|
||||
chr(128 + ($v & 63))
|
||||
);
|
||||
} elseif ($v < (1 << 16)) { // 3 bytes
|
||||
$output .= sprintf(
|
||||
'%s%s%s',
|
||||
chr(224 + ($v >> 12)),
|
||||
chr(128 + (($v >> 6) & 63)),
|
||||
chr(128 + ($v & 63))
|
||||
);
|
||||
} elseif ($v < (1 << 21)) { // 4 bytes
|
||||
$output .= sprintf(
|
||||
'%s%s%s%s',
|
||||
chr(240 + ($v >> 18)),
|
||||
chr(128 + (($v >> 12) & 63)),
|
||||
chr(128 + (($v >> 6) & 63)),
|
||||
chr(128 + ($v & 63))
|
||||
);
|
||||
} elseif ($this->safeMode) {
|
||||
$output .= $this->safeCodepoint;
|
||||
} else {
|
||||
throw new InvalidCharacterException(
|
||||
sprintf('Conversion from UCS-4 to UTF-8 failed: malformed input at byte %d', $k),
|
||||
305
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function utf7imap_ucs4array($input)
|
||||
{
|
||||
return $this->utf7_ucs4array(str_replace(',', '/', $input), '&');
|
||||
}
|
||||
|
||||
private function utf7_ucs4array($input, $sc = '+')
|
||||
{
|
||||
$output = [];
|
||||
$outputLength = 0;
|
||||
$inputLength = $this->byteLength($input);
|
||||
$mode = 'd';
|
||||
$b64 = '';
|
||||
|
||||
for ($k = 0; $k < $inputLength; ++$k) {
|
||||
$c = $input[$k];
|
||||
|
||||
// Ignore zero bytes
|
||||
if (0 === ord($c)) {
|
||||
continue;
|
||||
}
|
||||
if ('b' === $mode) {
|
||||
// Sequence got terminated
|
||||
if (!preg_match('![A-Za-z0-9/'.preg_quote($sc, '!').']!', $c)) {
|
||||
if ('-' == $c) {
|
||||
if ($b64 === '') {
|
||||
$output[$outputLength] = ord($sc);
|
||||
$outputLength++;
|
||||
$mode = 'd';
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$tmp = base64_decode($b64);
|
||||
$tmp = substr($tmp, -1 * (strlen($tmp) % 2));
|
||||
for ($i = 0; $i < strlen($tmp); $i++) {
|
||||
if ($i % 2) {
|
||||
$output[$outputLength] += ord($tmp[$i]);
|
||||
$outputLength++;
|
||||
} else {
|
||||
$output[$outputLength] = ord($tmp[$i]) << 8;
|
||||
}
|
||||
}
|
||||
$mode = 'd';
|
||||
$b64 = '';
|
||||
|
||||
continue;
|
||||
} else {
|
||||
$b64 .= $c;
|
||||
}
|
||||
}
|
||||
if ('d' === $mode) {
|
||||
if ($sc === $c) {
|
||||
$mode = 'b';
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$output[$outputLength] = ord($c);
|
||||
$outputLength++;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function ucs4array_utf7imap($input)
|
||||
{
|
||||
return str_replace(
|
||||
'/',
|
||||
',',
|
||||
$this->ucs4array_utf7($input, '&')
|
||||
);
|
||||
}
|
||||
|
||||
private function ucs4array_utf7($input, $sc = '+')
|
||||
{
|
||||
$output = '';
|
||||
$mode = 'd';
|
||||
$b64 = '';
|
||||
while (true) {
|
||||
$v = (!empty($input)) ? array_shift($input) : false;
|
||||
$isDirect = (false !== $v)
|
||||
? (0x20 <= $v && $v <= 0x7e && $v !== ord($sc))
|
||||
: true;
|
||||
if ($mode === 'b') {
|
||||
if ($isDirect) {
|
||||
if ($b64 === chr(0).$sc) {
|
||||
$output .= $sc.'-';
|
||||
$b64 = '';
|
||||
} elseif ($b64) {
|
||||
$output .= $sc.str_replace('=', '', base64_encode($b64)).'-';
|
||||
$b64 = '';
|
||||
}
|
||||
$mode = 'd';
|
||||
} elseif (false !== $v) {
|
||||
$b64 .= chr(($v >> 8) & 255).chr($v & 255);
|
||||
}
|
||||
}
|
||||
if ($mode === 'd' && false !== $v) {
|
||||
if ($isDirect) {
|
||||
$output .= chr($v);
|
||||
} else {
|
||||
$b64 = chr(($v >> 8) & 255).chr($v & 255);
|
||||
$mode = 'b';
|
||||
}
|
||||
}
|
||||
if (false === $v && $b64 === '') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UCS-4 array into UCS-4 string (Little Endian at the moment)
|
||||
* @param $input array UCS-4 code points
|
||||
* @return string
|
||||
* @access public
|
||||
*/
|
||||
private function ucs4array_ucs4($input)
|
||||
{
|
||||
$output = '';
|
||||
foreach ($input as $v) {
|
||||
$output .= sprintf(
|
||||
'%s%s%s%s',
|
||||
chr(($v >> 24) & 255),
|
||||
chr(($v >> 16) & 255),
|
||||
chr(($v >> 8) & 255),
|
||||
chr($v & 255)
|
||||
);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UCS-4 string (LE ar the moment) into UCS-4 array
|
||||
*
|
||||
* @param $input string UCS-4 LE string
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
* @throws InvalidCharacterException
|
||||
*/
|
||||
private function ucs4_ucs4array($input)
|
||||
{
|
||||
$output = [];
|
||||
|
||||
$inputLength = $this->byteLength($input);
|
||||
// Input length must be dividable by 4
|
||||
if ($inputLength % 4) {
|
||||
throw new InvalidCharacterException('Input UCS4 string is broken', 306);
|
||||
}
|
||||
// Empty input - return empty output
|
||||
if (!$inputLength) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
for ($i = 0, $outputLength = -1; $i < $inputLength; ++$i) {
|
||||
if (!($i % 4)) { // Increment output position every 4 input bytes
|
||||
$outputLength++;
|
||||
$output[$outputLength] = 0;
|
||||
}
|
||||
$output[$outputLength] += ord($input[$i]) << (8 * (3 - ($i % 4)));
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of a string in bytes even if mbstring function
|
||||
* overloading is turned on
|
||||
*
|
||||
* @param string $string the string for which to get the length.
|
||||
* @return integer the length of the string in bytes.
|
||||
*/
|
||||
protected function byteLength($string)
|
||||
{
|
||||
if ((extension_loaded('mbstring')
|
||||
&& (ini_get('mbstring.func_overload') & 0x02) === 0x02)
|
||||
) {
|
||||
return mb_strlen($string, '8bit');
|
||||
}
|
||||
|
||||
return strlen((binary) $string);
|
||||
}
|
||||
}
|
||||
13
libraries/vendor/algo26-matthias/idna-convert/src/TranscodeUnicode/TranscodeUnicodeInterface.php
vendored
Normal file
13
libraries/vendor/algo26-matthias/idna-convert/src/TranscodeUnicode/TranscodeUnicodeInterface.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace Algo26\IdnaConvert\TranscodeUnicode;
|
||||
|
||||
interface TranscodeUnicodeInterface
|
||||
{
|
||||
public function convert(
|
||||
$data,
|
||||
string $fromEncoding,
|
||||
string $toEncoding,
|
||||
bool $safeMode = false,
|
||||
int $safeCodepoint = 0xFFFC
|
||||
);
|
||||
}
|
||||
25
libraries/vendor/autoload.php
vendored
Normal file
25
libraries/vendor/autoload.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = '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;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit32fd40b9411b8100a91002ab36b71748::getLoader();
|
||||
20
libraries/vendor/brick/math/LICENSE
vendored
Normal file
20
libraries/vendor/brick/math/LICENSE
vendored
Normal 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.
|
||||
786
libraries/vendor/brick/math/src/BigDecimal.php
vendored
Normal file
786
libraries/vendor/brick/math/src/BigDecimal.php
vendored
Normal file
@ -0,0 +1,786 @@
|
||||
<?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.
|
||||
*/
|
||||
private string $value;
|
||||
|
||||
/**
|
||||
* The scale (number of digits after the decimal point) of this decimal number.
|
||||
*
|
||||
* This must be zero or more.
|
||||
*/
|
||||
private int $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.
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigDecimal.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigDecimal
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale is negative.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ofUnscaledValue(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function plus(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function minus(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function multipliedBy(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @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(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @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(BigNumber|int|float|string $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`.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function quotient(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function remainder(BigNumber|int|float|string $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(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public function abs() : BigDecimal
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this number.
|
||||
*/
|
||||
public function negated() : BigDecimal
|
||||
{
|
||||
return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
|
||||
}
|
||||
|
||||
public function compareTo(BigNumber|int|float|string $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);
|
||||
}
|
||||
|
||||
public function getSign() : int
|
||||
{
|
||||
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
||||
}
|
||||
|
||||
public function getUnscaledValue() : BigInteger
|
||||
{
|
||||
return self::newBigInteger($this->value);
|
||||
}
|
||||
|
||||
public function getScale() : int
|
||||
{
|
||||
return $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the integral part of this decimal number.
|
||||
*
|
||||
* Example: `-123.456` => `-123`.
|
||||
*/
|
||||
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` => ''.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public function hasNonZeroFractionalPart() : bool
|
||||
{
|
||||
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
|
||||
}
|
||||
|
||||
public function toBigInteger() : BigInteger
|
||||
{
|
||||
$zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
|
||||
|
||||
return self::newBigInteger($zeroScaleDecimal->value);
|
||||
}
|
||||
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
$numerator = self::newBigInteger($this->value);
|
||||
$denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
|
||||
|
||||
return self::newBigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
if ($scale === $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
|
||||
}
|
||||
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
public function toFloat() : float
|
||||
{
|
||||
return (float) (string) $this;
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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];
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
1079
libraries/vendor/brick/math/src/BigInteger.php
vendored
Normal file
1079
libraries/vendor/brick/math/src/BigInteger.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
512
libraries/vendor/brick/math/src/BigNumber.php
vendored
Normal file
512
libraries/vendor/brick/math/src/BigNumber.php
vendored
Normal file
@ -0,0 +1,512 @@
|
||||
<?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
|
||||
*
|
||||
* @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(BigNumber|int|float|string $value) : BigNumber
|
||||
{
|
||||
if ($value instanceof BigNumber) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (\is_int($value)) {
|
||||
return new BigInteger((string) $value);
|
||||
}
|
||||
|
||||
$value = \is_float($value) ? self::floatToString($value) : $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 fn(string $value): ?string => (($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
|
||||
*
|
||||
* @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 BigInteger's protected constructor from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigInteger(string $value) : BigInteger
|
||||
{
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method to access BigDecimal's protected constructor from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
|
||||
{
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method to access BigRational's protected constructor from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
|
||||
{
|
||||
return new BigRational($numerator, $denominator, $checkDenominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @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(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
$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.
|
||||
*
|
||||
* @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(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
$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.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function sum(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
/** @var static|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...)
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public function isEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly lower than the given one.
|
||||
*/
|
||||
public function isLessThan(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is lower than or equal to the given one.
|
||||
*/
|
||||
public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly greater than the given one.
|
||||
*/
|
||||
public function isGreaterThan(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is greater than or equal to the given one.
|
||||
*/
|
||||
public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number equals zero.
|
||||
*/
|
||||
public function isZero() : bool
|
||||
{
|
||||
return $this->getSign() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly negative.
|
||||
*/
|
||||
public function isNegative() : bool
|
||||
{
|
||||
return $this->getSign() < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is negative or zero.
|
||||
*/
|
||||
public function isNegativeOrZero() : bool
|
||||
{
|
||||
return $this->getSign() <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly positive.
|
||||
*/
|
||||
public function isPositive() : bool
|
||||
{
|
||||
return $this->getSign() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is positive or zero.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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(BigNumber|int|float|string $that) : int;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigInteger.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
|
||||
*/
|
||||
abstract public function toBigInteger() : BigInteger;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigDecimal.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
|
||||
*/
|
||||
abstract public function toBigDecimal() : BigDecimal;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigRational.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
abstract public function __toString() : string;
|
||||
|
||||
public function jsonSerialize() : string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
}
|
||||
445
libraries/vendor/brick/math/src/BigRational.php
vendored
Normal file
445
libraries/vendor/brick/math/src/BigRational.php
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
<?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.
|
||||
*/
|
||||
private BigInteger $numerator;
|
||||
|
||||
/**
|
||||
* The denominator. Always strictly positive.
|
||||
*/
|
||||
private BigInteger $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.
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigRational.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigRational
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @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(
|
||||
BigNumber|int|float|string $numerator,
|
||||
BigNumber|int|float|string $denominator,
|
||||
) : BigRational {
|
||||
$numerator = BigInteger::of($numerator);
|
||||
$denominator = BigInteger::of($denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing zero.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
public function getNumerator() : BigInteger
|
||||
{
|
||||
return $this->numerator;
|
||||
}
|
||||
|
||||
public function getDenominator() : BigInteger
|
||||
{
|
||||
return $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of the numerator by the denominator.
|
||||
*/
|
||||
public function quotient() : BigInteger
|
||||
{
|
||||
return $this->numerator->quotient($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of the numerator by the denominator.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function plus(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function minus(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number.
|
||||
*/
|
||||
public function multipliedBy(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, or is zero.
|
||||
*/
|
||||
public function dividedBy(BigNumber|int|float|string $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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public function abs() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->abs(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this BigRational.
|
||||
*/
|
||||
public function negated() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->negated(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simplified value of this 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);
|
||||
}
|
||||
|
||||
public function compareTo(BigNumber|int|float|string $that) : int
|
||||
{
|
||||
return $this->minus($that)->getSign();
|
||||
}
|
||||
|
||||
public function getSign() : int
|
||||
{
|
||||
return $this->numerator->getSign();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
|
||||
}
|
||||
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||
}
|
||||
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
public function toFloat() : float
|
||||
{
|
||||
$simplified = $this->simplified();
|
||||
return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
35
libraries/vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
35
libraries/vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a division by zero occurs.
|
||||
*/
|
||||
class DivisionByZeroException extends MathException
|
||||
{
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function divisionByZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('Division by zero.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function modulusMustNotBeZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('The modulus must not be zero.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function denominatorMustNotBeZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('The denominator of a rational number cannot be zero.');
|
||||
}
|
||||
}
|
||||
23
libraries/vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
23
libraries/vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Exception thrown when an integer overflow occurs.
|
||||
*/
|
||||
class IntegerOverflowException extends MathException
|
||||
{
|
||||
/**
|
||||
* @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));
|
||||
}
|
||||
}
|
||||
12
libraries/vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
12
libraries/vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Base class for all math exceptions.
|
||||
*/
|
||||
class MathException extends \Exception
|
||||
{
|
||||
}
|
||||
12
libraries/vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal file
12
libraries/vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal 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
|
||||
{
|
||||
}
|
||||
33
libraries/vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
33
libraries/vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?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.
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
}
|
||||
19
libraries/vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
19
libraries/vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?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
|
||||
{
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function roundingNecessary() : RoundingNecessaryException
|
||||
{
|
||||
return new self('Rounding is necessary to represent the result of the operation at this scale.');
|
||||
}
|
||||
}
|
||||
676
libraries/vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
676
libraries/vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
@ -0,0 +1,676 @@
|
||||
<?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.
|
||||
*/
|
||||
private static ?Calculator $instance = null;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
final public function abs(string $n) : string
|
||||
{
|
||||
return ($n[0] === '-') ? \substr($n, 1) : $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates a number.
|
||||
*/
|
||||
final public function neg(string $n) : string
|
||||
{
|
||||
if ($n === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($n[0] === '-') {
|
||||
return \substr($n, 1);
|
||||
}
|
||||
|
||||
return '-' . $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two numbers.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
abstract public function add(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Subtracts two numbers.
|
||||
*/
|
||||
abstract public function sub(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Multiplies two numbers.
|
||||
*/
|
||||
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 array{string, 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 $b The modulus; must not be zero.
|
||||
*/
|
||||
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 $m The modulus; must not be negative or zero.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
[$g, $x] = $this->gcdExtended($modVal, $m);
|
||||
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{string, string, string} GCD, X, Y
|
||||
*/
|
||||
private function gcdExtended(string $a, string $b) : array
|
||||
{
|
||||
if ($a === '0') {
|
||||
return [$b, '0', '1'];
|
||||
}
|
||||
|
||||
[$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a);
|
||||
|
||||
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
|
||||
$y = $x1;
|
||||
|
||||
return [$gcd, $x, $y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of the given number, rounded down.
|
||||
*
|
||||
* The result is the largest x such that x² ≤ n.
|
||||
* The input MUST NOT be negative.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the rounding mode is invalid.
|
||||
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
||||
*
|
||||
* @psalm-suppress ImpureFunctionCall
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('xor', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a bitwise operation on a decimal number.
|
||||
*
|
||||
* @param 'and'|'or'|'xor' $operator The operator to use.
|
||||
* @param string $a The left operand.
|
||||
* @param string $b The right operand.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
75
libraries/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
75
libraries/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
<?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
|
||||
{
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \bcadd($a, $b, 0);
|
||||
}
|
||||
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \bcsub($a, $b, 0);
|
||||
}
|
||||
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \bcmul($a, $b, 0);
|
||||
}
|
||||
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \bcdiv($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \bcmod($a, $b, 0);
|
||||
}
|
||||
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
$q = \bcdiv($a, $b, 0);
|
||||
$r = \bcmod($a, $b, 0);
|
||||
|
||||
assert($r !== null);
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \bcpow($a, (string) $e, 0);
|
||||
}
|
||||
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \bcpowmod($base, $exp, $mod, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \bcsqrt($n, 0);
|
||||
}
|
||||
}
|
||||
108
libraries/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
108
libraries/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
<?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
|
||||
{
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_add($a, $b));
|
||||
}
|
||||
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sub($a, $b));
|
||||
}
|
||||
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_mul($a, $b));
|
||||
}
|
||||
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_q($a, $b));
|
||||
}
|
||||
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_r($a, $b));
|
||||
}
|
||||
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
[$q, $r] = \gmp_div_qr($a, $b);
|
||||
|
||||
return [
|
||||
\gmp_strval($q),
|
||||
\gmp_strval($r)
|
||||
];
|
||||
}
|
||||
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_pow($a, $e));
|
||||
}
|
||||
|
||||
public function modInverse(string $x, string $m) : ?string
|
||||
{
|
||||
$result = \gmp_invert($x, $m);
|
||||
|
||||
if ($result === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \gmp_strval($result);
|
||||
}
|
||||
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_powm($base, $exp, $mod));
|
||||
}
|
||||
|
||||
public function gcd(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_gcd($a, $b));
|
||||
}
|
||||
|
||||
public function fromBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_init($number, $base));
|
||||
}
|
||||
|
||||
public function toBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval($number, $base);
|
||||
}
|
||||
|
||||
public function and(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_and($a, $b));
|
||||
}
|
||||
|
||||
public function or(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_or($a, $b));
|
||||
}
|
||||
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_xor($a, $b));
|
||||
}
|
||||
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sqrt($n));
|
||||
}
|
||||
}
|
||||
581
libraries/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
581
libraries/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
@ -0,0 +1,581 @@
|
||||
<?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.
|
||||
*
|
||||
* In 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)
|
||||
*/
|
||||
private int $maxDigits;
|
||||
|
||||
/**
|
||||
* @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.');
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return $this->add($a, $this->neg($b));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return $this->divQR($a, $b)[0];
|
||||
}
|
||||
|
||||
public function divR(string $a, string $b): string
|
||||
{
|
||||
return $this->divQR($a, $b)[1];
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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/
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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];
|
||||
}
|
||||
}
|
||||
107
libraries/vendor/brick/math/src/RoundingMode.php
vendored
Normal file
107
libraries/vendor/brick/math/src/RoundingMode.php
vendored
Normal 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;
|
||||
}
|
||||
579
libraries/vendor/composer/ClassLoader.php
vendored
Normal file
579
libraries/vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,579 @@
|
||||
<?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 \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @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 list<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)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$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 list<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)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$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] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$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 list<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 list<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 = self::$includeFile;
|
||||
$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 keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
359
libraries/vendor/composer/InstalledVersions.php
vendored
Normal file
359
libraries/vendor/composer/InstalledVersions.php
vendored
Normal file
@ -0,0 +1,359 @@
|
||||
<?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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: 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 || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
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((string) $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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: 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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: 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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: 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')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
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') {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array()) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
libraries/vendor/composer/LICENSE
vendored
Normal file
21
libraries/vendor/composer/LICENSE
vendored
Normal 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.
|
||||
|
||||
2866
libraries/vendor/composer/autoload_classmap.php
vendored
Normal file
2866
libraries/vendor/composer/autoload_classmap.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
54
libraries/vendor/composer/autoload_files.php
vendored
Normal file
54
libraries/vendor/composer/autoload_files.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'2fb9d6f23c8e8faefc193a4cde0cab4f' => $vendorDir . '/joomla/string/src/phputf8/utf8.php',
|
||||
'e6851e0ae7328fe5412fcec73928f3d9' => $vendorDir . '/joomla/string/src/phputf8/ord.php',
|
||||
'd9ad1b7c85c100a18c404a13824b846e' => $vendorDir . '/joomla/string/src/phputf8/str_ireplace.php',
|
||||
'62bad9b6730d2f83493d2337bf61519d' => $vendorDir . '/joomla/string/src/phputf8/str_pad.php',
|
||||
'c4d521b8d54308532dce032713d4eec0' => $vendorDir . '/joomla/string/src/phputf8/str_split.php',
|
||||
'fa973e71cace925de2afdc692b861b1d' => $vendorDir . '/joomla/string/src/phputf8/strcasecmp.php',
|
||||
'0c98c2f1295d9f4d093cc77d5834bb04' => $vendorDir . '/joomla/string/src/phputf8/strcspn.php',
|
||||
'a52639d843b4094945115c178a91ca86' => $vendorDir . '/joomla/string/src/phputf8/stristr.php',
|
||||
'73ee7d0297e683c4c2e7798ef040fb2f' => $vendorDir . '/joomla/string/src/phputf8/strrev.php',
|
||||
'd55633c05ddb996e0005f35debaa7b5b' => $vendorDir . '/joomla/string/src/phputf8/strspn.php',
|
||||
'944e69d23b93558fc0714353cf0c8beb' => $vendorDir . '/joomla/string/src/phputf8/trim.php',
|
||||
'31264bab20f14a8fc7a9d4265d91ee98' => $vendorDir . '/joomla/string/src/phputf8/ucfirst.php',
|
||||
'05d739a990f75f0c44ebe1f032b33148' => $vendorDir . '/joomla/string/src/phputf8/ucwords.php',
|
||||
'4292e2fa66516089e6006723267587b4' => $vendorDir . '/joomla/string/src/phputf8/utils/ascii.php',
|
||||
'87465e33b7551b401bf051928f220e9a' => $vendorDir . '/joomla/string/src/phputf8/utils/validation.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'07d7f1a47144818725fd8d91a907ac57' => $vendorDir . '/laminas/laminas-diactoros/src/functions/create_uploaded_file.php',
|
||||
'da94ac5d3ca7d2dbab84ce561ce72bfd' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.php',
|
||||
'3d97c8dcdfba8cb85d3b34f116bb248b' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.php',
|
||||
'e6f3bc6883e449ab367280b34158c05b' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_protocol_version_from_sapi.php',
|
||||
'd59fbae42019aedf227094ac49a46f50' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php',
|
||||
'de95e0ac670b27c84ef8c5ac41fc1b34' => $vendorDir . '/laminas/laminas-diactoros/src/functions/normalize_server.php',
|
||||
'b6c2870932b0250c10334a86dcb33c7f' => $vendorDir . '/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.php',
|
||||
'd02cf21124526632320d6f20b1bbf905' => $vendorDir . '/laminas/laminas-diactoros/src/functions/parse_cookie_header.php',
|
||||
'd919fc9d5ad52cfb7f322f7fe36458ab' => $vendorDir . '/laminas/laminas-diactoros/src/functions/create_uploaded_file.legacy.php',
|
||||
'e397f74f8af3b1e56166a6e99f216ee7' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.legacy.php',
|
||||
'd154b49fab8e4da34fb553a2d644918c' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.legacy.php',
|
||||
'9d3db23ca418094bcf0b641a0c9559ed' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_protocol_version_from_sapi.legacy.php',
|
||||
'b0b88a3b89caae681462c58ff19a7059' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.legacy.php',
|
||||
'cc8e14526dc240491e17a838cb78508c' => $vendorDir . '/laminas/laminas-diactoros/src/functions/normalize_server.legacy.php',
|
||||
'786bf90caabc9e09b6ad4cc5ca8f0e30' => $vendorDir . '/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.legacy.php',
|
||||
'751a5a3f463e4be759be31748b61737c' => $vendorDir . '/laminas/laminas-diactoros/src/functions/parse_cookie_header.legacy.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
|
||||
'09f6b20656683369174dd6fa83b7e5fb' => $vendorDir . '/symfony/polyfill-uuid/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
|
||||
'b45b351e6b6f7487d819961fef2fda77' => $vendorDir . '/jakeasmith/http_build_url/src/http_build_url.php',
|
||||
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
||||
'b46ad4fe52f4d1899a2951c7e6ea56b0' => $vendorDir . '/voku/portable-utf8/bootstrap.php',
|
||||
'3109cb1a231dcd04bee1f9f620d46975' => $vendorDir . '/paragonie/sodium_compat/autoload.php',
|
||||
'56823cacd97af379eceaf82ad00b928f' => $vendorDir . '/phpseclib/bcmath_compat/lib/bcmath.php',
|
||||
);
|
||||
9
libraries/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
libraries/vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
);
|
||||
89
libraries/vendor/composer/autoload_psr4.php
vendored
Normal file
89
libraries/vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku', $vendorDir . '/voku/portable-utf8/src/voku'),
|
||||
'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
|
||||
'enshrined\\svgSanitize\\' => array($vendorDir . '/enshrined/svg-sanitize/src'),
|
||||
'bcmath_compat\\' => array($vendorDir . '/phpseclib/bcmath_compat/src'),
|
||||
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
|
||||
'Webauthn\\MetadataService\\' => array($vendorDir . '/web-auth/metadata-service/src'),
|
||||
'Webauthn\\' => array($vendorDir . '/web-auth/webauthn-lib/src'),
|
||||
'Wamania\\Snowball\\' => array($vendorDir . '/wamania/php-stemmer/src'),
|
||||
'Tobscure\\JsonApi\\' => array($vendorDir . '/tobscure/json-api/src'),
|
||||
'TYPO3\\PharStreamWrapper\\' => array($vendorDir . '/typo3/phar-stream-wrapper/src'),
|
||||
'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'),
|
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
|
||||
'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'),
|
||||
'Symfony\\Polyfill\\Iconv\\' => array($vendorDir . '/symfony/polyfill-iconv'),
|
||||
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
||||
'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
|
||||
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
|
||||
'Symfony\\Component\\WebLink\\' => array($vendorDir . '/symfony/web-link'),
|
||||
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
|
||||
'Symfony\\Component\\Uid\\' => array($vendorDir . '/symfony/uid'),
|
||||
'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
|
||||
'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'),
|
||||
'Symfony\\Component\\Ldap\\' => array($vendorDir . '/symfony/ldap'),
|
||||
'Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'),
|
||||
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
|
||||
'SpomkyLabs\\Pki\\' => array($vendorDir . '/spomky-labs/pki-framework/src'),
|
||||
'ReCaptcha\\' => array($vendorDir . '/google/recaptcha/src/ReCaptcha'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
|
||||
'Psr\\Link\\' => array($vendorDir . '/psr/link/src'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
||||
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
|
||||
'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
|
||||
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
|
||||
'Negotiation\\' => array($vendorDir . '/willdurand/negotiation/src/Negotiation'),
|
||||
'Lcobucci\\JWT\\' => array($vendorDir . '/lcobucci/jwt/src'),
|
||||
'Lcobucci\\Clock\\' => array($vendorDir . '/lcobucci/clock/src'),
|
||||
'Laminas\\Diactoros\\' => array($vendorDir . '/laminas/laminas-diactoros/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-experimental', $vendorDir . '/web-token/jwt-signature-algorithm-hmac', $vendorDir . '/web-token/jwt-signature-algorithm-none', $vendorDir . '/web-token/jwt-signature-algorithm-rsa'),
|
||||
'Jose\\Component\\Signature\\' => array($vendorDir . '/web-token/jwt-signature'),
|
||||
'Jose\\Component\\Core\\' => array($vendorDir . '/web-token/jwt-core'),
|
||||
'Joomla\\Utilities\\' => array($vendorDir . '/joomla/utilities/src'),
|
||||
'Joomla\\Uri\\' => array($vendorDir . '/joomla/uri/src'),
|
||||
'Joomla\\String\\' => array($vendorDir . '/joomla/string/src'),
|
||||
'Joomla\\Session\\' => array($vendorDir . '/joomla/session/src'),
|
||||
'Joomla\\Router\\' => array($vendorDir . '/joomla/router/src'),
|
||||
'Joomla\\Registry\\' => array($vendorDir . '/joomla/registry/src'),
|
||||
'Joomla\\OAuth2\\' => array($vendorDir . '/joomla/oauth2/src'),
|
||||
'Joomla\\OAuth1\\' => array($vendorDir . '/joomla/oauth1/src'),
|
||||
'Joomla\\Language\\' => array($vendorDir . '/joomla/language/src'),
|
||||
'Joomla\\Input\\' => array($vendorDir . '/joomla/input/src'),
|
||||
'Joomla\\Http\\' => array($vendorDir . '/joomla/http/src'),
|
||||
'Joomla\\Filter\\' => array($vendorDir . '/joomla/filter/src'),
|
||||
'Joomla\\Filesystem\\' => array($vendorDir . '/joomla/filesystem/src'),
|
||||
'Joomla\\Event\\' => array($vendorDir . '/joomla/event/src'),
|
||||
'Joomla\\Database\\' => array($vendorDir . '/joomla/database/src'),
|
||||
'Joomla\\Data\\' => array($vendorDir . '/joomla/data/src'),
|
||||
'Joomla\\DI\\' => array($vendorDir . '/joomla/di/src'),
|
||||
'Joomla\\Crypt\\' => array($vendorDir . '/joomla/crypt/src'),
|
||||
'Joomla\\Console\\' => array($vendorDir . '/joomla/console/src'),
|
||||
'Joomla\\CMS\\' => array($baseDir . '/libraries/src'),
|
||||
'Joomla\\Authentication\\' => array($vendorDir . '/joomla/authentication/src'),
|
||||
'Joomla\\Archive\\' => array($vendorDir . '/joomla/archive/src'),
|
||||
'Joomla\\Application\\' => array($vendorDir . '/joomla/application/src'),
|
||||
'Jfcherng\\Utility\\' => array($vendorDir . '/jfcherng/php-color-output/src', $vendorDir . '/jfcherng/php-mb-string/src'),
|
||||
'Jfcherng\\Diff\\' => array($vendorDir . '/jfcherng/php-diff/src', $vendorDir . '/jfcherng/php-sequence-matcher/src'),
|
||||
'Fig\\Link\\' => array($vendorDir . '/fig/link-util/src'),
|
||||
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
|
||||
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'),
|
||||
'Defuse\\Crypto\\' => array($vendorDir . '/defuse/php-encryption/src'),
|
||||
'DebugBar\\' => array($vendorDir . '/maximebf/debugbar/src/DebugBar'),
|
||||
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
|
||||
'Cose\\' => array($vendorDir . '/web-auth/cose-lib/src'),
|
||||
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
|
||||
'CBOR\\' => array($vendorDir . '/spomky-labs/cbor-php/src'),
|
||||
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
|
||||
'Algo26\\IdnaConvert\\' => array($vendorDir . '/algo26-matthias/idna-convert/src'),
|
||||
);
|
||||
50
libraries/vendor/composer/autoload_real.php
vendored
Normal file
50
libraries/vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit32fd40b9411b8100a91002ab36b71748
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit32fd40b9411b8100a91002ab36b71748', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit32fd40b9411b8100a91002ab36b71748', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit32fd40b9411b8100a91002ab36b71748::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit32fd40b9411b8100a91002ab36b71748::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
3392
libraries/vendor/composer/autoload_static.php
vendored
Normal file
3392
libraries/vendor/composer/autoload_static.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
19
libraries/vendor/composer/ca-bundle/LICENSE
vendored
Normal file
19
libraries/vendor/composer/ca-bundle/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2016 Composer
|
||||
|
||||
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.
|
||||
3451
libraries/vendor/composer/ca-bundle/res/cacert.pem
vendored
Normal file
3451
libraries/vendor/composer/ca-bundle/res/cacert.pem
vendored
Normal file
File diff suppressed because it is too large
Load Diff
431
libraries/vendor/composer/ca-bundle/src/CaBundle.php
vendored
Normal file
431
libraries/vendor/composer/ca-bundle/src/CaBundle.php
vendored
Normal file
@ -0,0 +1,431 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of composer/ca-bundle.
|
||||
*
|
||||
* (c) Composer <https://github.com/composer>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\CaBundle;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Process\PhpProcess;
|
||||
|
||||
/**
|
||||
* @author Chris Smith <chris@cs278.org>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class CaBundle
|
||||
{
|
||||
/** @var string|null */
|
||||
private static $caPath;
|
||||
/** @var array<string, bool> */
|
||||
private static $caFileValidity = array();
|
||||
/** @var bool|null */
|
||||
private static $useOpensslParse;
|
||||
|
||||
/**
|
||||
* Returns the system CA bundle path, or a path to the bundled one
|
||||
*
|
||||
* This method was adapted from Sslurp.
|
||||
* https://github.com/EvanDotPro/Sslurp
|
||||
*
|
||||
* (c) Evan Coury <me@evancoury.com>
|
||||
*
|
||||
* For the full copyright and license information, please see below:
|
||||
*
|
||||
* Copyright (c) 2013, Evan Coury
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
||||
* @return string path to a CA bundle file or directory
|
||||
*/
|
||||
public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
|
||||
{
|
||||
if (self::$caPath !== null) {
|
||||
return self::$caPath;
|
||||
}
|
||||
$caBundlePaths = array();
|
||||
|
||||
// If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
|
||||
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
||||
$caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
|
||||
|
||||
// If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
|
||||
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
||||
$caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
|
||||
|
||||
$caBundlePaths[] = ini_get('openssl.cafile');
|
||||
$caBundlePaths[] = ini_get('openssl.capath');
|
||||
|
||||
$otherLocations = array(
|
||||
'/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
|
||||
'/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
|
||||
'/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
|
||||
'/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
|
||||
'/usr/ssl/certs/ca-bundle.crt', // Cygwin
|
||||
'/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
|
||||
'/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
|
||||
'/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
|
||||
'/etc/ssl/cert.pem', // OpenBSD
|
||||
'/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
|
||||
'/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
|
||||
'/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package
|
||||
);
|
||||
|
||||
foreach($otherLocations as $location) {
|
||||
$otherLocations[] = dirname($location);
|
||||
}
|
||||
|
||||
$caBundlePaths = array_merge($caBundlePaths, $otherLocations);
|
||||
|
||||
foreach ($caBundlePaths as $caBundle) {
|
||||
if ($caBundle && self::caFileUsable($caBundle, $logger)) {
|
||||
return self::$caPath = $caBundle;
|
||||
}
|
||||
|
||||
if ($caBundle && self::caDirUsable($caBundle, $logger)) {
|
||||
return self::$caPath = $caBundle;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the bundled CA file
|
||||
*
|
||||
* In case you don't want to trust the user or the system, you can use this directly
|
||||
*
|
||||
* @return string path to a CA bundle file
|
||||
*/
|
||||
public static function getBundledCaBundlePath()
|
||||
{
|
||||
$caBundleFile = __DIR__.'/../res/cacert.pem';
|
||||
|
||||
// cURL does not understand 'phar://' paths
|
||||
// see https://github.com/composer/ca-bundle/issues/10
|
||||
if (0 === strpos($caBundleFile, 'phar://')) {
|
||||
$tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-');
|
||||
if (false === $tempCaBundleFile) {
|
||||
throw new \RuntimeException('Could not create a temporary file to store the bundled CA file');
|
||||
}
|
||||
|
||||
file_put_contents(
|
||||
$tempCaBundleFile,
|
||||
file_get_contents($caBundleFile)
|
||||
);
|
||||
|
||||
register_shutdown_function(function() use ($tempCaBundleFile) {
|
||||
@unlink($tempCaBundleFile);
|
||||
});
|
||||
|
||||
$caBundleFile = $tempCaBundleFile;
|
||||
}
|
||||
|
||||
return $caBundleFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a CA file using opensl_x509_parse only if it is safe to use
|
||||
*
|
||||
* @param string $filename
|
||||
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateCaFile($filename, LoggerInterface $logger = null)
|
||||
{
|
||||
static $warned = false;
|
||||
|
||||
if (isset(self::$caFileValidity[$filename])) {
|
||||
return self::$caFileValidity[$filename];
|
||||
}
|
||||
|
||||
$contents = file_get_contents($filename);
|
||||
|
||||
// assume the CA is valid if php is vulnerable to
|
||||
// https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
|
||||
if (!static::isOpensslParseSafe()) {
|
||||
if (!$warned && $logger) {
|
||||
$logger->warning(sprintf(
|
||||
'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
|
||||
PHP_VERSION
|
||||
));
|
||||
$warned = true;
|
||||
}
|
||||
|
||||
$isValid = !empty($contents);
|
||||
} elseif (is_string($contents) && strlen($contents) > 0) {
|
||||
$contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
|
||||
if (null === $contents) {
|
||||
// regex extraction failed
|
||||
$isValid = false;
|
||||
} else {
|
||||
$isValid = (bool) openssl_x509_parse($contents);
|
||||
}
|
||||
} else {
|
||||
$isValid = false;
|
||||
}
|
||||
|
||||
if ($logger) {
|
||||
$logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
|
||||
}
|
||||
|
||||
return self::$caFileValidity[$filename] = $isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if it is safe to use the PHP function openssl_x509_parse().
|
||||
*
|
||||
* This checks if OpenSSL extensions is vulnerable to remote code execution
|
||||
* via the exploit documented as CVE-2013-6420.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isOpensslParseSafe()
|
||||
{
|
||||
if (null !== self::$useOpensslParse) {
|
||||
return self::$useOpensslParse;
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID >= 50600) {
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
// Vulnerable:
|
||||
// PHP 5.3.0 - PHP 5.3.27
|
||||
// PHP 5.4.0 - PHP 5.4.22
|
||||
// PHP 5.5.0 - PHP 5.5.6
|
||||
if (
|
||||
(PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
|
||||
|| (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
|
||||
|| PHP_VERSION_ID >= 50507
|
||||
) {
|
||||
// This version of PHP has the fix for CVE-2013-6420 applied.
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
// Windows is probably insecure in this case.
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
$compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
|
||||
$regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
|
||||
|
||||
if (preg_match($regex, PHP_VERSION, $m)) {
|
||||
return ((int) $m[1]) >= $fixedVersion;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Hard coded list of PHP distributions with the fix backported.
|
||||
if (
|
||||
$compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
|
||||
|| $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
|
||||
|| $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
|
||||
) {
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
// Symfony Process component is missing so we assume it is unsafe at this point
|
||||
if (!class_exists('Symfony\Component\Process\PhpProcess')) {
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
// This is where things get crazy, because distros backport security
|
||||
// fixes the chances are on NIX systems the fix has been applied but
|
||||
// it's not possible to verify that from the PHP version.
|
||||
//
|
||||
// To verify exec a new PHP process and run the issue testcase with
|
||||
// known safe input that replicates the bug.
|
||||
|
||||
// Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
|
||||
// changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
|
||||
$cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
|
||||
$script = <<<'EOT'
|
||||
|
||||
error_reporting(-1);
|
||||
$info = openssl_x509_parse(base64_decode('%s'));
|
||||
var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
|
||||
|
||||
EOT;
|
||||
$script = '<'."?php\n".sprintf($script, $cert);
|
||||
|
||||
try {
|
||||
$process = new PhpProcess($script);
|
||||
$process->mustRun();
|
||||
} catch (\Exception $e) {
|
||||
// In the case of any exceptions just accept it is not possible to
|
||||
// determine the safety of openssl_x509_parse and bail out.
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
$output = preg_split('{\r?\n}', trim($process->getOutput()));
|
||||
$errorOutput = trim($process->getErrorOutput());
|
||||
|
||||
if (
|
||||
is_array($output)
|
||||
&& count($output) === 3
|
||||
&& $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
|
||||
&& $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
|
||||
&& $output[2] === 'int(-1)'
|
||||
&& preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
|
||||
) {
|
||||
// This PHP has the fix backported probably by a distro security team.
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the static caches
|
||||
* @return void
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
self::$caFileValidity = array();
|
||||
self::$caPath = null;
|
||||
self::$useOpensslParse = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return string|false
|
||||
*/
|
||||
private static function getEnvVariable($name)
|
||||
{
|
||||
if (isset($_SERVER[$name])) {
|
||||
return (string) $_SERVER[$name];
|
||||
}
|
||||
|
||||
if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|false $certFile
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function caFileUsable($certFile, LoggerInterface $logger = null)
|
||||
{
|
||||
return $certFile
|
||||
&& static::isFile($certFile, $logger)
|
||||
&& static::isReadable($certFile, $logger)
|
||||
&& static::validateCaFile($certFile, $logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|false $certDir
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function caDirUsable($certDir, LoggerInterface $logger = null)
|
||||
{
|
||||
return $certDir
|
||||
&& static::isDir($certDir, $logger)
|
||||
&& static::isReadable($certDir, $logger)
|
||||
&& static::glob($certDir . '/*', $logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $certFile
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function isFile($certFile, LoggerInterface $logger = null)
|
||||
{
|
||||
$isFile = @is_file($certFile);
|
||||
if (!$isFile && $logger) {
|
||||
$logger->debug(sprintf('Checked CA file %s does not exist or it is not a file.', $certFile));
|
||||
}
|
||||
|
||||
return $isFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $certDir
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function isDir($certDir, LoggerInterface $logger = null)
|
||||
{
|
||||
$isDir = @is_dir($certDir);
|
||||
if (!$isDir && $logger) {
|
||||
$logger->debug(sprintf('Checked directory %s does not exist or it is not a directory.', $certDir));
|
||||
}
|
||||
|
||||
return $isDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $certFileOrDir
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function isReadable($certFileOrDir, LoggerInterface $logger = null)
|
||||
{
|
||||
$isReadable = @is_readable($certFileOrDir);
|
||||
if (!$isReadable && $logger) {
|
||||
$logger->debug(sprintf('Checked file or directory %s is not readable.', $certFileOrDir));
|
||||
}
|
||||
|
||||
return $isReadable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $pattern
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function glob($pattern, LoggerInterface $logger = null)
|
||||
{
|
||||
$certs = glob($pattern);
|
||||
if ($certs === false) {
|
||||
if ($logger) {
|
||||
$logger->debug(sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count($certs) === 0) {
|
||||
if ($logger) {
|
||||
$logger->debug(sprintf("No CA files found for pattern: %s", $pattern));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
6665
libraries/vendor/composer/installed.json
vendored
Normal file
6665
libraries/vendor/composer/installed.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
935
libraries/vendor/composer/installed.php
vendored
Normal file
935
libraries/vendor/composer/installed.php
vendored
Normal file
@ -0,0 +1,935 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'joomla/joomla-cms',
|
||||
'pretty_version' => 'dev-5.0/build/githublayout',
|
||||
'version' => 'dev-5.0/build/githublayout',
|
||||
'reference' => '0e23b165e580270f5b53f9dc0c5fd17011f4bf87',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../../',
|
||||
'aliases' => array(),
|
||||
'dev' => false,
|
||||
),
|
||||
'versions' => array(
|
||||
'algo26-matthias/idna-convert' => array(
|
||||
'pretty_version' => 'v3.1.0',
|
||||
'version' => '3.1.0.0',
|
||||
'reference' => '340a4dc65f6b0d9884853a3d32895d82f0c1502a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../algo26-matthias/idna-convert',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'brick/math' => array(
|
||||
'pretty_version' => '0.11.0',
|
||||
'version' => '0.11.0.0',
|
||||
'reference' => '0ad82ce168c82ba30d1c01ec86116ab52f589478',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../brick/math',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'composer/ca-bundle' => array(
|
||||
'pretty_version' => '1.3.7',
|
||||
'version' => '1.3.7.0',
|
||||
'reference' => '76e46335014860eec1aa5a724799a00a2e47cc85',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/./ca-bundle',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'defuse/php-encryption' => array(
|
||||
'pretty_version' => 'v2.4.0',
|
||||
'version' => '2.4.0.0',
|
||||
'reference' => 'f53396c2d34225064647a05ca76c1da9d99e5828',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../defuse/php-encryption',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'doctrine/inflector' => array(
|
||||
'pretty_version' => '1.4.4',
|
||||
'version' => '1.4.4.0',
|
||||
'reference' => '4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../doctrine/inflector',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dragonmantank/cron-expression' => array(
|
||||
'pretty_version' => 'v3.3.3',
|
||||
'version' => '3.3.3.0',
|
||||
'reference' => 'adfb1f505deb6384dc8b39804c5065dd3c8c8c0a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dragonmantank/cron-expression',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'enshrined/svg-sanitize' => array(
|
||||
'pretty_version' => '0.15.4',
|
||||
'version' => '0.15.4.0',
|
||||
'reference' => 'e50b83a2f1f296ca61394fe88fbfe3e896a84cf4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../enshrined/svg-sanitize',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'fig/link-util' => array(
|
||||
'pretty_version' => '1.2.0',
|
||||
'version' => '1.2.0.0',
|
||||
'reference' => '10e52348a2e9ad4581f2bf3e16458f0861a88c6a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../fig/link-util',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'google/recaptcha' => array(
|
||||
'pretty_version' => '1.3.0',
|
||||
'version' => '1.3.0.0',
|
||||
'reference' => 'd59a801e98a4e9174814a6d71bbc268dff1202df',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../google/recaptcha',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jakeasmith/http_build_url' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => '93c273e77cb1edead0cf8bcf8cd2003428e74e37',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jakeasmith/http_build_url',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-color-output' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '6c7bf16686cc6a291647fcb87491640a2d5edd20',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-color-output',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-diff' => array(
|
||||
'pretty_version' => '6.15.3',
|
||||
'version' => '6.15.3.0',
|
||||
'reference' => '39be09756f8eda115299add3f34dc64b4bc32b66',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-diff',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-mb-string' => array(
|
||||
'pretty_version' => '2.0.1',
|
||||
'version' => '2.0.1.0',
|
||||
'reference' => '8407bfefde47849c9e7c9594e6de2ac85a0f845d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-mb-string',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jfcherng/php-sequence-matcher' => array(
|
||||
'pretty_version' => '4.0.3',
|
||||
'version' => '4.0.3.0',
|
||||
'reference' => 'd2038ac29627340a7458609072a8ba355e80ec5b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jfcherng/php-sequence-matcher',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/application' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '96d279d19d7551746f97f7702cf92ad050eac01f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../joomla/application',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/archive' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '843ec2ae8f539b2aaed0846113dbb2cb52bae1e1',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/archive',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/authentication' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'c8caa1b772c9ff7442115f68f6d1a6db1f633e8a',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/authentication',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/console' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'e105c751a53b63d5ff932c122e31ddf5480aa66d',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/console',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/crypt' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '2f1c4e43eeb520557887a9e6ed6b2747485ee78d',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/crypt',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/data' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '1fd9dbac7a19c761874784ea4c8215c3c3ff775b',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/data',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/database' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'd440247b1e07710f22d5e07650393fbd9364b01e',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/database',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/di' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'ec3866463257b3d4bfbd5ed0900a5e5505b909cb',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/di',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/event' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'b259ffdb574067ec74953693cb61a9690291920e',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/event',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/filesystem' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '1398fe1b3acbd97c5237cd9b405530a1f7d49daa',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/filesystem',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/filter' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'b589b6a6c40ace650e2f55ed404994bd99ac3d4a',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/filter',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/http' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'ec389a64def1d71d145fdcc06895cbd960f5d805',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/http',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/input' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '3ab947f2baf8b8f08b8ecc11f7ada91092a75354',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/input',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/joomla-cms' => array(
|
||||
'pretty_version' => 'dev-5.0/build/githublayout',
|
||||
'version' => 'dev-5.0/build/githublayout',
|
||||
'reference' => '0e23b165e580270f5b53f9dc0c5fd17011f4bf87',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/language' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'd2008ccb727f3a582579496d1fba9a4af840c03c',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/language',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/oauth1' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'bf390ed9288a6b858853880efc41620dd8d08a2d',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/oauth1',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/oauth2' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '70f61fe09a9e7d261684194f8d55a2035e84dbcc',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/oauth2',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/registry' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'dc57ab21856e79d45e5a44cf6d41253a2414d110',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/registry',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/router' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '951c2fa144b459cc35d9fe69193e970a3ef86893',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/router',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/session' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'be15f3eee054802c3d8dfeabb2e42ecbe5a4c574',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/session',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/string' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '9d76d779450745679c2fa591add238b5dd3f203f',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/string',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/uri' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '42862cc99be6dc75587e6ce6eb29e0c33de6ffa2',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/uri',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'joomla/utilities' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '0b85f5c876b7b81046648402db4b84168be96d9a',
|
||||
'type' => 'joomla-package',
|
||||
'install_path' => __DIR__ . '/../joomla/utilities',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'laminas/laminas-diactoros' => array(
|
||||
'pretty_version' => '2.25.2',
|
||||
'version' => '2.25.2.0',
|
||||
'reference' => '9f3f4bf5b99c9538b6f1dbcc20f6fec357914f9e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../laminas/laminas-diactoros',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'lcobucci/clock' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '039ef98c6b57b101d10bd11d8fdfda12cbd996dc',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../lcobucci/clock',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'lcobucci/jwt' => array(
|
||||
'pretty_version' => '4.3.0',
|
||||
'version' => '4.3.0.0',
|
||||
'reference' => '4d7de2fe0d51a96418c0d04004986e410e87f6b4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../lcobucci/jwt',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'maximebf/debugbar' => array(
|
||||
'pretty_version' => 'v1.19.0',
|
||||
'version' => '1.19.0.0',
|
||||
'reference' => '30f65f18f7ac086255a77a079f8e0dcdd35e828e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../maximebf/debugbar',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'mtdowling/cron-expression' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '^1.0',
|
||||
),
|
||||
),
|
||||
'paragonie/constant_time_encoding' => array(
|
||||
'pretty_version' => 'v2.6.3',
|
||||
'version' => '2.6.3.0',
|
||||
'reference' => '58c3f47f650c94ec05a151692652a868995d2938',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/constant_time_encoding',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'paragonie/random_compat' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '9.99.99',
|
||||
),
|
||||
),
|
||||
'paragonie/sodium_compat' => array(
|
||||
'pretty_version' => 'v1.20.0',
|
||||
'version' => '1.20.0.0',
|
||||
'reference' => 'e592a3e06d1fa0d43988c7c7d9948ca836f644b6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/sodium_compat',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpmailer/phpmailer' => array(
|
||||
'pretty_version' => 'v6.8.1',
|
||||
'version' => '6.8.1.0',
|
||||
'reference' => 'e88da8d679acc3824ff231fdc553565b802ac016',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpseclib/bcmath_compat' => array(
|
||||
'pretty_version' => '2.0.1',
|
||||
'version' => '2.0.1.0',
|
||||
'reference' => '2ffea8bfe1702b4535a7b3c2649c4301968e9a3c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpseclib/bcmath_compat',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpseclib/phpseclib' => array(
|
||||
'pretty_version' => '3.0.23',
|
||||
'version' => '3.0.23.0',
|
||||
'reference' => '866cc78fbd82462ffd880e3f65692afe928bed50',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/clock' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/clock',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/clock-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '1.1.2',
|
||||
'version' => '1.1.2.0',
|
||||
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/container',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/container-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '~1.0',
|
||||
),
|
||||
),
|
||||
'psr/event-dispatcher' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/event-dispatcher',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-client' => array(
|
||||
'pretty_version' => '1.0.3',
|
||||
'version' => '1.0.3.0',
|
||||
'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-client',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-factory' => array(
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-factory-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-message' => array(
|
||||
'pretty_version' => '1.1',
|
||||
'version' => '1.1.0.0',
|
||||
'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-message',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-message-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/link' => array(
|
||||
'pretty_version' => '1.1.1',
|
||||
'version' => '1.1.1.0',
|
||||
'reference' => '846c25f58a1f02b93a00f2404e3626b6bf9b7807',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/link',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/link-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
1 => '1.0|2.0',
|
||||
),
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/log-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0|2.0|3.0',
|
||||
),
|
||||
),
|
||||
'spomky-labs/cbor-php' => array(
|
||||
'pretty_version' => '3.0.2',
|
||||
'version' => '3.0.2.0',
|
||||
'reference' => '81d5dff7a1101d680729b5789f4359d01b15e6c5',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../spomky-labs/cbor-php',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'spomky-labs/pki-framework' => array(
|
||||
'pretty_version' => '1.1.0',
|
||||
'version' => '1.1.0.0',
|
||||
'reference' => 'd3ba688bf40e7c6e0dabf065ee18fc210734e760',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../spomky-labs/pki-framework',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/console' => array(
|
||||
'pretty_version' => 'v6.3.4',
|
||||
'version' => '6.3.4.0',
|
||||
'reference' => 'eca495f2ee845130855ddf1cf18460c38966c8b6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/console',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/deprecation-contracts' => array(
|
||||
'pretty_version' => 'v3.3.0',
|
||||
'version' => '3.3.0.0',
|
||||
'reference' => '7c3aff79d10325257a001fcf92d991f24fc967cf',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/error-handler' => array(
|
||||
'pretty_version' => 'v6.3.2',
|
||||
'version' => '6.3.2.0',
|
||||
'reference' => '85fd65ed295c4078367c784e8a5a6cee30348b7a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/error-handler',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/ldap' => array(
|
||||
'pretty_version' => 'v6.3.0',
|
||||
'version' => '6.3.0.0',
|
||||
'reference' => '5f1308de5d3a1ca9e5c6ef6bb4b736e5dd6f3508',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/ldap',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/options-resolver' => array(
|
||||
'pretty_version' => 'v6.3.0',
|
||||
'version' => '6.3.0.0',
|
||||
'reference' => 'a10f19f5198d589d5c33333cffe98dc9820332dd',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/options-resolver',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-ctype' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => 'ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-iconv' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '6de50471469b8c9afc38164452ab2b6170ee71c1',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-iconv',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-intl-grapheme' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '875e90aeea2777b6f135677f618529449334a612',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-intl-normalizer' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '42292d99c55abe617799667f454222c54c60e229',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php70' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php71' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php72' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php73' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php74' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php81' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-uuid' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '9c44518a5aff8da565c8a55dbe85d2769e6f630e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-uuid',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/service-contracts' => array(
|
||||
'pretty_version' => 'v2.5.2',
|
||||
'version' => '2.5.2.0',
|
||||
'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/service-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/string' => array(
|
||||
'pretty_version' => 'v6.3.2',
|
||||
'version' => '6.3.2.0',
|
||||
'reference' => '53d1a83225002635bca3482fcbf963001313fb68',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/string',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/uid' => array(
|
||||
'pretty_version' => 'v6.3.0',
|
||||
'version' => '6.3.0.0',
|
||||
'reference' => '01b0f20b1351d997711c56f1638f7a8c3061e384',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/uid',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/var-dumper' => array(
|
||||
'pretty_version' => 'v6.3.4',
|
||||
'version' => '6.3.4.0',
|
||||
'reference' => '2027be14f8ae8eae999ceadebcda5b4909b81d45',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/web-link' => array(
|
||||
'pretty_version' => 'v6.3.0',
|
||||
'version' => '6.3.0.0',
|
||||
'reference' => '0989ca617d0703cdca501a245f10e194ff22315b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/web-link',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/yaml' => array(
|
||||
'pretty_version' => 'v6.3.3',
|
||||
'version' => '6.3.3.0',
|
||||
'reference' => 'e23292e8c07c85b971b44c1c4b87af52133e2add',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/yaml',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'tobscure/json-api' => array(
|
||||
'pretty_version' => 'dev-joomla-backports',
|
||||
'version' => 'dev-joomla-backports',
|
||||
'reference' => 'a56f59df9e0fc95b1421a5210e1cdf208c9f91d2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../tobscure/json-api',
|
||||
'aliases' => array(
|
||||
0 => '9999999-dev',
|
||||
),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'typo3/phar-stream-wrapper' => array(
|
||||
'pretty_version' => 'v3.1.7',
|
||||
'version' => '3.1.7.0',
|
||||
'reference' => '5cc2f04a4e2f5c7e9cc02a3bdf80fae0f3e11a8c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../typo3/phar-stream-wrapper',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'voku/portable-ascii' => array(
|
||||
'pretty_version' => '2.0.1',
|
||||
'version' => '2.0.1.0',
|
||||
'reference' => 'b56450eed252f6801410d810c8e1727224ae0743',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../voku/portable-ascii',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'voku/portable-utf8' => array(
|
||||
'pretty_version' => '6.0.13',
|
||||
'version' => '6.0.13.0',
|
||||
'reference' => 'b8ce36bf26593e5c2e81b1850ef0ffb299d2043f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../voku/portable-utf8',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'wamania/php-stemmer' => array(
|
||||
'pretty_version' => 'v3.0.1',
|
||||
'version' => '3.0.1.0',
|
||||
'reference' => '8ea32b6fa27d6888587fe860b64a8763525c5a66',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../wamania/php-stemmer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-auth/cose-lib' => array(
|
||||
'pretty_version' => '4.2.3',
|
||||
'version' => '4.2.3.0',
|
||||
'reference' => '0ecad86d2d034ea22e2205d81c8cdec13d93a991',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-auth/cose-lib',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-auth/metadata-service' => array(
|
||||
'pretty_version' => '4.5.2',
|
||||
'version' => '4.5.2.0',
|
||||
'reference' => '82b3a517894987db1f8959a9320b9891515af9e7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-auth/metadata-service',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-auth/webauthn-lib' => array(
|
||||
'pretty_version' => '4.5.2',
|
||||
'version' => '4.5.2.0',
|
||||
'reference' => '30c5e891c6418abef6d87a4351132b01b1828a98',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-auth/webauthn-lib',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-core' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => '2bc6e99a60910d0f495682acd8b23d3eef9865a3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-core',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-signature' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => '156e0b0ef534e53eecf23a32a92ee6d8cb4fdac4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-signature',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-signature-algorithm-ecdsa' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => '34b119d6b5eca53914ad3b96660e5bd7fb5538b9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-ecdsa',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-signature-algorithm-eddsa' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => '2ee185c4378671e5b0fd0a47021f3df74246f9b3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-eddsa',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-signature-algorithm-experimental' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => '5839b18e271440121ca950c5bc126c1c2163dcc2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-experimental',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-signature-algorithm-hmac' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => '16b091bb8d41bd0f0897f04195ce1e99b24ca15b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-hmac',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-signature-algorithm-none' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => 'db776b4b44e0ae1aaf78e58d28a899c4c0fd4c7b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-none',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/jwt-signature-algorithm-rsa' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => '1015c68cc4e7d7a355e40bba6beeee3fe21b5572',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../web-token/jwt-signature-algorithm-rsa',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'web-token/signature-pack' => array(
|
||||
'pretty_version' => '3.2.8',
|
||||
'version' => '3.2.8.0',
|
||||
'reference' => 'c41146a621cbb3a1b3053be4a7d05912d6d23de7',
|
||||
'type' => 'symfony-pack',
|
||||
'install_path' => __DIR__ . '/../web-token/signature-pack',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'webmozart/assert' => array(
|
||||
'pretty_version' => '1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../webmozart/assert',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'willdurand/negotiation' => array(
|
||||
'pretty_version' => '3.1.0',
|
||||
'version' => '3.1.0.0',
|
||||
'reference' => '68e9ea0553ef6e2ee8db5c1d98829f111e623ec2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../willdurand/negotiation',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
26
libraries/vendor/composer/platform_check.php
vendored
Normal file
26
libraries/vendor/composer/platform_check.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 80100)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
21
libraries/vendor/defuse/php-encryption/LICENSE
vendored
Normal file
21
libraries/vendor/defuse/php-encryption/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Taylor Hornby <https://defuse.ca>
|
||||
Copyright (c) 2016 Paragon Initiative Enterprises <https://paragonie.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.
|
||||
14
libraries/vendor/defuse/php-encryption/bin/generate-defuse-key
vendored
Executable file
14
libraries/vendor/defuse/php-encryption/bin/generate-defuse-key
vendored
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use Defuse\Crypto\Key;
|
||||
|
||||
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$key = Key::createNewRandomKey();
|
||||
echo $key->saveToAsciiSafeString(), "\n";
|
||||
39
libraries/vendor/defuse/php-encryption/dist/Makefile
vendored
Normal file
39
libraries/vendor/defuse/php-encryption/dist/Makefile
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# This builds defuse-crypto.phar. To run this Makefile, `box` and `composer`
|
||||
# must be installed and in your $PATH. Run it from inside the dist/ directory.
|
||||
|
||||
box := $(shell which box)
|
||||
composer := $(shell which composer)
|
||||
gitcommit := $(shell git rev-parse HEAD)
|
||||
|
||||
.PHONY: all
|
||||
all: build-phar
|
||||
|
||||
.PHONY: sign-phar
|
||||
sign-phar:
|
||||
gpg -u DD2E507F7BDB1669 --armor --output defuse-crypto.phar.sig --detach-sig defuse-crypto.phar
|
||||
|
||||
# ensure we run in clean tree. export git tree and run there.
|
||||
.PHONY: build-phar
|
||||
build-phar:
|
||||
@echo "Creating .phar from revision $(shell git rev-parse HEAD)."
|
||||
rm -rf worktree
|
||||
install -d worktree
|
||||
(cd $(CURDIR)/..; git archive HEAD) | tar -x -C worktree
|
||||
$(MAKE) -f $(CURDIR)/Makefile -C worktree defuse-crypto.phar
|
||||
mv worktree/*.phar .
|
||||
rm -rf worktree
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -vf defuse-crypto.phar defuse-crypto.phar.sig
|
||||
|
||||
# Inside workdir/:
|
||||
|
||||
defuse-crypto.phar: dist/box.json composer.lock
|
||||
cp dist/box.json .
|
||||
php $(box) compile -c box.json -v
|
||||
|
||||
composer.lock:
|
||||
$(composer) config autoloader-suffix $(gitcommit)
|
||||
$(composer) install --no-dev
|
||||
|
||||
22
libraries/vendor/defuse/php-encryption/dist/box.json
vendored
Normal file
22
libraries/vendor/defuse/php-encryption/dist/box.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"chmod": "0755",
|
||||
"finder": [
|
||||
{
|
||||
"in": "src",
|
||||
"name": "*.php"
|
||||
},
|
||||
{
|
||||
"in": "vendor/composer",
|
||||
"name": "*.php"
|
||||
},
|
||||
{
|
||||
"in": "vendor/paragonie",
|
||||
"name": "*.php",
|
||||
"exclude": "other"
|
||||
}
|
||||
],
|
||||
"main": "vendor/autoload.php",
|
||||
"output": "defuse-crypto.phar",
|
||||
"shebang": false,
|
||||
"stub": true
|
||||
}
|
||||
4
libraries/vendor/defuse/php-encryption/dist/phar-testing-autoload.php
vendored
Normal file
4
libraries/vendor/defuse/php-encryption/dist/phar-testing-autoload.php
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
require 'defuse-crypto.phar';
|
||||
require realpath(dirname(__FILE__) . '/../vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php');
|
||||
?>
|
||||
53
libraries/vendor/defuse/php-encryption/dist/signingkey-new.asc
vendored
Normal file
53
libraries/vendor/defuse/php-encryption/dist/signingkey-new.asc
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBF5V4TABEAC4G2BkHDaqbip3gj1oOqKh3V6LQa9QAd/f/hyhmR5hXpciPxf3
|
||||
NNHAxzoGAuB51f1YPJTNO59mGKHDuCFfr0pI94HDGoW4WgxqnUyqHBj2+/JhQPqO
|
||||
lgDT0QDcfxmUd0wfZl/Ur+8SsaBYvfFWNmPaXHp9m4MMRtw9uZNIW6LlZ24JqmGy
|
||||
/YUELUSH7P+uJ4HQEdixaqQ0VgIomRDI+5IwdJMtq4TSNazQm3nNmH9Em37cdi6J
|
||||
NDfFRy2QxJDmuqlg8mkpS5TvrrNy/UJwIeXO9PuGaBODr8GAKWvhkpfGlxN+hWMY
|
||||
01bOFnuEnOcuXw8BjPAKHqwOuGvinNmQ7lX1Rj3ssd31sTUimop0oNjOTZztpJBR
|
||||
m6wO2/YGMjt+eL02NgBBDIsV837PeWuJmymTJDGQuBjZ3JWUfyT3AnkA8OU5vKjs
|
||||
pM8AjIiuU7C8zQhUSHDnukTKWpBmMdOXeWNb5Ye6n60wJWzWFGlm+cYalPs+q3H8
|
||||
bxHxHEdFT0rUpxB05bc9zsZ3gGkc2NTNW/00a6gvTyX1UsBAeNgvVSHBHQGfow6o
|
||||
ZKG+LnVxd+cl97ay6kP29eLypXffbXQ3hMXe9tUNBjAeiok9tssU70Epr9wTh/Fm
|
||||
/iEbGc8VhS4TSk3c+3eS16rvlQ51FmAlmG6kAnN/ah+BiM4syPrWcJHIDQARAQAB
|
||||
tG1kZWZ1c2UvcGhwLWVuY3J5cHRpb24gbWFpbnRhaW5lcnMgKGRlZnVzZS9waHAt
|
||||
ZW5jcnlwdGlvbiByZWxlYXNlIHNpZ25pbmcga2V5KSA8cGhwLWVuY3J5cHRpb25A
|
||||
ZGVmdXNlLmludmFsaWQ+iQJUBBMBCAA+FiEEbdbmdwKBWEb8hSWj3S5Qf3vbFmkF
|
||||
Al5V4TACGwMFCQlmAYAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ3S5Qf3vb
|
||||
FmnQ4Q//bHAwDI7CcTlDDktdRCP0YCRtb5zMa6vSqnZLi5aTqzmL1yQCAp1/JTwf
|
||||
nlHn5xt60eKwfjIKj7Kj0n8WDFYnlOu30H5fNtFHis0xeS7GkH60tIE/pQUZILlB
|
||||
Wcnx/ZPnlxccjtfSbnpelSPdvIoHVRNhh1ZYG/49kuuv8TMbMIi2FBAzGEatPoLN
|
||||
f4wntoOKGvl8R2rPc2geapXTz++X+HJkddHCISR61obDRl9P0t9x+0M7gGSVMGfC
|
||||
GC4wh3JB6/ha8l+DI+l88/64IKRG+M33bBwLGQ0RIhotHIy442gLJTm6TeoH8iUz
|
||||
xCBwPYW+Ta1wZi17PIjHdTkNGBeEj/Hr5tTVV3oxrQVgHCymzasnz9IwcCCMwpKK
|
||||
ZOMFl0+PT3TSBKLnUByvOB64YOjxU7t+sRf53Biz3yKzto5VdHGW64OG2vGFy/Xz
|
||||
vI5RqU34wjtEHxWfz8y2GBnhD2TzEFCIIWPAX3TDG64NBSEBjhUraOmoVoaYJlP6
|
||||
rqxIQo4yhC+f5rnr2ZA48Hnrg0jEdVvN07FegoOnQQPpYBBkOrkTDWChn8oiXMfg
|
||||
9bjv19zDOBVXl9EU+P8AhwTHz/pBKmhb97N9nYp/pbmejA+I0Kw1vZo7gaMxL938
|
||||
oQkdtWT70ZzcpcZfeKVXoZa/ddAmuxzNknZA8ZnjQ9Qhv7aNX2O5Ag0EXlXhMAEQ
|
||||
AM8od4/85i7ZPmM6C1M4n4XcXeKsuZKHLvLLcRHFGkjVdXRSaxpbk2yDJiLnB9hX
|
||||
GSJG2gUCT+yrimjQ71bJ4q9K2+mkVHVjdtCrCtoOYEIpMLzsRtqyAWotcVmdv8Zv
|
||||
4IIjxfdxpTkj9gZmUfDIe6tbN2iBCAo1HArXq1qSdof3ui8SqdWeinkd7lZMesFm
|
||||
dGQaAcHbmEakO5mRzljme8IBs3UY9j/zxEG1JbsHx9ua7CVwJ7lxi2SgSW6nF9k5
|
||||
CX5zbrDqlqSJNtDs+KbjCbI2eK+qe4qZWHPiw4bNBn6EWf97/4Os8w7Vrrpyd2eO
|
||||
1JENwjlG6WG9mbJdIWWwakZ0CeH5LnJo6dV47KZbbbB6ncavaL+VpfbTCgdOGsCc
|
||||
GcYUVl90/v5pPm2owx4Dg9hSfcp8fesQuq4b79NAcjF7meu5wgNdvFlfuXony+UC
|
||||
W2wNi0mi9lzLD0n0j0GDzWyd3r7yXmPTL4LhrQu/pIcWIljKI3GUAQZqIYbGAO3G
|
||||
7hEFT8rDWg2vKRtMag4iy5FvZFqR+7TwWJAcWnHJBZ95F9NzeYIFhp9a3hxbKXqD
|
||||
xEnyGgzAszUycq29BApT4/4rDZQuXuOBd4lJp8tSzctLjvo7D3la+MWD6AlDkYT4
|
||||
bGKN9NfRCzYr2Zq3jOByAV3d5hGgyzdJlZSqXAGtbHHdABEBAAGJAjwEGAEIACYW
|
||||
IQRt1uZ3AoFYRvyFJaPdLlB/e9sWaQUCXlXhMAIbDAUJCWYBgAAKCRDdLlB/e9sW
|
||||
aSGfD/wPeq6lGu8ocHIkO74VPioJRKRXDVLsY02xKP64p0RHUGFTOqqB3A3UV0ue
|
||||
tkizoUdfF5xkgJ18gbxXo8lotBq+Ita5hoYAfqJnTnucAPGovREJ+X1HfdK4pJqW
|
||||
KNJElBz+fC4chqksiUAuH7IMImmy0/lA+LqZagzkQJU10MvmiFZ6kn+X5Mb4izRl
|
||||
vAHo16eI4psApdT8Bs7mwAjgCHxS9Re46uOElB4Bx3iFPd/PEwHWnfr8x9TJZYKW
|
||||
fsShG31+vfBRCfGtfKGxiAkp3EEM11lzbbfMcC3lai5iJQ/FmHgoIDeIG2Ebuk4w
|
||||
/PYakSrpvkEYoMP31pVHDhzopVeURS2lpvQJ4CvTP5CVQtKrbuygow6GF8N/drCE
|
||||
hdEx22pzW02ADS9fgzrlDztIOlOvC9a+epISIaEjfrc9dWhrw6chZEoWIil2MVQR
|
||||
Sj0jZ8w/H7P88oHTOcFVel73ZEPg9eRUkqMnIn3DWUuqLI2SX/AtVnhdYHWTiOkq
|
||||
knsGofWxUSu3RZR2ZElK9hjNKdVbGDzHGAYeJihieTKIOXpCf6Ix5B32tmFpfmBV
|
||||
Q9YP3JLsRTxIMbXsJImand/r6fSjdmTpk2PovYPtE1HTJKaVHeagQdsrWw5LaJv0
|
||||
ZWuwJm0y0WJXcAEjwOHhBs0nvq2CXuZi2ZTPtY+DbsSFWhaN7g==
|
||||
=Ysgx
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
BIN
libraries/vendor/defuse/php-encryption/dist/signingkey-new.asc.sig
vendored
Normal file
BIN
libraries/vendor/defuse/php-encryption/dist/signingkey-new.asc.sig
vendored
Normal file
Binary file not shown.
52
libraries/vendor/defuse/php-encryption/dist/signingkey.asc
vendored
Normal file
52
libraries/vendor/defuse/php-encryption/dist/signingkey.asc
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v2
|
||||
|
||||
mQINBFarvO4BEACdQBaLt6SUBx1cB5liUu1qo+YwVLh9bxTregQtmEREMdTVqXYt
|
||||
e5b79uL4pQp2GlKHcEyRURS+6rIIruM0oh9ZYGTJYPAkCDzJxaU2awZeFbfBvpCm
|
||||
iF66/O4ZJI4mlT8dFKmxBJxDhfeOR2UmmhDiEsJK9FxBKUzvo/dWrX2pBzf8Y122
|
||||
iIaVraSo+tymaf7vriaIf/NnSKhDw8dtQYGM4NMrxxsPTfbCF8XiboDgTkoD2A+6
|
||||
NpOJYxA4Veedsf2TP9YLhljH4m5yYlfjjqBzbBCPWuE6Hhy5Xze9mncgDr7LKenm
|
||||
Ctf2NxW6y4O3RCI+9eLlBfFWB+KuGV87/b5daetX7NNLbjID8z2rqEa+d6wu5xA5
|
||||
Ta2uiVkAOEovr3XnkayZ9zth+Za7w7Ai0ln0N/LVMkM+Gu4z/pJv6HjmTGDM2wJb
|
||||
fs+UOM0TFdg+N81Do67XT2M4o0MeHyUqsIiWpYa2Qf1PNmqTQNJnRk8uZZ9I96Nh
|
||||
eCgNuCbhsQiYBMicox+xmuWAlGAfA06y0kCtmqGhiBGArdJlWvUqPqGiZ4Hln9z0
|
||||
FJmXDOh0Q/FIPxcDg8mKRRbx+lOP389PLsPpj4b2B/4PEgfpCCOwuKpLotATZxC1
|
||||
9JwFk0Y/cvUUkq4a+nAJBNtBbtRJkEesuuUnRq6XexmnE3uUucDcV0XCSwARAQAB
|
||||
tCBUYXlsb3IgSG9ybmJ5IDx0YXlsb3JAZGVmdXNlLmNhPokCPQQTAQgAJwUCVqu8
|
||||
7gIbAwUJB4TOAAULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRA4XuBVoSkVOJbx
|
||||
EACG0F9blPMAsK05EWyNnnS4mw25zPfbaqqEvYbquAeM0nBpRDm7sRn2MNR0AL4g
|
||||
7XrtxE/4qYkdEl6f2wFCQeRhZgxE3w22llredzLme11Hic8hn4i7ysdIw0r9dMMR
|
||||
kjgR5UcWpv8iU847czyK09PkKW2EaLRbX2qbA7rNU5qCFKeD4Sy4bBTteISeVsHo
|
||||
Vr9o1/bRrMhgZ++ts8hYf0LmujIf5cxp+qcdKwCXSnS/gmmXaKRMCPv/Wdlq9bt6
|
||||
LX9jZB9lXBdGxcBJeFOsTG+QRDiVjg3d6i3o3TAKV87ALBI4v2ADEYtN8lviHo3/
|
||||
SovVKv6zrUsZHxhoGiLTiksNrYsKMmiMxdJCoOazmtUPnZ4UOtT8NdqMPoKvdoRz
|
||||
f4rhZ+f5jSVD9OuX2PDmfyq21Rdiym7Vcgr+uTIFJ3ShRHjWb/ytCwoB2FeGY6+G
|
||||
AKY58bTQvUIqEJvSov/+TAqZ4BfOuSdTLcHglV1OdUu2SFZvU2gmyVp0l5elGv5t
|
||||
FyUlBJUkQT9MtvsdLOR7vQi8QapV+9LWpqwvaj9hyEJz848DQ2sdYTphUytFHv7H
|
||||
k58DAtVhTrVjHyeefjiYtMl6vSAgTjy5LWAUpo5TfhdGrAi0Tdd/GD7amHoWoDy8
|
||||
EKXKq2xPLo3JOdkWYQUi5NErzEskfsSzpCOgyDJmGetWK7kCDQRWq7zuARAAu7/i
|
||||
cm8cjgLhHEX/bgfwOT2hLOLSjjve0O8YFSuJO9XqIHXqmfVOrqWtfG0Mh4bwlfqc
|
||||
MAvBfF5NSSPfAE4ftBAQ1e5jEv8hJeqICpq3IHTFX4etBs49NfNkyveQl/amVTu1
|
||||
+/O5J4CuIcsEf3y0Xuu38n7EB3SfMQCWLcOR1NyZoX3bI+CGRpOVVoFse3ljSWL4
|
||||
LhLVl0WiEMXULsussEoN+c6x9KCyAi/jFOrxrTrFC//sZesKj6KucoqKGfwMWrrv
|
||||
IeRT9Ga8Wn5MJnQu0aWg+zVVYqTedXZLNLODgQIInFnXO0seBXy15yDok1y5bkx2
|
||||
sinKg4+mueYaGUpoUti0hM3J3yaC34i6Cwa8MQoLNw1JIS/oNtKjpMxyV10w8aoc
|
||||
PHRK3n7UYp10mJHx7aM+lldSKvVS1NTQmI4vloNLwMp324H5ANDFAlRUz7mysVnu
|
||||
DEEvigPSPxs5ZYENu/i7pCQC5qHfhrlBrQwTjhegr0pQPcumy2fO5SGC9l/5B7ev
|
||||
bqQSZmDeWWoTvh2w2wl5/RWAsgZKx6rDtkCqYx7sSBY17uorrxP24LP4zhq7NxRV
|
||||
nfdsLogbCFNVQ66u7qvq5zFccdFtg9h1HQWdS7wbnKSBGZoo5gl6js7GGtxfGbb0
|
||||
oQ9kp6eciF4U92r6POhVgbRe4CfPo50nqgZBddkAEQEAAYkCJQQYAQgADwUCVqu8
|
||||
7gIbDAUJB4TOAAAKCRA4XuBVoSkVOFJ8D/9J8IJ4XWUU3FYIaHJ3XeSoxDmTi7d5
|
||||
WmNdf1lmwz82MQjG4uw17oCbvQzmj4/a/CM1Ly4v0WwBhUf9aiNErD0ByHASFnuc
|
||||
tlQBLVJdk0vRyD0fZakGg64qCA76hiySjMhlGHkQFyP2mDORc2GNu/OqFGm79pXT
|
||||
ZUplXxd431E603/agM5xJrweutMMpP1nBFTSEMJvbMNzDVN8I1A1CH4zVmAVxOUk
|
||||
sQ5L5rXW+KeXWyiMF24+l2CMnkQ2CxfHpkcpfPJs1Cbt+TIBSSofIqK8QJXrb/2f
|
||||
Zpl/ftqW7Xe86rJFrB/Y/77LDWx10rqWEvfCqrBxrMj7ONAQfbKQF/IjAwDN17Wf
|
||||
1K74rqKnRu+KHCyNM89s1iDbQC9kzZfzYt4AEOvAH/ZQDMZffzPSbnfkBerExFpa
|
||||
93XMuiR66jiBsf9IXIQeydpJD4Ogl2sSUSxFEJxJ/bBSxPxC5w7/BVMA7Am1y8Zo
|
||||
3hrpqnX2PBzxG7L0FZ6fYkfR3p8JS7vI6nByBf2IDv8W32wn43olPf+u6uobHLvt
|
||||
ttapOjwPAhPDalRuxs9U6WSg06QJkT/0F8TFUPWpsFmKTl+G4Ty7PHWsjeeNHJCL
|
||||
7/5RQboFY3k8Jy3/sIofABO6Un9LJivDuu9PxqA0IgvaS6Mja8JdCCk9Nyk4vHB7
|
||||
IEgAL/CYqrk38w==
|
||||
=lmD7
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
470
libraries/vendor/defuse/php-encryption/src/Core.php
vendored
Normal file
470
libraries/vendor/defuse/php-encryption/src/Core.php
vendored
Normal file
@ -0,0 +1,470 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class Core
|
||||
{
|
||||
const HEADER_VERSION_SIZE = 4;
|
||||
const MINIMUM_CIPHERTEXT_SIZE = 84;
|
||||
|
||||
const CURRENT_VERSION = "\xDE\xF5\x02\x00";
|
||||
|
||||
const CIPHER_METHOD = 'aes-256-ctr';
|
||||
const BLOCK_BYTE_SIZE = 16;
|
||||
const KEY_BYTE_SIZE = 32;
|
||||
const SALT_BYTE_SIZE = 32;
|
||||
const MAC_BYTE_SIZE = 32;
|
||||
const HASH_FUNCTION_NAME = 'sha256';
|
||||
const ENCRYPTION_INFO_STRING = 'DefusePHP|V2|KeyForEncryption';
|
||||
const AUTHENTICATION_INFO_STRING = 'DefusePHP|V2|KeyForAuthentication';
|
||||
const BUFFER_BYTE_SIZE = 1048576;
|
||||
|
||||
const LEGACY_CIPHER_METHOD = 'aes-128-cbc';
|
||||
const LEGACY_BLOCK_BYTE_SIZE = 16;
|
||||
const LEGACY_KEY_BYTE_SIZE = 16;
|
||||
const LEGACY_HASH_FUNCTION_NAME = 'sha256';
|
||||
const LEGACY_MAC_BYTE_SIZE = 32;
|
||||
const LEGACY_ENCRYPTION_INFO_STRING = 'DefusePHP|KeyForEncryption';
|
||||
const LEGACY_AUTHENTICATION_INFO_STRING = 'DefusePHP|KeyForAuthentication';
|
||||
|
||||
/*
|
||||
* V2.0 Format: VERSION (4 bytes) || SALT (32 bytes) || IV (16 bytes) ||
|
||||
* CIPHERTEXT (varies) || HMAC (32 bytes)
|
||||
*
|
||||
* V1.0 Format: HMAC (32 bytes) || IV (16 bytes) || CIPHERTEXT (varies).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds an integer to a block-sized counter.
|
||||
*
|
||||
* @param string $ctr
|
||||
* @param int $inc
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @psalm-suppress RedundantCondition - It's valid to use is_int to check for overflow.
|
||||
*/
|
||||
public static function incrementCounter($ctr, $inc)
|
||||
{
|
||||
Core::ensureTrue(
|
||||
Core::ourStrlen($ctr) === Core::BLOCK_BYTE_SIZE,
|
||||
'Trying to increment a nonce of the wrong size.'
|
||||
);
|
||||
|
||||
Core::ensureTrue(
|
||||
\is_int($inc),
|
||||
'Trying to increment nonce by a non-integer.'
|
||||
);
|
||||
|
||||
// The caller is probably re-using CTR-mode keystream if they increment by 0.
|
||||
Core::ensureTrue(
|
||||
$inc > 0,
|
||||
'Trying to increment a nonce by a nonpositive amount'
|
||||
);
|
||||
|
||||
Core::ensureTrue(
|
||||
$inc <= PHP_INT_MAX - 255,
|
||||
'Integer overflow may occur'
|
||||
);
|
||||
|
||||
/*
|
||||
* We start at the rightmost byte (big-endian)
|
||||
* So, too, does OpenSSL: http://stackoverflow.com/a/3146214/2224584
|
||||
*/
|
||||
for ($i = Core::BLOCK_BYTE_SIZE - 1; $i >= 0; --$i) {
|
||||
$sum = \ord($ctr[$i]) + $inc;
|
||||
|
||||
/* Detect integer overflow and fail. */
|
||||
Core::ensureTrue(\is_int($sum), 'Integer overflow in CTR mode nonce increment');
|
||||
|
||||
$ctr[$i] = \pack('C', $sum & 0xFF);
|
||||
$inc = $sum >> 8;
|
||||
}
|
||||
return $ctr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random byte string of the specified length.
|
||||
*
|
||||
* @param int $octets
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function secureRandom($octets)
|
||||
{
|
||||
if ($octets <= 0) {
|
||||
throw new Ex\CryptoException(
|
||||
'A zero or negative amount of random bytes was requested.'
|
||||
);
|
||||
}
|
||||
self::ensureFunctionExists('random_bytes');
|
||||
try {
|
||||
return \random_bytes(max(1, $octets));
|
||||
} catch (\Exception $ex) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Your system does not have a secure random number generator.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the HKDF key derivation function specified in
|
||||
* http://tools.ietf.org/html/rfc5869.
|
||||
*
|
||||
* @param string $hash Hash Function
|
||||
* @param string $ikm Initial Keying Material
|
||||
* @param int $length How many bytes?
|
||||
* @param string $info What sort of key are we deriving?
|
||||
* @param string $salt
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @psalm-suppress UndefinedFunction - We're checking if the function exists first.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function HKDF($hash, $ikm, $length, $info = '', $salt = null)
|
||||
{
|
||||
static $nativeHKDF = null;
|
||||
if ($nativeHKDF === null) {
|
||||
$nativeHKDF = \is_callable('\\hash_hkdf');
|
||||
}
|
||||
if ($nativeHKDF) {
|
||||
if (\is_null($salt)) {
|
||||
$salt = '';
|
||||
}
|
||||
return \hash_hkdf($hash, $ikm, $length, $info, $salt);
|
||||
}
|
||||
|
||||
$digest_length = Core::ourStrlen(\hash_hmac($hash, '', '', true));
|
||||
|
||||
// Sanity-check the desired output length.
|
||||
Core::ensureTrue(
|
||||
!empty($length) && \is_int($length) && $length >= 0 && $length <= 255 * $digest_length,
|
||||
'Bad output length requested of HDKF.'
|
||||
);
|
||||
|
||||
// "if [salt] not provided, is set to a string of HashLen zeroes."
|
||||
if (\is_null($salt)) {
|
||||
$salt = \str_repeat("\x00", $digest_length);
|
||||
}
|
||||
|
||||
// HKDF-Extract:
|
||||
// PRK = HMAC-Hash(salt, IKM)
|
||||
// The salt is the HMAC key.
|
||||
$prk = \hash_hmac($hash, $ikm, $salt, true);
|
||||
|
||||
// HKDF-Expand:
|
||||
|
||||
// This check is useless, but it serves as a reminder to the spec.
|
||||
Core::ensureTrue(Core::ourStrlen($prk) >= $digest_length);
|
||||
|
||||
// T(0) = ''
|
||||
$t = '';
|
||||
$last_block = '';
|
||||
for ($block_index = 1; Core::ourStrlen($t) < $length; ++$block_index) {
|
||||
// T(i) = HMAC-Hash(PRK, T(i-1) | info | 0x??)
|
||||
$last_block = \hash_hmac(
|
||||
$hash,
|
||||
$last_block . $info . \chr($block_index),
|
||||
$prk,
|
||||
true
|
||||
);
|
||||
// T = T(1) | T(2) | T(3) | ... | T(N)
|
||||
$t .= $last_block;
|
||||
}
|
||||
|
||||
// ORM = first L octets of T
|
||||
/** @var string $orm */
|
||||
$orm = Core::ourSubstr($t, 0, $length);
|
||||
Core::ensureTrue(\is_string($orm));
|
||||
return $orm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if two equal-length strings are the same without leaking
|
||||
* information through side channels.
|
||||
*
|
||||
* @param string $expected
|
||||
* @param string $given
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hashEquals($expected, $given)
|
||||
{
|
||||
static $native = null;
|
||||
if ($native === null) {
|
||||
$native = \function_exists('hash_equals');
|
||||
}
|
||||
if ($native) {
|
||||
return \hash_equals($expected, $given);
|
||||
}
|
||||
|
||||
// We can't just compare the strings with '==', since it would make
|
||||
// timing attacks possible. We could use the XOR-OR constant-time
|
||||
// comparison algorithm, but that may not be a reliable defense in an
|
||||
// interpreted language. So we use the approach of HMACing both strings
|
||||
// with a random key and comparing the HMACs.
|
||||
|
||||
// We're not attempting to make variable-length string comparison
|
||||
// secure, as that's very difficult. Make sure the strings are the same
|
||||
// length.
|
||||
Core::ensureTrue(Core::ourStrlen($expected) === Core::ourStrlen($given));
|
||||
|
||||
$blind = Core::secureRandom(32);
|
||||
$message_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $given, $blind);
|
||||
$correct_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $expected, $blind);
|
||||
return $correct_compare === $message_compare;
|
||||
}
|
||||
/**
|
||||
* Throws an exception if the constant doesn't exist.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
public static function ensureConstantExists($name)
|
||||
{
|
||||
Core::ensureTrue(
|
||||
\defined($name),
|
||||
'Constant '.$name.' does not exists'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the function doesn't exist.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
public static function ensureFunctionExists($name)
|
||||
{
|
||||
Core::ensureTrue(
|
||||
\function_exists($name),
|
||||
'function '.$name.' does not exists'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the condition is false.
|
||||
*
|
||||
* @param bool $condition
|
||||
* @param string $message
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
public static function ensureTrue($condition, $message = '')
|
||||
{
|
||||
if (!$condition) {
|
||||
throw new Ex\EnvironmentIsBrokenException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need these strlen() and substr() functions because when
|
||||
* 'mbstring.func_overload' is set in php.ini, the standard strlen() and
|
||||
* substr() are replaced by mb_strlen() and mb_substr().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Computes the length of a string in bytes.
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function ourStrlen($str)
|
||||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \extension_loaded('mbstring') && \function_exists('mb_strlen');
|
||||
}
|
||||
if ($exists) {
|
||||
$length = \mb_strlen($str, '8bit');
|
||||
Core::ensureTrue($length !== false);
|
||||
return $length;
|
||||
} else {
|
||||
return \strlen($str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Behaves roughly like the function substr() in PHP 7 does.
|
||||
*
|
||||
* @param string $str
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public static function ourSubstr($str, $start, $length = null)
|
||||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \extension_loaded('mbstring') && \function_exists('mb_substr');
|
||||
}
|
||||
|
||||
// This is required to make mb_substr behavior identical to substr.
|
||||
// Without this, mb_substr() would return false, contra to what the
|
||||
// PHP documentation says (it doesn't say it can return false.)
|
||||
$input_len = Core::ourStrlen($str);
|
||||
if ($start === $input_len && !$length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($start > $input_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// mb_substr($str, 0, NULL, '8bit') returns an empty string on PHP 5.3,
|
||||
// so we have to find the length ourselves. Also, substr() doesn't
|
||||
// accept null for the length.
|
||||
if (! isset($length)) {
|
||||
if ($start >= 0) {
|
||||
$length = $input_len - $start;
|
||||
} else {
|
||||
$length = -$start;
|
||||
}
|
||||
}
|
||||
|
||||
if ($length < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Negative lengths are not supported with ourSubstr."
|
||||
);
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
$substr = \mb_substr($str, $start, $length, '8bit');
|
||||
// At this point there are two cases where mb_substr can
|
||||
// legitimately return an empty string. Either $length is 0, or
|
||||
// $start is equal to the length of the string (both mb_substr and
|
||||
// substr return an empty string when this happens). It should never
|
||||
// ever return a string that's longer than $length.
|
||||
if (Core::ourStrlen($substr) > $length || (Core::ourStrlen($substr) === 0 && $length !== 0 && $start !== $input_len)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Your version of PHP has bug #66797. Its implementation of
|
||||
mb_substr() is incorrect. See the details here:
|
||||
https://bugs.php.net/bug.php?id=66797'
|
||||
);
|
||||
}
|
||||
return $substr;
|
||||
}
|
||||
|
||||
return \substr($str, $start, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the PBKDF2 password-based key derivation function.
|
||||
*
|
||||
* The PBKDF2 function is defined in RFC 2898. Test vectors can be found in
|
||||
* RFC 6070. This implementation of PBKDF2 was originally created by Taylor
|
||||
* Hornby, with improvements from http://www.variations-of-shadow.com/.
|
||||
*
|
||||
* @param string $algorithm The hash algorithm to use. Recommended: SHA256
|
||||
* @param string $password The password.
|
||||
* @param string $salt A salt that is unique to the password.
|
||||
* @param int $count Iteration count. Higher is better, but slower. Recommended: At least 1000.
|
||||
* @param int $key_length The length of the derived key in bytes.
|
||||
* @param bool $raw_output If true, the key is returned in raw binary format. Hex encoded otherwise.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string A $key_length-byte key derived from the password and salt.
|
||||
*/
|
||||
public static function pbkdf2(
|
||||
$algorithm,
|
||||
#[\SensitiveParameter]
|
||||
$password,
|
||||
$salt,
|
||||
$count,
|
||||
$key_length,
|
||||
$raw_output = false
|
||||
)
|
||||
{
|
||||
// Type checks:
|
||||
if (! \is_string($algorithm)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'pbkdf2(): algorithm must be a string'
|
||||
);
|
||||
}
|
||||
if (! \is_string($password)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'pbkdf2(): password must be a string'
|
||||
);
|
||||
}
|
||||
if (! \is_string($salt)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'pbkdf2(): salt must be a string'
|
||||
);
|
||||
}
|
||||
// Coerce strings to integers with no information loss or overflow
|
||||
$count += 0;
|
||||
$key_length += 0;
|
||||
|
||||
$algorithm = \strtolower($algorithm);
|
||||
Core::ensureTrue(
|
||||
\in_array($algorithm, \hash_algos(), true),
|
||||
'Invalid or unsupported hash algorithm.'
|
||||
);
|
||||
|
||||
// Whitelist, or we could end up with people using CRC32.
|
||||
$ok_algorithms = [
|
||||
'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
|
||||
'ripemd160', 'ripemd256', 'ripemd320', 'whirlpool',
|
||||
];
|
||||
Core::ensureTrue(
|
||||
\in_array($algorithm, $ok_algorithms, true),
|
||||
'Algorithm is not a secure cryptographic hash function.'
|
||||
);
|
||||
|
||||
Core::ensureTrue($count > 0 && $key_length > 0, 'Invalid PBKDF2 parameters.');
|
||||
|
||||
if (\function_exists('hash_pbkdf2')) {
|
||||
// The output length is in NIBBLES (4-bits) if $raw_output is false!
|
||||
if (! $raw_output) {
|
||||
$key_length = $key_length * 2;
|
||||
}
|
||||
return \hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
|
||||
}
|
||||
|
||||
$hash_length = Core::ourStrlen(\hash($algorithm, '', true));
|
||||
$block_count = \ceil($key_length / $hash_length);
|
||||
|
||||
$output = '';
|
||||
for ($i = 1; $i <= $block_count; $i++) {
|
||||
// $i encoded as 4 bytes, big endian.
|
||||
$last = $salt . \pack('N', $i);
|
||||
// first iteration
|
||||
$last = $xorsum = \hash_hmac($algorithm, $last, $password, true);
|
||||
// perform the other $count - 1 iterations
|
||||
for ($j = 1; $j < $count; $j++) {
|
||||
/**
|
||||
* @psalm-suppress InvalidOperand
|
||||
*/
|
||||
$xorsum ^= ($last = \hash_hmac($algorithm, $last, $password, true));
|
||||
}
|
||||
$output .= $xorsum;
|
||||
}
|
||||
|
||||
if ($raw_output) {
|
||||
return (string) Core::ourSubstr($output, 0, $key_length);
|
||||
} else {
|
||||
return Encoding::binToHex((string) Core::ourSubstr($output, 0, $key_length));
|
||||
}
|
||||
}
|
||||
}
|
||||
477
libraries/vendor/defuse/php-encryption/src/Crypto.php
vendored
Normal file
477
libraries/vendor/defuse/php-encryption/src/Crypto.php
vendored
Normal file
@ -0,0 +1,477 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
class Crypto
|
||||
{
|
||||
/**
|
||||
* Encrypts a string with a Key.
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param Key $key
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws \TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encrypt($plaintext, $key, $raw_binary = false)
|
||||
{
|
||||
if (!\is_string($plaintext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!($key instanceof Key)) {
|
||||
throw new \TypeError(
|
||||
'Key expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::encryptInternal(
|
||||
$plaintext,
|
||||
KeyOrPassword::createFromKey($key),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a string with a password, using a slow key derivation function
|
||||
* to make password cracking more expensive.
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param string $password
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws \TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encryptWithPassword(
|
||||
$plaintext,
|
||||
#[\SensitiveParameter]
|
||||
$password,
|
||||
$raw_binary = false
|
||||
)
|
||||
{
|
||||
if (!\is_string($plaintext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_string($password)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::encryptInternal(
|
||||
$plaintext,
|
||||
KeyOrPassword::createFromPassword($password),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a ciphertext to a string with a Key.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param Key $key
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws \TypeError
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function decrypt($ciphertext, $key, $raw_binary = false)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!($key instanceof Key)) {
|
||||
throw new \TypeError(
|
||||
'Key expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::decryptInternal(
|
||||
$ciphertext,
|
||||
KeyOrPassword::createFromKey($key),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a ciphertext to a string with a password, using a slow key
|
||||
* derivation function to make password cracking more expensive.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param string $password
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
* @throws \TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function decryptWithPassword(
|
||||
$ciphertext,
|
||||
#[\SensitiveParameter]
|
||||
$password,
|
||||
$raw_binary = false
|
||||
)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_string($password)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::decryptInternal(
|
||||
$ciphertext,
|
||||
KeyOrPassword::createFromPassword($password),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a legacy ciphertext produced by version 1 of this library.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param string $key
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
* @throws \TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function legacyDecrypt(
|
||||
$ciphertext,
|
||||
#[\SensitiveParameter]
|
||||
$key
|
||||
)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_string($key)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
|
||||
RuntimeTests::runtimeTest();
|
||||
|
||||
// Extract the HMAC from the front of the ciphertext.
|
||||
if (Core::ourStrlen($ciphertext) <= Core::LEGACY_MAC_BYTE_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext is too short.'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$hmac = Core::ourSubstr($ciphertext, 0, Core::LEGACY_MAC_BYTE_SIZE);
|
||||
Core::ensureTrue(\is_string($hmac));
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$messageCiphertext = Core::ourSubstr($ciphertext, Core::LEGACY_MAC_BYTE_SIZE);
|
||||
Core::ensureTrue(\is_string($messageCiphertext));
|
||||
|
||||
// Regenerate the same authentication sub-key.
|
||||
$akey = Core::HKDF(
|
||||
Core::LEGACY_HASH_FUNCTION_NAME,
|
||||
$key,
|
||||
Core::LEGACY_KEY_BYTE_SIZE,
|
||||
Core::LEGACY_AUTHENTICATION_INFO_STRING,
|
||||
null
|
||||
);
|
||||
|
||||
if (self::verifyHMAC($hmac, $messageCiphertext, $akey)) {
|
||||
// Regenerate the same encryption sub-key.
|
||||
$ekey = Core::HKDF(
|
||||
Core::LEGACY_HASH_FUNCTION_NAME,
|
||||
$key,
|
||||
Core::LEGACY_KEY_BYTE_SIZE,
|
||||
Core::LEGACY_ENCRYPTION_INFO_STRING,
|
||||
null
|
||||
);
|
||||
|
||||
// Extract the IV from the ciphertext.
|
||||
if (Core::ourStrlen($messageCiphertext) <= Core::LEGACY_BLOCK_BYTE_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext is too short.'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$iv = Core::ourSubstr($messageCiphertext, 0, Core::LEGACY_BLOCK_BYTE_SIZE);
|
||||
Core::ensureTrue(\is_string($iv));
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$actualCiphertext = Core::ourSubstr($messageCiphertext, Core::LEGACY_BLOCK_BYTE_SIZE);
|
||||
Core::ensureTrue(\is_string($actualCiphertext));
|
||||
|
||||
// Do the decryption.
|
||||
$plaintext = self::plainDecrypt($actualCiphertext, $ekey, $iv, Core::LEGACY_CIPHER_METHOD);
|
||||
return $plaintext;
|
||||
} else {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Integrity check failed.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a string with either a key or a password.
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param KeyOrPassword $secret
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function encryptInternal($plaintext, KeyOrPassword $secret, $raw_binary)
|
||||
{
|
||||
RuntimeTests::runtimeTest();
|
||||
|
||||
$salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
|
||||
$keys = $secret->deriveKeys($salt);
|
||||
$ekey = $keys->getEncryptionKey();
|
||||
$akey = $keys->getAuthenticationKey();
|
||||
$iv = Core::secureRandom(Core::BLOCK_BYTE_SIZE);
|
||||
|
||||
$ciphertext = Core::CURRENT_VERSION . $salt . $iv . self::plainEncrypt($plaintext, $ekey, $iv);
|
||||
$auth = \hash_hmac(Core::HASH_FUNCTION_NAME, $ciphertext, $akey, true);
|
||||
$ciphertext = $ciphertext . $auth;
|
||||
|
||||
if ($raw_binary) {
|
||||
return $ciphertext;
|
||||
}
|
||||
return Encoding::binToHex($ciphertext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a ciphertext to a string with either a key or a password.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param KeyOrPassword $secret
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function decryptInternal($ciphertext, KeyOrPassword $secret, $raw_binary)
|
||||
{
|
||||
RuntimeTests::runtimeTest();
|
||||
|
||||
if (! $raw_binary) {
|
||||
try {
|
||||
$ciphertext = Encoding::hexToBin($ciphertext);
|
||||
} catch (Ex\BadFormatException $ex) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext has invalid hex encoding.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (Core::ourStrlen($ciphertext) < Core::MINIMUM_CIPHERTEXT_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext is too short.'
|
||||
);
|
||||
}
|
||||
|
||||
// Get and check the version header.
|
||||
/** @var string $header */
|
||||
$header = Core::ourSubstr($ciphertext, 0, Core::HEADER_VERSION_SIZE);
|
||||
if ($header !== Core::CURRENT_VERSION) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Bad version header.'
|
||||
);
|
||||
}
|
||||
|
||||
// Get the salt.
|
||||
/** @var string $salt */
|
||||
$salt = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::HEADER_VERSION_SIZE,
|
||||
Core::SALT_BYTE_SIZE
|
||||
);
|
||||
Core::ensureTrue(\is_string($salt));
|
||||
|
||||
// Get the IV.
|
||||
/** @var string $iv */
|
||||
$iv = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE,
|
||||
Core::BLOCK_BYTE_SIZE
|
||||
);
|
||||
Core::ensureTrue(\is_string($iv));
|
||||
|
||||
// Get the HMAC.
|
||||
/** @var string $hmac */
|
||||
$hmac = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE,
|
||||
Core::MAC_BYTE_SIZE
|
||||
);
|
||||
Core::ensureTrue(\is_string($hmac));
|
||||
|
||||
// Get the actual encrypted ciphertext.
|
||||
/** @var string $encrypted */
|
||||
$encrypted = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE +
|
||||
Core::BLOCK_BYTE_SIZE,
|
||||
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE - Core::SALT_BYTE_SIZE -
|
||||
Core::BLOCK_BYTE_SIZE - Core::HEADER_VERSION_SIZE
|
||||
);
|
||||
Core::ensureTrue(\is_string($encrypted));
|
||||
|
||||
// Derive the separate encryption and authentication keys from the key
|
||||
// or password, whichever it is.
|
||||
$keys = $secret->deriveKeys($salt);
|
||||
|
||||
if (self::verifyHMAC($hmac, $header . $salt . $iv . $encrypted, $keys->getAuthenticationKey())) {
|
||||
$plaintext = self::plainDecrypt($encrypted, $keys->getEncryptionKey(), $iv, Core::CIPHER_METHOD);
|
||||
return $plaintext;
|
||||
} else {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Integrity check failed.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw unauthenticated encryption (insecure on its own).
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param string $key
|
||||
* @param string $iv
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function plainEncrypt(
|
||||
$plaintext,
|
||||
#[\SensitiveParameter]
|
||||
$key,
|
||||
#[\SensitiveParameter]
|
||||
$iv
|
||||
)
|
||||
{
|
||||
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
||||
Core::ensureFunctionExists('openssl_encrypt');
|
||||
/** @var string $ciphertext */
|
||||
$ciphertext = \openssl_encrypt(
|
||||
$plaintext,
|
||||
Core::CIPHER_METHOD,
|
||||
$key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
|
||||
Core::ensureTrue(\is_string($ciphertext), 'openssl_encrypt() failed');
|
||||
|
||||
return $ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw unauthenticated decryption (insecure on its own).
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param string $key
|
||||
* @param string $iv
|
||||
* @param string $cipherMethod
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function plainDecrypt(
|
||||
$ciphertext,
|
||||
#[\SensitiveParameter]
|
||||
$key,
|
||||
#[\SensitiveParameter]
|
||||
$iv,
|
||||
$cipherMethod
|
||||
)
|
||||
{
|
||||
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
||||
Core::ensureFunctionExists('openssl_decrypt');
|
||||
|
||||
/** @var string $plaintext */
|
||||
$plaintext = \openssl_decrypt(
|
||||
$ciphertext,
|
||||
$cipherMethod,
|
||||
$key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
Core::ensureTrue(\is_string($plaintext), 'openssl_decrypt() failed.');
|
||||
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies an HMAC without leaking information through side-channels.
|
||||
*
|
||||
* @param string $expected_hmac
|
||||
* @param string $message
|
||||
* @param string $key
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function verifyHMAC(
|
||||
$expected_hmac,
|
||||
$message,
|
||||
#[\SensitiveParameter]
|
||||
$key
|
||||
)
|
||||
{
|
||||
$message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true);
|
||||
return Core::hashEquals($message_hmac, $expected_hmac);
|
||||
}
|
||||
}
|
||||
50
libraries/vendor/defuse/php-encryption/src/DerivedKeys.php
vendored
Normal file
50
libraries/vendor/defuse/php-encryption/src/DerivedKeys.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
/**
|
||||
* Class DerivedKeys
|
||||
* @package Defuse\Crypto
|
||||
*/
|
||||
final class DerivedKeys
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $akey = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $ekey = '';
|
||||
|
||||
/**
|
||||
* Returns the authentication key.
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthenticationKey()
|
||||
{
|
||||
return $this->akey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encryption key.
|
||||
* @return string
|
||||
*/
|
||||
public function getEncryptionKey()
|
||||
{
|
||||
return $this->ekey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DerivedKeys.
|
||||
*
|
||||
* @param string $akey
|
||||
* @param string $ekey
|
||||
*/
|
||||
public function __construct($akey, $ekey)
|
||||
{
|
||||
$this->akey = $akey;
|
||||
$this->ekey = $ekey;
|
||||
}
|
||||
}
|
||||
277
libraries/vendor/defuse/php-encryption/src/Encoding.php
vendored
Normal file
277
libraries/vendor/defuse/php-encryption/src/Encoding.php
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class Encoding
|
||||
{
|
||||
const CHECKSUM_BYTE_SIZE = 32;
|
||||
const CHECKSUM_HASH_ALGO = 'sha256';
|
||||
const SERIALIZE_HEADER_BYTES = 4;
|
||||
|
||||
/**
|
||||
* Converts a byte string to a hexadecimal string without leaking
|
||||
* information through side channels.
|
||||
*
|
||||
* @param string $byte_string
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function binToHex($byte_string)
|
||||
{
|
||||
$hex = '';
|
||||
$len = Core::ourStrlen($byte_string);
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$c = \ord($byte_string[$i]) & 0xf;
|
||||
$b = \ord($byte_string[$i]) >> 4;
|
||||
$hex .= \pack(
|
||||
'CC',
|
||||
87 + $b + ((($b - 10) >> 8) & ~38),
|
||||
87 + $c + ((($c - 10) >> 8) & ~38)
|
||||
);
|
||||
}
|
||||
return $hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hexadecimal string into a byte string without leaking
|
||||
* information through side channels.
|
||||
*
|
||||
* @param string $hex_string
|
||||
*
|
||||
* @throws Ex\BadFormatException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
* @psalm-suppress TypeDoesNotContainType
|
||||
*/
|
||||
public static function hexToBin($hex_string)
|
||||
{
|
||||
$hex_pos = 0;
|
||||
$bin = '';
|
||||
$hex_len = Core::ourStrlen($hex_string);
|
||||
$state = 0;
|
||||
$c_acc = 0;
|
||||
|
||||
while ($hex_pos < $hex_len) {
|
||||
$c = \ord($hex_string[$hex_pos]);
|
||||
$c_num = $c ^ 48;
|
||||
$c_num0 = ($c_num - 10) >> 8;
|
||||
$c_alpha = ($c & ~32) - 55;
|
||||
$c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
|
||||
if (($c_num0 | $c_alpha0) === 0) {
|
||||
throw new Ex\BadFormatException(
|
||||
'Encoding::hexToBin() input is not a hex string.'
|
||||
);
|
||||
}
|
||||
$c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
|
||||
if ($state === 0) {
|
||||
$c_acc = $c_val * 16;
|
||||
} else {
|
||||
$bin .= \pack('C', $c_acc | $c_val);
|
||||
}
|
||||
$state ^= 1;
|
||||
++$hex_pos;
|
||||
}
|
||||
return $bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove trialing whitespace without table look-ups or branches.
|
||||
*
|
||||
* Calling this function may leak the length of the string as well as the
|
||||
* number of trailing whitespace characters through side-channels.
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function trimTrailingWhitespace($string = '')
|
||||
{
|
||||
$length = Core::ourStrlen($string);
|
||||
if ($length < 1) {
|
||||
return '';
|
||||
}
|
||||
do {
|
||||
$prevLength = $length;
|
||||
$last = $length - 1;
|
||||
$chr = \ord($string[$last]);
|
||||
|
||||
/* Null Byte (0x00), a.k.a. \0 */
|
||||
// if ($chr === 0x00) $length -= 1;
|
||||
$sub = (($chr - 1) >> 8 ) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* Horizontal Tab (0x09) a.k.a. \t */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x09) $length -= 1;
|
||||
$sub = (((0x08 - $chr) & ($chr - 0x0a)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* New Line (0x0a), a.k.a. \n */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x0a) $length -= 1;
|
||||
$sub = (((0x09 - $chr) & ($chr - 0x0b)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* Carriage Return (0x0D), a.k.a. \r */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x0d) $length -= 1;
|
||||
$sub = (((0x0c - $chr) & ($chr - 0x0e)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* Space */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x20) $length -= 1;
|
||||
$sub = (((0x1f - $chr) & ($chr - 0x21)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
} while ($prevLength !== $length && $length > 0);
|
||||
return (string) Core::ourSubstr($string, 0, $length);
|
||||
}
|
||||
|
||||
/*
|
||||
* SECURITY NOTE ON APPLYING CHECKSUMS TO SECRETS:
|
||||
*
|
||||
* The checksum introduces a potential security weakness. For example,
|
||||
* suppose we apply a checksum to a key, and that an adversary has an
|
||||
* exploit against the process containing the key, such that they can
|
||||
* overwrite an arbitrary byte of memory and then cause the checksum to
|
||||
* be verified and learn the result.
|
||||
*
|
||||
* In this scenario, the adversary can extract the key one byte at
|
||||
* a time by overwriting it with their guess of its value and then
|
||||
* asking if the checksum matches. If it does, their guess was right.
|
||||
* This kind of attack may be more easy to implement and more reliable
|
||||
* than a remote code execution attack.
|
||||
*
|
||||
* This attack also applies to authenticated encryption as a whole, in
|
||||
* the situation where the adversary can overwrite a byte of the key
|
||||
* and then cause a valid ciphertext to be decrypted, and then
|
||||
* determine whether the MAC check passed or failed.
|
||||
*
|
||||
* By using the full SHA256 hash instead of truncating it, I'm ensuring
|
||||
* that both ways of going about the attack are equivalently difficult.
|
||||
* A shorter checksum of say 32 bits might be more useful to the
|
||||
* adversary as an oracle in case their writes are coarser grained.
|
||||
*
|
||||
* Because the scenario assumes a serious vulnerability, we don't try
|
||||
* to prevent attacks of this style.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INTERNAL USE ONLY: Applies a version header, applies a checksum, and
|
||||
* then encodes a byte string into a range of printable ASCII characters.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string $bytes
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function saveBytesToChecksummedAsciiSafeString(
|
||||
$header,
|
||||
#[\SensitiveParameter]
|
||||
$bytes
|
||||
)
|
||||
{
|
||||
// Headers must be a constant length to prevent one type's header from
|
||||
// being a prefix of another type's header, leading to ambiguity.
|
||||
Core::ensureTrue(
|
||||
Core::ourStrlen($header) === self::SERIALIZE_HEADER_BYTES,
|
||||
'Header must be ' . self::SERIALIZE_HEADER_BYTES . ' bytes.'
|
||||
);
|
||||
|
||||
return Encoding::binToHex(
|
||||
$header .
|
||||
$bytes .
|
||||
\hash(
|
||||
self::CHECKSUM_HASH_ALGO,
|
||||
$header . $bytes,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL USE ONLY: Decodes, verifies the header and checksum, and returns
|
||||
* the encoded byte string.
|
||||
*
|
||||
* @param string $expected_header
|
||||
* @param string $string
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\BadFormatException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function loadBytesFromChecksummedAsciiSafeString(
|
||||
$expected_header,
|
||||
#[\SensitiveParameter]
|
||||
$string
|
||||
)
|
||||
{
|
||||
// Headers must be a constant length to prevent one type's header from
|
||||
// being a prefix of another type's header, leading to ambiguity.
|
||||
Core::ensureTrue(
|
||||
Core::ourStrlen($expected_header) === self::SERIALIZE_HEADER_BYTES,
|
||||
'Header must be 4 bytes.'
|
||||
);
|
||||
|
||||
/* If you get an exception here when attempting to load from a file, first pass your
|
||||
key to Encoding::trimTrailingWhitespace() to remove newline characters, etc. */
|
||||
$bytes = Encoding::hexToBin($string);
|
||||
|
||||
/* Make sure we have enough bytes to get the version header and checksum. */
|
||||
if (Core::ourStrlen($bytes) < self::SERIALIZE_HEADER_BYTES + self::CHECKSUM_BYTE_SIZE) {
|
||||
throw new Ex\BadFormatException(
|
||||
'Encoded data is shorter than expected.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Grab the version header. */
|
||||
$actual_header = (string) Core::ourSubstr($bytes, 0, self::SERIALIZE_HEADER_BYTES);
|
||||
|
||||
if ($actual_header !== $expected_header) {
|
||||
throw new Ex\BadFormatException(
|
||||
'Invalid header.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Grab the bytes that are part of the checksum. */
|
||||
$checked_bytes = (string) Core::ourSubstr(
|
||||
$bytes,
|
||||
0,
|
||||
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE
|
||||
);
|
||||
|
||||
/* Grab the included checksum. */
|
||||
$checksum_a = (string) Core::ourSubstr(
|
||||
$bytes,
|
||||
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE,
|
||||
self::CHECKSUM_BYTE_SIZE
|
||||
);
|
||||
|
||||
/* Re-compute the checksum. */
|
||||
$checksum_b = \hash(self::CHECKSUM_HASH_ALGO, $checked_bytes, true);
|
||||
|
||||
/* Check if the checksum matches. */
|
||||
if (! Core::hashEquals($checksum_a, $checksum_b)) {
|
||||
throw new Ex\BadFormatException(
|
||||
"Data is corrupted, the checksum doesn't match"
|
||||
);
|
||||
}
|
||||
|
||||
return (string) Core::ourSubstr(
|
||||
$bytes,
|
||||
self::SERIALIZE_HEADER_BYTES,
|
||||
Core::ourStrlen($bytes) - self::SERIALIZE_HEADER_BYTES - self::CHECKSUM_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
}
|
||||
7
libraries/vendor/defuse/php-encryption/src/Exception/BadFormatException.php
vendored
Normal file
7
libraries/vendor/defuse/php-encryption/src/Exception/BadFormatException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class BadFormatException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
7
libraries/vendor/defuse/php-encryption/src/Exception/CryptoException.php
vendored
Normal file
7
libraries/vendor/defuse/php-encryption/src/Exception/CryptoException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class CryptoException extends \Exception
|
||||
{
|
||||
}
|
||||
7
libraries/vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php
vendored
Normal file
7
libraries/vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class EnvironmentIsBrokenException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
7
libraries/vendor/defuse/php-encryption/src/Exception/IOException.php
vendored
Normal file
7
libraries/vendor/defuse/php-encryption/src/Exception/IOException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class IOException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class WrongKeyOrModifiedCiphertextException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
835
libraries/vendor/defuse/php-encryption/src/File.php
vendored
Normal file
835
libraries/vendor/defuse/php-encryption/src/File.php
vendored
Normal file
@ -0,0 +1,835 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class File
|
||||
{
|
||||
/**
|
||||
* Encrypts the input file, saving the ciphertext to the output file.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
public static function encryptFile($inputFilename, $outputFilename, Key $key)
|
||||
{
|
||||
self::encryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a file with a password, using a slow key derivation function to
|
||||
* make password cracking more expensive.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
public static function encryptFileWithPassword(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::encryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the input file, saving the plaintext to the output file.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptFile($inputFilename, $outputFilename, Key $key)
|
||||
{
|
||||
self::decryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a file with a password, using a slow key derivation function to
|
||||
* make password cracking more expensive.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptFileWithPassword(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::decryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes two resource handles and encrypts the contents of the first,
|
||||
* writing the ciphertext into the second.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function encryptResource($inputHandle, $outputHandle, Key $key)
|
||||
{
|
||||
self::encryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the contents of one resource handle into another with a
|
||||
* password, using a slow key derivation function to make password cracking
|
||||
* more expensive.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function encryptResourceWithPassword(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::encryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes two resource handles and decrypts the contents of the first,
|
||||
* writing the plaintext into the second.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptResource($inputHandle, $outputHandle, Key $key)
|
||||
{
|
||||
self::decryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the contents of one resource into another with a password, using
|
||||
* a slow key derivation function to make password cracking more expensive.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptResourceWithPassword(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::decryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a file with either a key or a password.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\CryptoException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
private static function encryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
|
||||
{
|
||||
if (file_exists($inputFilename) && file_exists($outputFilename) && realpath($inputFilename) === realpath($outputFilename)) {
|
||||
throw new Ex\IOException('Input and output filenames must be different.');
|
||||
}
|
||||
|
||||
/* Open the input file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$if = @\fopen($inputFilename, 'rb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($if === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot open input file for encrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
if (\is_callable('\\stream_set_read_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_read_buffer($if, 0);
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$of = @\fopen($outputFilename, 'wb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($of === false) {
|
||||
\fclose($if);
|
||||
throw new Ex\IOException(
|
||||
'Cannot open output file for encrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
if (\is_callable('\\stream_set_write_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_write_buffer($of, 0);
|
||||
}
|
||||
|
||||
/* Perform the encryption. */
|
||||
try {
|
||||
self::encryptResourceInternal($if, $of, $secret);
|
||||
} catch (Ex\CryptoException $ex) {
|
||||
\fclose($if);
|
||||
\fclose($of);
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
/* Close the input file. */
|
||||
if (\fclose($if) === false) {
|
||||
\fclose($of);
|
||||
throw new Ex\IOException(
|
||||
'Cannot close input file after encrypting'
|
||||
);
|
||||
}
|
||||
|
||||
/* Close the output file. */
|
||||
if (\fclose($of) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot close output file after encrypting'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a file with either a key or a password.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\CryptoException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
private static function decryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
|
||||
{
|
||||
if (file_exists($inputFilename) && file_exists($outputFilename) && realpath($inputFilename) === realpath($outputFilename)) {
|
||||
throw new Ex\IOException('Input and output filenames must be different.');
|
||||
}
|
||||
|
||||
/* Open the input file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$if = @\fopen($inputFilename, 'rb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($if === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot open input file for decrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
|
||||
if (\is_callable('\\stream_set_read_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_read_buffer($if, 0);
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$of = @\fopen($outputFilename, 'wb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($of === false) {
|
||||
\fclose($if);
|
||||
throw new Ex\IOException(
|
||||
'Cannot open output file for decrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
|
||||
if (\is_callable('\\stream_set_write_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_write_buffer($of, 0);
|
||||
}
|
||||
|
||||
/* Perform the decryption. */
|
||||
try {
|
||||
self::decryptResourceInternal($if, $of, $secret);
|
||||
} catch (Ex\CryptoException $ex) {
|
||||
\fclose($if);
|
||||
\fclose($of);
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
/* Close the input file. */
|
||||
if (\fclose($if) === false) {
|
||||
\fclose($of);
|
||||
throw new Ex\IOException(
|
||||
'Cannot close input file after decrypting'
|
||||
);
|
||||
}
|
||||
|
||||
/* Close the output file. */
|
||||
if (\fclose($of) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot close output file after decrypting'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a resource with either a key or a password.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @psalm-suppress PossiblyInvalidArgument
|
||||
* Fixes erroneous errors caused by PHP 7.2 switching the return value
|
||||
* of hash_init from a resource to a HashContext.
|
||||
*/
|
||||
private static function encryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
|
||||
{
|
||||
if (! \is_resource($inputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Input handle must be a resource!'
|
||||
);
|
||||
}
|
||||
if (! \is_resource($outputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Output handle must be a resource!'
|
||||
);
|
||||
}
|
||||
|
||||
$inputStat = \fstat($inputHandle);
|
||||
$inputSize = $inputStat['size'];
|
||||
|
||||
$file_salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
|
||||
$keys = $secret->deriveKeys($file_salt);
|
||||
$ekey = $keys->getEncryptionKey();
|
||||
$akey = $keys->getAuthenticationKey();
|
||||
|
||||
$ivsize = Core::BLOCK_BYTE_SIZE;
|
||||
$iv = Core::secureRandom($ivsize);
|
||||
|
||||
/* Initialize a streaming HMAC state. */
|
||||
/** @var mixed $hmac */
|
||||
$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
|
||||
Core::ensureTrue(
|
||||
\is_resource($hmac) || \is_object($hmac),
|
||||
'Cannot initialize a hash context'
|
||||
);
|
||||
|
||||
/* Write the header, salt, and IV. */
|
||||
self::writeBytes(
|
||||
$outputHandle,
|
||||
Core::CURRENT_VERSION . $file_salt . $iv,
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + $ivsize
|
||||
);
|
||||
|
||||
/* Add the header, salt, and IV to the HMAC. */
|
||||
\hash_update($hmac, Core::CURRENT_VERSION);
|
||||
\hash_update($hmac, $file_salt);
|
||||
\hash_update($hmac, $iv);
|
||||
|
||||
/* $thisIv will be incremented after each call to the encryption. */
|
||||
$thisIv = $iv;
|
||||
|
||||
/* How many blocks do we encrypt at a time? We increment by this value. */
|
||||
/**
|
||||
* @psalm-suppress RedundantCast
|
||||
*/
|
||||
$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);
|
||||
|
||||
/* Loop until we reach the end of the input file. */
|
||||
$at_file_end = false;
|
||||
while (! (\feof($inputHandle) || $at_file_end)) {
|
||||
/* Find out if we can read a full buffer, or only a partial one. */
|
||||
/** @var int */
|
||||
$pos = \ftell($inputHandle);
|
||||
if (!\is_int($pos)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not get current position in input file during encryption'
|
||||
);
|
||||
}
|
||||
if ($pos + Core::BUFFER_BYTE_SIZE >= $inputSize) {
|
||||
/* We're at the end of the file, so we need to break out of the loop. */
|
||||
$at_file_end = true;
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
$inputSize - $pos
|
||||
);
|
||||
} else {
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
Core::BUFFER_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
/* Encrypt this buffer. */
|
||||
/** @var string */
|
||||
$encrypted = \openssl_encrypt(
|
||||
$read,
|
||||
Core::CIPHER_METHOD,
|
||||
$ekey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$thisIv
|
||||
);
|
||||
|
||||
Core::ensureTrue(\is_string($encrypted), 'OpenSSL encryption error');
|
||||
|
||||
/* Write this buffer's ciphertext. */
|
||||
self::writeBytes($outputHandle, $encrypted, Core::ourStrlen($encrypted));
|
||||
/* Add this buffer's ciphertext to the HMAC. */
|
||||
\hash_update($hmac, $encrypted);
|
||||
|
||||
/* Increment the counter by the number of blocks in a buffer. */
|
||||
$thisIv = Core::incrementCounter($thisIv, $inc);
|
||||
/* WARNING: Usually, unless the file is a multiple of the buffer
|
||||
* size, $thisIv will contain an incorrect value here on the last
|
||||
* iteration of this loop. */
|
||||
}
|
||||
|
||||
/* Get the HMAC and append it to the ciphertext. */
|
||||
$final_mac = \hash_final($hmac, true);
|
||||
self::writeBytes($outputHandle, $final_mac, Core::MAC_BYTE_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a file-backed resource with either a key or a password.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
* @psalm-suppress PossiblyInvalidArgument
|
||||
* Fixes erroneous errors caused by PHP 7.2 switching the return value
|
||||
* of hash_init from a resource to a HashContext.
|
||||
*/
|
||||
public static function decryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
|
||||
{
|
||||
if (! \is_resource($inputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Input handle must be a resource!'
|
||||
);
|
||||
}
|
||||
if (! \is_resource($outputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Output handle must be a resource!'
|
||||
);
|
||||
}
|
||||
|
||||
/* Make sure the file is big enough for all the reads we need to do. */
|
||||
$stat = \fstat($inputHandle);
|
||||
if ($stat['size'] < Core::MINIMUM_CIPHERTEXT_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Input file is too small to have been created by this library.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Check the version header. */
|
||||
$header = self::readBytes($inputHandle, Core::HEADER_VERSION_SIZE);
|
||||
if ($header !== Core::CURRENT_VERSION) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Bad version header.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Get the salt. */
|
||||
$file_salt = self::readBytes($inputHandle, Core::SALT_BYTE_SIZE);
|
||||
|
||||
/* Get the IV. */
|
||||
$ivsize = Core::BLOCK_BYTE_SIZE;
|
||||
$iv = self::readBytes($inputHandle, $ivsize);
|
||||
|
||||
/* Derive the authentication and encryption keys. */
|
||||
$keys = $secret->deriveKeys($file_salt);
|
||||
$ekey = $keys->getEncryptionKey();
|
||||
$akey = $keys->getAuthenticationKey();
|
||||
|
||||
/* We'll store the MAC of each buffer-sized chunk as we verify the
|
||||
* actual MAC, so that we can check them again when decrypting. */
|
||||
$macs = [];
|
||||
|
||||
/* $thisIv will be incremented after each call to the decryption. */
|
||||
$thisIv = $iv;
|
||||
|
||||
/* How many blocks do we encrypt at a time? We increment by this value. */
|
||||
/**
|
||||
* @psalm-suppress RedundantCast
|
||||
*/
|
||||
$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);
|
||||
|
||||
/* Get the HMAC. */
|
||||
if (\fseek($inputHandle, (-1 * Core::MAC_BYTE_SIZE), SEEK_END) === -1) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot seek to beginning of MAC within input file'
|
||||
);
|
||||
}
|
||||
|
||||
/* Get the position of the last byte in the actual ciphertext. */
|
||||
/** @var int $cipher_end */
|
||||
$cipher_end = \ftell($inputHandle);
|
||||
if (!\is_int($cipher_end)) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot read input file'
|
||||
);
|
||||
}
|
||||
/* We have the position of the first byte of the HMAC. Go back by one. */
|
||||
--$cipher_end;
|
||||
|
||||
/* Read the HMAC. */
|
||||
/** @var string $stored_mac */
|
||||
$stored_mac = self::readBytes($inputHandle, Core::MAC_BYTE_SIZE);
|
||||
|
||||
/* Initialize a streaming HMAC state. */
|
||||
/** @var mixed $hmac */
|
||||
$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
|
||||
Core::ensureTrue(\is_resource($hmac) || \is_object($hmac), 'Cannot initialize a hash context');
|
||||
|
||||
/* Reset file pointer to the beginning of the file after the header */
|
||||
if (\fseek($inputHandle, Core::HEADER_VERSION_SIZE, SEEK_SET) === -1) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot read seek within input file'
|
||||
);
|
||||
}
|
||||
|
||||
/* Seek to the start of the actual ciphertext. */
|
||||
if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize, SEEK_CUR) === -1) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot seek input file to beginning of ciphertext'
|
||||
);
|
||||
}
|
||||
|
||||
/* PASS #1: Calculating the HMAC. */
|
||||
|
||||
\hash_update($hmac, $header);
|
||||
\hash_update($hmac, $file_salt);
|
||||
\hash_update($hmac, $iv);
|
||||
/** @var mixed $hmac2 */
|
||||
$hmac2 = \hash_copy($hmac);
|
||||
|
||||
$break = false;
|
||||
while (! $break) {
|
||||
/** @var int $pos */
|
||||
$pos = \ftell($inputHandle);
|
||||
if (!\is_int($pos)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not get current position in input file during decryption'
|
||||
);
|
||||
}
|
||||
|
||||
/* Read the next buffer-sized chunk (or less). */
|
||||
if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
|
||||
$break = true;
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
$cipher_end - $pos + 1
|
||||
);
|
||||
} else {
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
Core::BUFFER_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
/* Update the HMAC. */
|
||||
\hash_update($hmac, $read);
|
||||
|
||||
/* Remember this buffer-sized chunk's HMAC. */
|
||||
/** @var mixed $chunk_mac */
|
||||
$chunk_mac = \hash_copy($hmac);
|
||||
Core::ensureTrue(\is_resource($chunk_mac) || \is_object($chunk_mac), 'Cannot duplicate a hash context');
|
||||
$macs []= \hash_final($chunk_mac);
|
||||
}
|
||||
|
||||
/* Get the final HMAC, which should match the stored one. */
|
||||
/** @var string $final_mac */
|
||||
$final_mac = \hash_final($hmac, true);
|
||||
|
||||
/* Verify the HMAC. */
|
||||
if (! Core::hashEquals($final_mac, $stored_mac)) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Integrity check failed.'
|
||||
);
|
||||
}
|
||||
|
||||
/* PASS #2: Decrypt and write output. */
|
||||
|
||||
/* Rewind to the start of the actual ciphertext. */
|
||||
if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize + Core::HEADER_VERSION_SIZE, SEEK_SET) === -1) {
|
||||
throw new Ex\IOException(
|
||||
'Could not move the input file pointer during decryption'
|
||||
);
|
||||
}
|
||||
|
||||
$at_file_end = false;
|
||||
while (! $at_file_end) {
|
||||
/** @var int $pos */
|
||||
$pos = \ftell($inputHandle);
|
||||
if (!\is_int($pos)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not get current position in input file during decryption'
|
||||
);
|
||||
}
|
||||
|
||||
/* Read the next buffer-sized chunk (or less). */
|
||||
if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
|
||||
$at_file_end = true;
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
$cipher_end - $pos + 1
|
||||
);
|
||||
} else {
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
Core::BUFFER_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
/* Recalculate the MAC (so far) and compare it with the one we
|
||||
* remembered from pass #1 to ensure attackers didn't change the
|
||||
* ciphertext after MAC verification. */
|
||||
\hash_update($hmac2, $read);
|
||||
/** @var mixed $calc_mac */
|
||||
$calc_mac = \hash_copy($hmac2);
|
||||
Core::ensureTrue(\is_resource($calc_mac) || \is_object($calc_mac), 'Cannot duplicate a hash context');
|
||||
$calc = \hash_final($calc_mac);
|
||||
|
||||
if (empty($macs)) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'File was modified after MAC verification'
|
||||
);
|
||||
} elseif (! Core::hashEquals(\array_shift($macs), $calc)) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'File was modified after MAC verification'
|
||||
);
|
||||
}
|
||||
|
||||
/* Decrypt this buffer-sized chunk. */
|
||||
/** @var string $decrypted */
|
||||
$decrypted = \openssl_decrypt(
|
||||
$read,
|
||||
Core::CIPHER_METHOD,
|
||||
$ekey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$thisIv
|
||||
);
|
||||
Core::ensureTrue(\is_string($decrypted), 'OpenSSL decryption error');
|
||||
|
||||
/* Write the plaintext to the output file. */
|
||||
self::writeBytes(
|
||||
$outputHandle,
|
||||
$decrypted,
|
||||
Core::ourStrlen($decrypted)
|
||||
);
|
||||
|
||||
/* Increment the IV by the amount of blocks in a buffer. */
|
||||
/** @var string $thisIv */
|
||||
$thisIv = Core::incrementCounter($thisIv, $inc);
|
||||
/* WARNING: Usually, unless the file is a multiple of the buffer
|
||||
* size, $thisIv will contain an incorrect value here on the last
|
||||
* iteration of this loop. */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a stream; prevent partial reads.
|
||||
*
|
||||
* @param resource $stream
|
||||
* @param int $num_bytes
|
||||
* @return string
|
||||
*
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
public static function readBytes($stream, $num_bytes)
|
||||
{
|
||||
Core::ensureTrue($num_bytes >= 0, 'Tried to read less than 0 bytes');
|
||||
|
||||
if ($num_bytes === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$buf = '';
|
||||
$remaining = $num_bytes;
|
||||
while ($remaining > 0 && ! \feof($stream)) {
|
||||
/** @var string $read */
|
||||
$read = \fread($stream, $remaining);
|
||||
if (!\is_string($read)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not read from the file'
|
||||
);
|
||||
}
|
||||
$buf .= $read;
|
||||
$remaining -= Core::ourStrlen($read);
|
||||
}
|
||||
if (Core::ourStrlen($buf) !== $num_bytes) {
|
||||
throw new Ex\IOException(
|
||||
'Tried to read past the end of the file'
|
||||
);
|
||||
}
|
||||
return $buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to a stream; prevents partial writes.
|
||||
*
|
||||
* @param resource $stream
|
||||
* @param string $buf
|
||||
* @param int $num_bytes
|
||||
* @return int
|
||||
*
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
public static function writeBytes($stream, $buf, $num_bytes = null)
|
||||
{
|
||||
$bufSize = Core::ourStrlen($buf);
|
||||
if ($num_bytes === null) {
|
||||
$num_bytes = $bufSize;
|
||||
}
|
||||
if ($num_bytes > $bufSize) {
|
||||
throw new Ex\IOException(
|
||||
'Trying to write more bytes than the buffer contains.'
|
||||
);
|
||||
}
|
||||
if ($num_bytes < 0) {
|
||||
throw new Ex\IOException(
|
||||
'Tried to write less than 0 bytes'
|
||||
);
|
||||
}
|
||||
$remaining = $num_bytes;
|
||||
while ($remaining > 0) {
|
||||
/** @var int $written */
|
||||
$written = \fwrite($stream, $buf, $remaining);
|
||||
if (!\is_int($written)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not write to the file'
|
||||
);
|
||||
}
|
||||
$buf = (string) Core::ourSubstr($buf, $written, null);
|
||||
$remaining -= $written;
|
||||
}
|
||||
return $num_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last PHP error's or warning's message string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getLastErrorMessage()
|
||||
{
|
||||
$error = error_get_last();
|
||||
if ($error === null) {
|
||||
return '[no PHP error, or you have a custom error handler set]';
|
||||
} else {
|
||||
return $error['message'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PHPUnit sets an error handler, which prevents getLastErrorMessage() from working,
|
||||
* because error_get_last does not work when custom handlers are set.
|
||||
*
|
||||
* This is a workaround, which should be a no-op in production deployments, to make
|
||||
* getLastErrorMessage() return the error messages that the PHPUnit tests expect.
|
||||
*
|
||||
* If, in a production deployment, a custom error handler is set, the exception
|
||||
* handling will still work as usual, but the error messages will be confusing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function removePHPUnitErrorHandler() {
|
||||
if (defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__')) {
|
||||
set_error_handler(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undoes what removePHPUnitErrorHandler did.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function restorePHPUnitErrorHandler() {
|
||||
if (defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__')) {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
101
libraries/vendor/defuse/php-encryption/src/Key.php
vendored
Normal file
101
libraries/vendor/defuse/php-encryption/src/Key.php
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class Key
|
||||
{
|
||||
const KEY_CURRENT_VERSION = "\xDE\xF0\x00\x00";
|
||||
const KEY_BYTE_SIZE = 32;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $key_bytes;
|
||||
|
||||
/**
|
||||
* Creates new random key.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return Key
|
||||
*/
|
||||
public static function createNewRandomKey()
|
||||
{
|
||||
return new Key(Core::secureRandom(self::KEY_BYTE_SIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a Key from its encoded form.
|
||||
*
|
||||
* By default, this function will call Encoding::trimTrailingWhitespace()
|
||||
* to remove trailing CR, LF, NUL, TAB, and SPACE characters, which are
|
||||
* commonly appended to files when working with text editors.
|
||||
*
|
||||
* @param string $saved_key_string
|
||||
* @param bool $do_not_trim (default: false)
|
||||
*
|
||||
* @throws Ex\BadFormatException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return Key
|
||||
*/
|
||||
public static function loadFromAsciiSafeString(
|
||||
#[\SensitiveParameter]
|
||||
$saved_key_string,
|
||||
$do_not_trim = false
|
||||
)
|
||||
{
|
||||
if (!$do_not_trim) {
|
||||
$saved_key_string = Encoding::trimTrailingWhitespace($saved_key_string);
|
||||
}
|
||||
$key_bytes = Encoding::loadBytesFromChecksummedAsciiSafeString(self::KEY_CURRENT_VERSION, $saved_key_string);
|
||||
return new Key($key_bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the Key into a string of printable ASCII characters.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function saveToAsciiSafeString()
|
||||
{
|
||||
return Encoding::saveBytesToChecksummedAsciiSafeString(
|
||||
self::KEY_CURRENT_VERSION,
|
||||
$this->key_bytes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw bytes of the key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRawBytes()
|
||||
{
|
||||
return $this->key_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Key object from a string of raw bytes.
|
||||
*
|
||||
* @param string $bytes
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
private function __construct(
|
||||
#[\SensitiveParameter]
|
||||
$bytes
|
||||
)
|
||||
{
|
||||
Core::ensureTrue(
|
||||
Core::ourStrlen($bytes) === self::KEY_BYTE_SIZE,
|
||||
'Bad key length.'
|
||||
);
|
||||
$this->key_bytes = $bytes;
|
||||
}
|
||||
|
||||
}
|
||||
156
libraries/vendor/defuse/php-encryption/src/KeyOrPassword.php
vendored
Normal file
156
libraries/vendor/defuse/php-encryption/src/KeyOrPassword.php
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class KeyOrPassword
|
||||
{
|
||||
const PBKDF2_ITERATIONS = 100000;
|
||||
const SECRET_TYPE_KEY = 1;
|
||||
const SECRET_TYPE_PASSWORD = 2;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $secret_type = 0;
|
||||
|
||||
/**
|
||||
* @var Key|string
|
||||
*/
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Initializes an instance of KeyOrPassword from a key.
|
||||
*
|
||||
* @param Key $key
|
||||
*
|
||||
* @return KeyOrPassword
|
||||
*/
|
||||
public static function createFromKey(Key $key)
|
||||
{
|
||||
return new KeyOrPassword(self::SECRET_TYPE_KEY, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an instance of KeyOrPassword from a password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @return KeyOrPassword
|
||||
*/
|
||||
public static function createFromPassword(
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
return new KeyOrPassword(self::SECRET_TYPE_PASSWORD, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives authentication and encryption keys from the secret, using a slow
|
||||
* key derivation function if the secret is a password.
|
||||
*
|
||||
* @param string $salt
|
||||
*
|
||||
* @throws Ex\CryptoException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return DerivedKeys
|
||||
*/
|
||||
public function deriveKeys($salt)
|
||||
{
|
||||
Core::ensureTrue(
|
||||
Core::ourStrlen($salt) === Core::SALT_BYTE_SIZE,
|
||||
'Bad salt.'
|
||||
);
|
||||
|
||||
if ($this->secret_type === self::SECRET_TYPE_KEY) {
|
||||
Core::ensureTrue($this->secret instanceof Key);
|
||||
/**
|
||||
* @psalm-suppress PossiblyInvalidMethodCall
|
||||
*/
|
||||
$akey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$this->secret->getRawBytes(),
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::AUTHENTICATION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
/**
|
||||
* @psalm-suppress PossiblyInvalidMethodCall
|
||||
*/
|
||||
$ekey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$this->secret->getRawBytes(),
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::ENCRYPTION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
return new DerivedKeys($akey, $ekey);
|
||||
} elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) {
|
||||
Core::ensureTrue(\is_string($this->secret));
|
||||
/* Our PBKDF2 polyfill is vulnerable to a DoS attack documented in
|
||||
* GitHub issue #230. The fix is to pre-hash the password to ensure
|
||||
* it is short. We do the prehashing here instead of in pbkdf2() so
|
||||
* that pbkdf2() still computes the function as defined by the
|
||||
* standard. */
|
||||
|
||||
/**
|
||||
* @psalm-suppress PossiblyInvalidArgument
|
||||
*/
|
||||
$prehash = \hash(Core::HASH_FUNCTION_NAME, $this->secret, true);
|
||||
|
||||
$prekey = Core::pbkdf2(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$prehash,
|
||||
$salt,
|
||||
self::PBKDF2_ITERATIONS,
|
||||
Core::KEY_BYTE_SIZE,
|
||||
true
|
||||
);
|
||||
$akey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$prekey,
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::AUTHENTICATION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
/* Note the cryptographic re-use of $salt here. */
|
||||
$ekey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$prekey,
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::ENCRYPTION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
return new DerivedKeys($akey, $ekey);
|
||||
} else {
|
||||
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for KeyOrPassword.
|
||||
*
|
||||
* @param int $secret_type
|
||||
* @param mixed $secret (either a Key or a password string)
|
||||
*/
|
||||
private function __construct(
|
||||
$secret_type,
|
||||
#[\SensitiveParameter]
|
||||
$secret
|
||||
)
|
||||
{
|
||||
// The constructor is private, so these should never throw.
|
||||
if ($secret_type === self::SECRET_TYPE_KEY) {
|
||||
Core::ensureTrue($secret instanceof Key);
|
||||
} elseif ($secret_type === self::SECRET_TYPE_PASSWORD) {
|
||||
Core::ensureTrue(\is_string($secret));
|
||||
} else {
|
||||
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
|
||||
}
|
||||
$this->secret_type = $secret_type;
|
||||
$this->secret = $secret;
|
||||
}
|
||||
}
|
||||
159
libraries/vendor/defuse/php-encryption/src/KeyProtectedByPassword.php
vendored
Normal file
159
libraries/vendor/defuse/php-encryption/src/KeyProtectedByPassword.php
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class KeyProtectedByPassword
|
||||
{
|
||||
const PASSWORD_KEY_CURRENT_VERSION = "\xDE\xF1\x00\x00";
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $encrypted_key = '';
|
||||
|
||||
/**
|
||||
* Creates a random key protected by the provided password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public static function createRandomPasswordProtectedKey(
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
$inner_key = Key::createNewRandomKey();
|
||||
/* The password is hashed as a form of poor-man's domain separation
|
||||
* between this use of encryptWithPassword() and other uses of
|
||||
* encryptWithPassword() that the user may also be using as part of the
|
||||
* same protocol. */
|
||||
$encrypted_key = Crypto::encryptWithPassword(
|
||||
$inner_key->saveToAsciiSafeString(),
|
||||
\hash(Core::HASH_FUNCTION_NAME, $password, true),
|
||||
true
|
||||
);
|
||||
|
||||
return new KeyProtectedByPassword($encrypted_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a KeyProtectedByPassword from its encoded form.
|
||||
*
|
||||
* @param string $saved_key_string
|
||||
*
|
||||
* @throws Ex\BadFormatException
|
||||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public static function loadFromAsciiSafeString(
|
||||
#[\SensitiveParameter]
|
||||
$saved_key_string
|
||||
)
|
||||
{
|
||||
$encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString(
|
||||
self::PASSWORD_KEY_CURRENT_VERSION,
|
||||
$saved_key_string
|
||||
);
|
||||
return new KeyProtectedByPassword($encrypted_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the KeyProtectedByPassword into a string of printable ASCII
|
||||
* characters.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function saveToAsciiSafeString()
|
||||
{
|
||||
return Encoding::saveBytesToChecksummedAsciiSafeString(
|
||||
self::PASSWORD_KEY_CURRENT_VERSION,
|
||||
$this->encrypted_key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the protected key, returning an unprotected Key object that can
|
||||
* be used for encryption and decryption.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @param string $password
|
||||
* @return Key
|
||||
*/
|
||||
public function unlockKey(
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
try {
|
||||
$inner_key_encoded = Crypto::decryptWithPassword(
|
||||
$this->encrypted_key,
|
||||
\hash(Core::HASH_FUNCTION_NAME, $password, true),
|
||||
true
|
||||
);
|
||||
return Key::loadFromAsciiSafeString($inner_key_encoded);
|
||||
} catch (Ex\BadFormatException $ex) {
|
||||
/* This should never happen unless an attacker replaced the
|
||||
* encrypted key ciphertext with some other ciphertext that was
|
||||
* encrypted with the same password. We transform the exception type
|
||||
* here in order to make the API simpler, avoiding the need to
|
||||
* document that this method might throw an Ex\BadFormatException. */
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
"The decrypted key was found to be in an invalid format. " .
|
||||
"This very likely indicates it was modified by an attacker."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the password.
|
||||
*
|
||||
* @param string $current_password
|
||||
* @param string $new_password
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public function changePassword(
|
||||
#[\SensitiveParameter]
|
||||
$current_password,
|
||||
#[\SensitiveParameter]
|
||||
$new_password
|
||||
)
|
||||
{
|
||||
$inner_key = $this->unlockKey($current_password);
|
||||
/* The password is hashed as a form of poor-man's domain separation
|
||||
* between this use of encryptWithPassword() and other uses of
|
||||
* encryptWithPassword() that the user may also be using as part of the
|
||||
* same protocol. */
|
||||
$encrypted_key = Crypto::encryptWithPassword(
|
||||
$inner_key->saveToAsciiSafeString(),
|
||||
\hash(Core::HASH_FUNCTION_NAME, $new_password, true),
|
||||
true
|
||||
);
|
||||
|
||||
$this->encrypted_key = $encrypted_key;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for KeyProtectedByPassword.
|
||||
*
|
||||
* @param string $encrypted_key
|
||||
*/
|
||||
private function __construct($encrypted_key)
|
||||
{
|
||||
$this->encrypted_key = $encrypted_key;
|
||||
}
|
||||
}
|
||||
228
libraries/vendor/defuse/php-encryption/src/RuntimeTests.php
vendored
Normal file
228
libraries/vendor/defuse/php-encryption/src/RuntimeTests.php
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
/*
|
||||
* We're using static class inheritance to get access to protected methods
|
||||
* inside Crypto. To make it easy to know where the method we're calling can be
|
||||
* found, within this file, prefix calls with `Crypto::` or `RuntimeTests::`,
|
||||
* and don't use `self::`.
|
||||
*/
|
||||
|
||||
class RuntimeTests extends Crypto
|
||||
{
|
||||
/**
|
||||
* Runs the runtime tests.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
public static function runtimeTest()
|
||||
{
|
||||
// 0: Tests haven't been run yet.
|
||||
// 1: Tests have passed.
|
||||
// 2: Tests are running right now.
|
||||
// 3: Tests have failed.
|
||||
static $test_state = 0;
|
||||
|
||||
if ($test_state === 1 || $test_state === 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($test_state === 3) {
|
||||
/* If an intermittent problem caused a test to fail previously, we
|
||||
* want that to be indicated to the user with every call to this
|
||||
* library. This way, if the user first does something they really
|
||||
* don't care about, and just ignores all exceptions, they won't get
|
||||
* screwed when they then start to use the library for something
|
||||
* they do care about. */
|
||||
throw new Ex\EnvironmentIsBrokenException('Tests failed previously.');
|
||||
}
|
||||
|
||||
try {
|
||||
$test_state = 2;
|
||||
|
||||
Core::ensureFunctionExists('openssl_get_cipher_methods');
|
||||
if (\in_array(Core::CIPHER_METHOD, \openssl_get_cipher_methods()) === false) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Cipher method not supported. This is normally caused by an outdated ' .
|
||||
'version of OpenSSL (and/or OpenSSL compiled for FIPS compliance). ' .
|
||||
'Please upgrade to a newer version of OpenSSL that supports ' .
|
||||
Core::CIPHER_METHOD . ' to use this library.'
|
||||
);
|
||||
}
|
||||
|
||||
RuntimeTests::AESTestVector();
|
||||
RuntimeTests::HMACTestVector();
|
||||
RuntimeTests::HKDFTestVector();
|
||||
|
||||
RuntimeTests::testEncryptDecrypt();
|
||||
Core::ensureTrue(Core::ourStrlen(Key::createNewRandomKey()->getRawBytes()) === Core::KEY_BYTE_SIZE);
|
||||
|
||||
Core::ensureTrue(Core::ENCRYPTION_INFO_STRING !== Core::AUTHENTICATION_INFO_STRING);
|
||||
} catch (Ex\EnvironmentIsBrokenException $ex) {
|
||||
// Do this, otherwise it will stay in the "tests are running" state.
|
||||
$test_state = 3;
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
// Change this to '0' make the tests always re-run (for benchmarking).
|
||||
$test_state = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* High-level tests of Crypto operations.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function testEncryptDecrypt()
|
||||
{
|
||||
$key = Key::createNewRandomKey();
|
||||
$data = "EnCrYpT EvErYThInG\x00\x00";
|
||||
|
||||
// Make sure encrypting then decrypting doesn't change the message.
|
||||
$ciphertext = Crypto::encrypt($data, $key, true);
|
||||
try {
|
||||
$decrypted = Crypto::decrypt($ciphertext, $key, true);
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $ex) {
|
||||
// It's important to catch this and change it into a
|
||||
// Ex\EnvironmentIsBrokenException, otherwise a test failure could trick
|
||||
// the user into thinking it's just an invalid ciphertext!
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
Core::ensureTrue($decrypted === $data);
|
||||
|
||||
// Modifying the ciphertext: Appending a string.
|
||||
try {
|
||||
Crypto::decrypt($ciphertext . 'a', $key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
|
||||
// Modifying the ciphertext: Changing an HMAC byte.
|
||||
$indices_to_change = [
|
||||
0, // The header.
|
||||
Core::HEADER_VERSION_SIZE + 1, // the salt
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + 1, // the IV
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + Core::BLOCK_BYTE_SIZE + 1, // the ciphertext
|
||||
];
|
||||
|
||||
foreach ($indices_to_change as $index) {
|
||||
try {
|
||||
$ciphertext[$index] = \chr((\ord($ciphertext[$index]) + 1) % 256);
|
||||
Crypto::decrypt($ciphertext, $key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypting with the wrong key.
|
||||
$key = Key::createNewRandomKey();
|
||||
$data = 'abcdef';
|
||||
$ciphertext = Crypto::encrypt($data, $key, true);
|
||||
$wrong_key = Key::createNewRandomKey();
|
||||
try {
|
||||
Crypto::decrypt($ciphertext, $wrong_key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
|
||||
// Ciphertext too small.
|
||||
$key = Key::createNewRandomKey();
|
||||
$ciphertext = \str_repeat('A', Core::MINIMUM_CIPHERTEXT_SIZE - 1);
|
||||
try {
|
||||
Crypto::decrypt($ciphertext, $key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test HKDF against test vectors.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function HKDFTestVector()
|
||||
{
|
||||
// HKDF test vectors from RFC 5869
|
||||
|
||||
// Test Case 1
|
||||
$ikm = \str_repeat("\x0b", 22);
|
||||
$salt = Encoding::hexToBin('000102030405060708090a0b0c');
|
||||
$info = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9');
|
||||
$length = 42;
|
||||
$okm = Encoding::hexToBin(
|
||||
'3cb25f25faacd57a90434f64d0362f2a' .
|
||||
'2d2d0a90cf1a5a4c5db02d56ecc4c5bf' .
|
||||
'34007208d5b887185865'
|
||||
);
|
||||
$computed_okm = Core::HKDF('sha256', $ikm, $length, $info, $salt);
|
||||
Core::ensureTrue($computed_okm === $okm);
|
||||
|
||||
// Test Case 7
|
||||
$ikm = \str_repeat("\x0c", 22);
|
||||
$length = 42;
|
||||
$okm = Encoding::hexToBin(
|
||||
'2c91117204d745f3500d636a62f64f0a' .
|
||||
'b3bae548aa53d423b0d1f27ebba6f5e5' .
|
||||
'673a081d70cce7acfc48'
|
||||
);
|
||||
$computed_okm = Core::HKDF('sha1', $ikm, $length, '', null);
|
||||
Core::ensureTrue($computed_okm === $okm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test HMAC against test vectors.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function HMACTestVector()
|
||||
{
|
||||
// HMAC test vector From RFC 4231 (Test Case 1)
|
||||
$key = \str_repeat("\x0b", 20);
|
||||
$data = 'Hi There';
|
||||
$correct = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
|
||||
Core::ensureTrue(
|
||||
\hash_hmac(Core::HASH_FUNCTION_NAME, $data, $key) === $correct
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test AES against test vectors.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function AESTestVector()
|
||||
{
|
||||
// AES CTR mode test vector from NIST SP 800-38A
|
||||
$key = Encoding::hexToBin(
|
||||
'603deb1015ca71be2b73aef0857d7781' .
|
||||
'1f352c073b6108d72d9810a30914dff4'
|
||||
);
|
||||
$iv = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
|
||||
$plaintext = Encoding::hexToBin(
|
||||
'6bc1bee22e409f96e93d7e117393172a' .
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' .
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' .
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
);
|
||||
$ciphertext = Encoding::hexToBin(
|
||||
'601ec313775789a5b7a7f504bbf3d228' .
|
||||
'f443e3ca4d62b59aca84e990cacaf5c5' .
|
||||
'2b0930daa23de94ce87017ba2d84988d' .
|
||||
'dfc9c58db67aada613c2dd08457941a6'
|
||||
);
|
||||
|
||||
$computed_ciphertext = Crypto::plainEncrypt($plaintext, $key, $iv);
|
||||
Core::ensureTrue($computed_ciphertext === $ciphertext);
|
||||
|
||||
$computed_plaintext = Crypto::plainDecrypt($ciphertext, $key, $iv, Core::CIPHER_METHOD);
|
||||
Core::ensureTrue($computed_plaintext === $plaintext);
|
||||
}
|
||||
}
|
||||
19
libraries/vendor/doctrine/inflector/LICENSE
vendored
Normal file
19
libraries/vendor/doctrine/inflector/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2015 Doctrine Project
|
||||
|
||||
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.
|
||||
284
libraries/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php
vendored
Normal file
284
libraries/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Common\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Inflector as InflectorObject;
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
use Doctrine\Inflector\LanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
use InvalidArgumentException;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_unshift;
|
||||
use function array_values;
|
||||
use function sprintf;
|
||||
use function trigger_error;
|
||||
use const E_USER_DEPRECATED;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
class Inflector
|
||||
{
|
||||
/**
|
||||
* @var LanguageInflectorFactory|null
|
||||
*/
|
||||
private static $factory;
|
||||
|
||||
/** @var InflectorObject|null */
|
||||
private static $instance;
|
||||
|
||||
private static function getInstance() : InflectorObject
|
||||
{
|
||||
if (self::$factory === null) {
|
||||
self::$factory = self::createFactory();
|
||||
}
|
||||
|
||||
if (self::$instance === null) {
|
||||
self::$instance = self::$factory->build();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private static function createFactory() : LanguageInflectorFactory
|
||||
{
|
||||
return InflectorFactory::create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function tableize(string $word) : string
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return self::getInstance()->tableize($word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
|
||||
*/
|
||||
public static function classify(string $word) : string
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return self::getInstance()->classify($word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Camelizes a word. This uses the classify() method and turns the first character to lowercase.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function camelize(string $word) : string
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return self::getInstance()->camelize($word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uppercases words with configurable delimiters between words.
|
||||
*
|
||||
* Takes a string and capitalizes all of the words, like PHP's built-in
|
||||
* ucwords function. This extends that behavior, however, by allowing the
|
||||
* word delimiters to be configured, rather than only separating on
|
||||
* whitespace.
|
||||
*
|
||||
* Here is an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $string = 'top-o-the-morning to all_of_you!';
|
||||
* echo \Doctrine\Common\Inflector\Inflector::ucwords($string);
|
||||
* // Top-O-The-Morning To All_of_you!
|
||||
*
|
||||
* echo \Doctrine\Common\Inflector\Inflector::ucwords($string, '-_ ');
|
||||
* // Top-O-The-Morning To All_Of_You!
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param string $string The string to operate on.
|
||||
* @param string $delimiters A list of word separators.
|
||||
*
|
||||
* @return string The string with all delimiter-separated words capitalized.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please use the "ucwords" function instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return ucwords($string, $delimiters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears Inflectors inflected value caches, and resets the inflection
|
||||
* rules to the initial values.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function reset() : void
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
self::$factory = null;
|
||||
self::$instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds custom inflection $rules, of either 'plural' or 'singular' $type.
|
||||
*
|
||||
* ### Usage:
|
||||
*
|
||||
* {{{
|
||||
* Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables'));
|
||||
* Inflector::rules('plural', array(
|
||||
* 'rules' => array('/^(inflect)ors$/i' => '\1ables'),
|
||||
* 'uninflected' => array('dontinflectme'),
|
||||
* 'irregular' => array('red' => 'redlings')
|
||||
* ));
|
||||
* }}}
|
||||
*
|
||||
* @param string $type The type of inflection, either 'plural' or 'singular'
|
||||
* @param array<string,mixed>|iterable<string,mixed> $rules An array of rules to be added.
|
||||
* @param boolean $reset If true, will unset default inflections for all
|
||||
* new rules that are being defined in $rules.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function rules(string $type, iterable $rules, bool $reset = false) : void
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if (self::$factory === null) {
|
||||
self::$factory = self::createFactory();
|
||||
}
|
||||
|
||||
self::$instance = null;
|
||||
|
||||
switch ($type) {
|
||||
case 'singular':
|
||||
self::$factory->withSingularRules(self::buildRuleset($rules), $reset);
|
||||
break;
|
||||
case 'plural':
|
||||
self::$factory->withPluralRules(self::buildRuleset($rules), $reset);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('Cannot define custom inflection rules for type "%s".', $type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed>|iterable<string,mixed> $rules An array of rules to be added.
|
||||
*/
|
||||
private static function buildRuleset(iterable $rules) : Ruleset
|
||||
{
|
||||
$regular = [];
|
||||
$irregular = [];
|
||||
$uninflected = [];
|
||||
|
||||
foreach ($rules as $rule => $pattern) {
|
||||
if ( ! is_array($pattern)) {
|
||||
$regular[$rule] = $pattern;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($rule) {
|
||||
case 'uninflected':
|
||||
$uninflected = $pattern;
|
||||
break;
|
||||
case 'irregular':
|
||||
$irregular = $pattern;
|
||||
break;
|
||||
case 'rules':
|
||||
$regular = $pattern;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new Ruleset(
|
||||
new Transformations(...array_map(
|
||||
static function (string $pattern, string $replacement) : Transformation {
|
||||
return new Transformation(new Pattern($pattern), $replacement);
|
||||
},
|
||||
array_keys($regular),
|
||||
array_values($regular)
|
||||
)),
|
||||
new Patterns(...array_map(
|
||||
static function (string $pattern) : Pattern {
|
||||
return new Pattern($pattern);
|
||||
},
|
||||
$uninflected
|
||||
)),
|
||||
new Substitutions(...array_map(
|
||||
static function (string $word, string $to) : Substitution {
|
||||
return new Substitution(new Word($word), new Word($to));
|
||||
},
|
||||
array_keys($irregular),
|
||||
array_values($irregular)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a word in plural form.
|
||||
*
|
||||
* @param string $word The word in singular form.
|
||||
*
|
||||
* @return string The word in plural form.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function pluralize(string $word) : string
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return self::getInstance()->pluralize($word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a word in singular form.
|
||||
*
|
||||
* @param string $word The word in plural form.
|
||||
*
|
||||
* @return string The word in singular form.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function singularize(string $word) : string
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return self::getInstance()->singularize($word);
|
||||
}
|
||||
}
|
||||
24
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/CachedWordInflector.php
vendored
Normal file
24
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/CachedWordInflector.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
class CachedWordInflector implements WordInflector
|
||||
{
|
||||
/** @var WordInflector */
|
||||
private $wordInflector;
|
||||
|
||||
/** @var string[] */
|
||||
private $cache = [];
|
||||
|
||||
public function __construct(WordInflector $wordInflector)
|
||||
{
|
||||
$this->wordInflector = $wordInflector;
|
||||
}
|
||||
|
||||
public function inflect(string $word): string
|
||||
{
|
||||
return $this->cache[$word] ?? $this->cache[$word] = $this->wordInflector->inflect($word);
|
||||
}
|
||||
}
|
||||
66
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/GenericLanguageInflectorFactory.php
vendored
Normal file
66
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/GenericLanguageInflectorFactory.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
use function array_unshift;
|
||||
|
||||
abstract class GenericLanguageInflectorFactory implements LanguageInflectorFactory
|
||||
{
|
||||
/** @var Ruleset[] */
|
||||
private $singularRulesets = [];
|
||||
|
||||
/** @var Ruleset[] */
|
||||
private $pluralRulesets = [];
|
||||
|
||||
final public function __construct()
|
||||
{
|
||||
$this->singularRulesets[] = $this->getSingularRuleset();
|
||||
$this->pluralRulesets[] = $this->getPluralRuleset();
|
||||
}
|
||||
|
||||
final public function build(): Inflector
|
||||
{
|
||||
return new Inflector(
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
...$this->singularRulesets
|
||||
)),
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
...$this->pluralRulesets
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
final public function withSingularRules(?Ruleset $singularRules, bool $reset = false): LanguageInflectorFactory
|
||||
{
|
||||
if ($reset) {
|
||||
$this->singularRulesets = [];
|
||||
}
|
||||
|
||||
if ($singularRules instanceof Ruleset) {
|
||||
array_unshift($this->singularRulesets, $singularRules);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function withPluralRules(?Ruleset $pluralRules, bool $reset = false): LanguageInflectorFactory
|
||||
{
|
||||
if ($reset) {
|
||||
$this->pluralRulesets = [];
|
||||
}
|
||||
|
||||
if ($pluralRules instanceof Ruleset) {
|
||||
array_unshift($this->pluralRulesets, $pluralRules);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
abstract protected function getSingularRuleset(): Ruleset;
|
||||
|
||||
abstract protected function getPluralRuleset(): Ruleset;
|
||||
}
|
||||
507
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Inflector.php
vendored
Normal file
507
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Inflector.php
vendored
Normal file
@ -0,0 +1,507 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
use function chr;
|
||||
use function function_exists;
|
||||
use function lcfirst;
|
||||
use function mb_strtolower;
|
||||
use function ord;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use function strtr;
|
||||
use function trim;
|
||||
use function ucwords;
|
||||
|
||||
class Inflector
|
||||
{
|
||||
private const ACCENTED_CHARACTERS = [
|
||||
'À' => 'A',
|
||||
'Á' => 'A',
|
||||
'Â' => 'A',
|
||||
'Ã' => 'A',
|
||||
'Ä' => 'Ae',
|
||||
'Æ' => 'Ae',
|
||||
'Å' => 'Aa',
|
||||
'æ' => 'a',
|
||||
'Ç' => 'C',
|
||||
'È' => 'E',
|
||||
'É' => 'E',
|
||||
'Ê' => 'E',
|
||||
'Ë' => 'E',
|
||||
'Ì' => 'I',
|
||||
'Í' => 'I',
|
||||
'Î' => 'I',
|
||||
'Ï' => 'I',
|
||||
'Ñ' => 'N',
|
||||
'Ò' => 'O',
|
||||
'Ó' => 'O',
|
||||
'Ô' => 'O',
|
||||
'Õ' => 'O',
|
||||
'Ö' => 'Oe',
|
||||
'Ù' => 'U',
|
||||
'Ú' => 'U',
|
||||
'Û' => 'U',
|
||||
'Ü' => 'Ue',
|
||||
'Ý' => 'Y',
|
||||
'ß' => 'ss',
|
||||
'à' => 'a',
|
||||
'á' => 'a',
|
||||
'â' => 'a',
|
||||
'ã' => 'a',
|
||||
'ä' => 'ae',
|
||||
'å' => 'aa',
|
||||
'ç' => 'c',
|
||||
'è' => 'e',
|
||||
'é' => 'e',
|
||||
'ê' => 'e',
|
||||
'ë' => 'e',
|
||||
'ì' => 'i',
|
||||
'í' => 'i',
|
||||
'î' => 'i',
|
||||
'ï' => 'i',
|
||||
'ñ' => 'n',
|
||||
'ò' => 'o',
|
||||
'ó' => 'o',
|
||||
'ô' => 'o',
|
||||
'õ' => 'o',
|
||||
'ö' => 'oe',
|
||||
'ù' => 'u',
|
||||
'ú' => 'u',
|
||||
'û' => 'u',
|
||||
'ü' => 'ue',
|
||||
'ý' => 'y',
|
||||
'ÿ' => 'y',
|
||||
'Ā' => 'A',
|
||||
'ā' => 'a',
|
||||
'Ă' => 'A',
|
||||
'ă' => 'a',
|
||||
'Ą' => 'A',
|
||||
'ą' => 'a',
|
||||
'Ć' => 'C',
|
||||
'ć' => 'c',
|
||||
'Ĉ' => 'C',
|
||||
'ĉ' => 'c',
|
||||
'Ċ' => 'C',
|
||||
'ċ' => 'c',
|
||||
'Č' => 'C',
|
||||
'č' => 'c',
|
||||
'Ď' => 'D',
|
||||
'ď' => 'd',
|
||||
'Đ' => 'D',
|
||||
'đ' => 'd',
|
||||
'Ē' => 'E',
|
||||
'ē' => 'e',
|
||||
'Ĕ' => 'E',
|
||||
'ĕ' => 'e',
|
||||
'Ė' => 'E',
|
||||
'ė' => 'e',
|
||||
'Ę' => 'E',
|
||||
'ę' => 'e',
|
||||
'Ě' => 'E',
|
||||
'ě' => 'e',
|
||||
'Ĝ' => 'G',
|
||||
'ĝ' => 'g',
|
||||
'Ğ' => 'G',
|
||||
'ğ' => 'g',
|
||||
'Ġ' => 'G',
|
||||
'ġ' => 'g',
|
||||
'Ģ' => 'G',
|
||||
'ģ' => 'g',
|
||||
'Ĥ' => 'H',
|
||||
'ĥ' => 'h',
|
||||
'Ħ' => 'H',
|
||||
'ħ' => 'h',
|
||||
'Ĩ' => 'I',
|
||||
'ĩ' => 'i',
|
||||
'Ī' => 'I',
|
||||
'ī' => 'i',
|
||||
'Ĭ' => 'I',
|
||||
'ĭ' => 'i',
|
||||
'Į' => 'I',
|
||||
'į' => 'i',
|
||||
'İ' => 'I',
|
||||
'ı' => 'i',
|
||||
'IJ' => 'IJ',
|
||||
'ij' => 'ij',
|
||||
'Ĵ' => 'J',
|
||||
'ĵ' => 'j',
|
||||
'Ķ' => 'K',
|
||||
'ķ' => 'k',
|
||||
'ĸ' => 'k',
|
||||
'Ĺ' => 'L',
|
||||
'ĺ' => 'l',
|
||||
'Ļ' => 'L',
|
||||
'ļ' => 'l',
|
||||
'Ľ' => 'L',
|
||||
'ľ' => 'l',
|
||||
'Ŀ' => 'L',
|
||||
'ŀ' => 'l',
|
||||
'Ł' => 'L',
|
||||
'ł' => 'l',
|
||||
'Ń' => 'N',
|
||||
'ń' => 'n',
|
||||
'Ņ' => 'N',
|
||||
'ņ' => 'n',
|
||||
'Ň' => 'N',
|
||||
'ň' => 'n',
|
||||
'ʼn' => 'N',
|
||||
'Ŋ' => 'n',
|
||||
'ŋ' => 'N',
|
||||
'Ō' => 'O',
|
||||
'ō' => 'o',
|
||||
'Ŏ' => 'O',
|
||||
'ŏ' => 'o',
|
||||
'Ő' => 'O',
|
||||
'ő' => 'o',
|
||||
'Œ' => 'OE',
|
||||
'œ' => 'oe',
|
||||
'Ø' => 'O',
|
||||
'ø' => 'o',
|
||||
'Ŕ' => 'R',
|
||||
'ŕ' => 'r',
|
||||
'Ŗ' => 'R',
|
||||
'ŗ' => 'r',
|
||||
'Ř' => 'R',
|
||||
'ř' => 'r',
|
||||
'Ś' => 'S',
|
||||
'ś' => 's',
|
||||
'Ŝ' => 'S',
|
||||
'ŝ' => 's',
|
||||
'Ş' => 'S',
|
||||
'ş' => 's',
|
||||
'Š' => 'S',
|
||||
'š' => 's',
|
||||
'Ţ' => 'T',
|
||||
'ţ' => 't',
|
||||
'Ť' => 'T',
|
||||
'ť' => 't',
|
||||
'Ŧ' => 'T',
|
||||
'ŧ' => 't',
|
||||
'Ũ' => 'U',
|
||||
'ũ' => 'u',
|
||||
'Ū' => 'U',
|
||||
'ū' => 'u',
|
||||
'Ŭ' => 'U',
|
||||
'ŭ' => 'u',
|
||||
'Ů' => 'U',
|
||||
'ů' => 'u',
|
||||
'Ű' => 'U',
|
||||
'ű' => 'u',
|
||||
'Ų' => 'U',
|
||||
'ų' => 'u',
|
||||
'Ŵ' => 'W',
|
||||
'ŵ' => 'w',
|
||||
'Ŷ' => 'Y',
|
||||
'ŷ' => 'y',
|
||||
'Ÿ' => 'Y',
|
||||
'Ź' => 'Z',
|
||||
'ź' => 'z',
|
||||
'Ż' => 'Z',
|
||||
'ż' => 'z',
|
||||
'Ž' => 'Z',
|
||||
'ž' => 'z',
|
||||
'ſ' => 's',
|
||||
'€' => 'E',
|
||||
'£' => '',
|
||||
];
|
||||
|
||||
/** @var WordInflector */
|
||||
private $singularizer;
|
||||
|
||||
/** @var WordInflector */
|
||||
private $pluralizer;
|
||||
|
||||
public function __construct(WordInflector $singularizer, WordInflector $pluralizer)
|
||||
{
|
||||
$this->singularizer = $singularizer;
|
||||
$this->pluralizer = $pluralizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
|
||||
*/
|
||||
public function tableize(string $word): string
|
||||
{
|
||||
$tableized = preg_replace('~(?<=\\w)([A-Z])~u', '_$1', $word);
|
||||
|
||||
if ($tableized === null) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'preg_replace returned null for value "%s"',
|
||||
$word
|
||||
));
|
||||
}
|
||||
|
||||
return mb_strtolower($tableized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
|
||||
*/
|
||||
public function classify(string $word): string
|
||||
{
|
||||
return str_replace([' ', '_', '-'], '', ucwords($word, ' _-'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Camelizes a word. This uses the classify() method and turns the first character to lowercase.
|
||||
*/
|
||||
public function camelize(string $word): string
|
||||
{
|
||||
return lcfirst($this->classify($word));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uppercases words with configurable delimiters between words.
|
||||
*
|
||||
* Takes a string and capitalizes all of the words, like PHP's built-in
|
||||
* ucwords function. This extends that behavior, however, by allowing the
|
||||
* word delimiters to be configured, rather than only separating on
|
||||
* whitespace.
|
||||
*
|
||||
* Here is an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $string = 'top-o-the-morning to all_of_you!';
|
||||
* echo $inflector->capitalize($string);
|
||||
* // Top-O-The-Morning To All_of_you!
|
||||
*
|
||||
* echo $inflector->capitalize($string, '-_ ');
|
||||
* // Top-O-The-Morning To All_Of_You!
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param string $string The string to operate on.
|
||||
* @param string $delimiters A list of word separators.
|
||||
*
|
||||
* @return string The string with all delimiter-separated words capitalized.
|
||||
*/
|
||||
public function capitalize(string $string, string $delimiters = " \n\t\r\0\x0B-"): string
|
||||
{
|
||||
return ucwords($string, $delimiters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given string seems like it has utf8 characters in it.
|
||||
*
|
||||
* @param string $string The string to check for utf8 characters in.
|
||||
*/
|
||||
public function seemsUtf8(string $string): bool
|
||||
{
|
||||
for ($i = 0; $i < strlen($string); $i++) {
|
||||
if (ord($string[$i]) < 0x80) {
|
||||
continue; // 0bbbbbbb
|
||||
}
|
||||
|
||||
if ((ord($string[$i]) & 0xE0) === 0xC0) {
|
||||
$n = 1; // 110bbbbb
|
||||
} elseif ((ord($string[$i]) & 0xF0) === 0xE0) {
|
||||
$n = 2; // 1110bbbb
|
||||
} elseif ((ord($string[$i]) & 0xF8) === 0xF0) {
|
||||
$n = 3; // 11110bbb
|
||||
} elseif ((ord($string[$i]) & 0xFC) === 0xF8) {
|
||||
$n = 4; // 111110bb
|
||||
} elseif ((ord($string[$i]) & 0xFE) === 0xFC) {
|
||||
$n = 5; // 1111110b
|
||||
} else {
|
||||
return false; // Does not match any model
|
||||
}
|
||||
|
||||
for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ?
|
||||
if (++$i === strlen($string) || ((ord($string[$i]) & 0xC0) !== 0x80)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any illegal characters, accents, etc.
|
||||
*
|
||||
* @param string $string String to unaccent
|
||||
*
|
||||
* @return string Unaccented string
|
||||
*/
|
||||
public function unaccent(string $string): string
|
||||
{
|
||||
if (preg_match('/[\x80-\xff]/', $string) === false) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
if ($this->seemsUtf8($string)) {
|
||||
$string = strtr($string, self::ACCENTED_CHARACTERS);
|
||||
} else {
|
||||
$characters = [];
|
||||
|
||||
// Assume ISO-8859-1 if not UTF-8
|
||||
$characters['in'] =
|
||||
chr(128)
|
||||
. chr(131)
|
||||
. chr(138)
|
||||
. chr(142)
|
||||
. chr(154)
|
||||
. chr(158)
|
||||
. chr(159)
|
||||
. chr(162)
|
||||
. chr(165)
|
||||
. chr(181)
|
||||
. chr(192)
|
||||
. chr(193)
|
||||
. chr(194)
|
||||
. chr(195)
|
||||
. chr(196)
|
||||
. chr(197)
|
||||
. chr(199)
|
||||
. chr(200)
|
||||
. chr(201)
|
||||
. chr(202)
|
||||
. chr(203)
|
||||
. chr(204)
|
||||
. chr(205)
|
||||
. chr(206)
|
||||
. chr(207)
|
||||
. chr(209)
|
||||
. chr(210)
|
||||
. chr(211)
|
||||
. chr(212)
|
||||
. chr(213)
|
||||
. chr(214)
|
||||
. chr(216)
|
||||
. chr(217)
|
||||
. chr(218)
|
||||
. chr(219)
|
||||
. chr(220)
|
||||
. chr(221)
|
||||
. chr(224)
|
||||
. chr(225)
|
||||
. chr(226)
|
||||
. chr(227)
|
||||
. chr(228)
|
||||
. chr(229)
|
||||
. chr(231)
|
||||
. chr(232)
|
||||
. chr(233)
|
||||
. chr(234)
|
||||
. chr(235)
|
||||
. chr(236)
|
||||
. chr(237)
|
||||
. chr(238)
|
||||
. chr(239)
|
||||
. chr(241)
|
||||
. chr(242)
|
||||
. chr(243)
|
||||
. chr(244)
|
||||
. chr(245)
|
||||
. chr(246)
|
||||
. chr(248)
|
||||
. chr(249)
|
||||
. chr(250)
|
||||
. chr(251)
|
||||
. chr(252)
|
||||
. chr(253)
|
||||
. chr(255);
|
||||
|
||||
$characters['out'] = 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy';
|
||||
|
||||
$string = strtr($string, $characters['in'], $characters['out']);
|
||||
|
||||
$doubleChars = [];
|
||||
|
||||
$doubleChars['in'] = [
|
||||
chr(140),
|
||||
chr(156),
|
||||
chr(198),
|
||||
chr(208),
|
||||
chr(222),
|
||||
chr(223),
|
||||
chr(230),
|
||||
chr(240),
|
||||
chr(254),
|
||||
];
|
||||
|
||||
$doubleChars['out'] = ['OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'];
|
||||
|
||||
$string = str_replace($doubleChars['in'], $doubleChars['out'], $string);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any passed string to a url friendly string.
|
||||
* Converts 'My first blog post' to 'my-first-blog-post'
|
||||
*
|
||||
* @param string $string String to urlize.
|
||||
*
|
||||
* @return string Urlized string.
|
||||
*/
|
||||
public function urlize(string $string): string
|
||||
{
|
||||
// Remove all non url friendly characters with the unaccent function
|
||||
$unaccented = $this->unaccent($string);
|
||||
|
||||
if (function_exists('mb_strtolower')) {
|
||||
$lowered = mb_strtolower($unaccented);
|
||||
} else {
|
||||
$lowered = strtolower($unaccented);
|
||||
}
|
||||
|
||||
$replacements = [
|
||||
'/\W/' => ' ',
|
||||
'/([A-Z]+)([A-Z][a-z])/' => '\1_\2',
|
||||
'/([a-z\d])([A-Z])/' => '\1_\2',
|
||||
'/[^A-Z^a-z^0-9^\/]+/' => '-',
|
||||
];
|
||||
|
||||
$urlized = $lowered;
|
||||
|
||||
foreach ($replacements as $pattern => $replacement) {
|
||||
$replaced = preg_replace($pattern, $replacement, $urlized);
|
||||
|
||||
if ($replaced === null) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'preg_replace returned null for value "%s"',
|
||||
$urlized
|
||||
));
|
||||
}
|
||||
|
||||
$urlized = $replaced;
|
||||
}
|
||||
|
||||
return trim($urlized, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a word in singular form.
|
||||
*
|
||||
* @param string $word The word in plural form.
|
||||
*
|
||||
* @return string The word in singular form.
|
||||
*/
|
||||
public function singularize(string $word): string
|
||||
{
|
||||
return $this->singularizer->inflect($word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a word in plural form.
|
||||
*
|
||||
* @param string $word The word in singular form.
|
||||
*
|
||||
* @return string The word in plural form.
|
||||
*/
|
||||
public function pluralize(string $word): string
|
||||
{
|
||||
return $this->pluralizer->inflect($word);
|
||||
}
|
||||
}
|
||||
52
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/InflectorFactory.php
vendored
Normal file
52
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/InflectorFactory.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Rules\English;
|
||||
use Doctrine\Inflector\Rules\French;
|
||||
use Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
use Doctrine\Inflector\Rules\Portuguese;
|
||||
use Doctrine\Inflector\Rules\Spanish;
|
||||
use Doctrine\Inflector\Rules\Turkish;
|
||||
use InvalidArgumentException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class InflectorFactory
|
||||
{
|
||||
public static function create(): LanguageInflectorFactory
|
||||
{
|
||||
return self::createForLanguage(Language::ENGLISH);
|
||||
}
|
||||
|
||||
public static function createForLanguage(string $language): LanguageInflectorFactory
|
||||
{
|
||||
switch ($language) {
|
||||
case Language::ENGLISH:
|
||||
return new English\InflectorFactory();
|
||||
|
||||
case Language::FRENCH:
|
||||
return new French\InflectorFactory();
|
||||
|
||||
case Language::NORWEGIAN_BOKMAL:
|
||||
return new NorwegianBokmal\InflectorFactory();
|
||||
|
||||
case Language::PORTUGUESE:
|
||||
return new Portuguese\InflectorFactory();
|
||||
|
||||
case Language::SPANISH:
|
||||
return new Spanish\InflectorFactory();
|
||||
|
||||
case Language::TURKISH:
|
||||
return new Turkish\InflectorFactory();
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Language "%s" is not supported.',
|
||||
$language
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
19
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Language.php
vendored
Normal file
19
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Language.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
final class Language
|
||||
{
|
||||
public const ENGLISH = 'english';
|
||||
public const FRENCH = 'french';
|
||||
public const NORWEGIAN_BOKMAL = 'norwegian-bokmal';
|
||||
public const PORTUGUESE = 'portuguese';
|
||||
public const SPANISH = 'spanish';
|
||||
public const TURKISH = 'turkish';
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
33
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/LanguageInflectorFactory.php
vendored
Normal file
33
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/LanguageInflectorFactory.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
interface LanguageInflectorFactory
|
||||
{
|
||||
/**
|
||||
* Applies custom rules for singularisation
|
||||
*
|
||||
* @param bool $reset If true, will unset default inflections for all new rules
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withSingularRules(?Ruleset $singularRules, bool $reset = false): self;
|
||||
|
||||
/**
|
||||
* Applies custom rules for pluralisation
|
||||
*
|
||||
* @param bool $reset If true, will unset default inflections for all new rules
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withPluralRules(?Ruleset $pluralRules, bool $reset = false): self;
|
||||
|
||||
/**
|
||||
* Builds the inflector instance with all applicable rules
|
||||
*/
|
||||
public function build(): Inflector;
|
||||
}
|
||||
13
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/NoopWordInflector.php
vendored
Normal file
13
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/NoopWordInflector.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
class NoopWordInflector implements WordInflector
|
||||
{
|
||||
public function inflect(string $word): string
|
||||
{
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
182
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Inflectible.php
vendored
Normal file
182
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Inflectible.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('(s)tatuses$'), '\1\2tatus');
|
||||
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatus');
|
||||
yield new Transformation(new Pattern('(c)ampus$'), '\1\2ampus');
|
||||
yield new Transformation(new Pattern('^(.*)(menu)s$'), '\1\2');
|
||||
yield new Transformation(new Pattern('(quiz)zes$'), '\\1');
|
||||
yield new Transformation(new Pattern('(matr)ices$'), '\1ix');
|
||||
yield new Transformation(new Pattern('(vert|ind)ices$'), '\1ex');
|
||||
yield new Transformation(new Pattern('^(ox)en'), '\1');
|
||||
yield new Transformation(new Pattern('(alias)(es)*$'), '\1');
|
||||
yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)oes$'), '\1o');
|
||||
yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$'), '\1us');
|
||||
yield new Transformation(new Pattern('([ftw]ax)es'), '\1');
|
||||
yield new Transformation(new Pattern('(analys|ax|cris|test|thes)es$'), '\1is');
|
||||
yield new Transformation(new Pattern('(shoe|slave)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(o)es$'), '\1');
|
||||
yield new Transformation(new Pattern('ouses$'), 'ouse');
|
||||
yield new Transformation(new Pattern('([^a])uses$'), '\1us');
|
||||
yield new Transformation(new Pattern('([m|l])ice$'), '\1ouse');
|
||||
yield new Transformation(new Pattern('(x|ch|ss|sh)es$'), '\1');
|
||||
yield new Transformation(new Pattern('(m)ovies$'), '\1\2ovie');
|
||||
yield new Transformation(new Pattern('(s)eries$'), '\1\2eries');
|
||||
yield new Transformation(new Pattern('([^aeiouy]|qu)ies$'), '\1y');
|
||||
yield new Transformation(new Pattern('([lr])ves$'), '\1f');
|
||||
yield new Transformation(new Pattern('(tive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(hive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(drive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(dive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(olive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('([^fo])ves$'), '\1fe');
|
||||
yield new Transformation(new Pattern('(^analy)ses$'), '\1sis');
|
||||
yield new Transformation(new Pattern('(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$'), '\1\2sis');
|
||||
yield new Transformation(new Pattern('(tax)a$'), '\1on');
|
||||
yield new Transformation(new Pattern('(c)riteria$'), '\1riterion');
|
||||
yield new Transformation(new Pattern('([ti])a$'), '\1um');
|
||||
yield new Transformation(new Pattern('(p)eople$'), '\1\2erson');
|
||||
yield new Transformation(new Pattern('(m)en$'), '\1an');
|
||||
yield new Transformation(new Pattern('(c)hildren$'), '\1\2hild');
|
||||
yield new Transformation(new Pattern('(f)eet$'), '\1oot');
|
||||
yield new Transformation(new Pattern('(n)ews$'), '\1\2ews');
|
||||
yield new Transformation(new Pattern('eaus$'), 'eau');
|
||||
yield new Transformation(new Pattern('s$'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatuses');
|
||||
yield new Transformation(new Pattern('(quiz)$'), '\1zes');
|
||||
yield new Transformation(new Pattern('^(ox)$'), '\1\2en');
|
||||
yield new Transformation(new Pattern('([m|l])ouse$'), '\1ice');
|
||||
yield new Transformation(new Pattern('(matr|vert|ind)(ix|ex)$'), '\1ices');
|
||||
yield new Transformation(new Pattern('(x|ch|ss|sh)$'), '\1es');
|
||||
yield new Transformation(new Pattern('([^aeiouy]|qu)y$'), '\1ies');
|
||||
yield new Transformation(new Pattern('(hive|gulf)$'), '\1s');
|
||||
yield new Transformation(new Pattern('(?:([^f])fe|([lr])f)$'), '\1\2ves');
|
||||
yield new Transformation(new Pattern('sis$'), 'ses');
|
||||
yield new Transformation(new Pattern('([ti])um$'), '\1a');
|
||||
yield new Transformation(new Pattern('(tax)on$'), '\1a');
|
||||
yield new Transformation(new Pattern('(c)riterion$'), '\1riteria');
|
||||
yield new Transformation(new Pattern('(p)erson$'), '\1eople');
|
||||
yield new Transformation(new Pattern('(m)an$'), '\1en');
|
||||
yield new Transformation(new Pattern('(c)hild$'), '\1hildren');
|
||||
yield new Transformation(new Pattern('(f)oot$'), '\1eet');
|
||||
yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)o$'), '\1\2oes');
|
||||
yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$'), '\1i');
|
||||
yield new Transformation(new Pattern('us$'), 'uses');
|
||||
yield new Transformation(new Pattern('(alias)$'), '\1es');
|
||||
yield new Transformation(new Pattern('(analys|ax|cris|test|thes)is$'), '\1es');
|
||||
yield new Transformation(new Pattern('s$'), 's');
|
||||
yield new Transformation(new Pattern('^$'), '');
|
||||
yield new Transformation(new Pattern('$'), 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular(): iterable
|
||||
{
|
||||
yield new Substitution(new Word('atlas'), new Word('atlases'));
|
||||
yield new Substitution(new Word('axe'), new Word('axes'));
|
||||
yield new Substitution(new Word('beef'), new Word('beefs'));
|
||||
yield new Substitution(new Word('brother'), new Word('brothers'));
|
||||
yield new Substitution(new Word('cafe'), new Word('cafes'));
|
||||
yield new Substitution(new Word('chateau'), new Word('chateaux'));
|
||||
yield new Substitution(new Word('niveau'), new Word('niveaux'));
|
||||
yield new Substitution(new Word('child'), new Word('children'));
|
||||
yield new Substitution(new Word('canvas'), new Word('canvases'));
|
||||
yield new Substitution(new Word('cookie'), new Word('cookies'));
|
||||
yield new Substitution(new Word('corpus'), new Word('corpuses'));
|
||||
yield new Substitution(new Word('cow'), new Word('cows'));
|
||||
yield new Substitution(new Word('criterion'), new Word('criteria'));
|
||||
yield new Substitution(new Word('curriculum'), new Word('curricula'));
|
||||
yield new Substitution(new Word('demo'), new Word('demos'));
|
||||
yield new Substitution(new Word('domino'), new Word('dominoes'));
|
||||
yield new Substitution(new Word('echo'), new Word('echoes'));
|
||||
yield new Substitution(new Word('foot'), new Word('feet'));
|
||||
yield new Substitution(new Word('fungus'), new Word('fungi'));
|
||||
yield new Substitution(new Word('ganglion'), new Word('ganglions'));
|
||||
yield new Substitution(new Word('gas'), new Word('gases'));
|
||||
yield new Substitution(new Word('genie'), new Word('genies'));
|
||||
yield new Substitution(new Word('genus'), new Word('genera'));
|
||||
yield new Substitution(new Word('goose'), new Word('geese'));
|
||||
yield new Substitution(new Word('graffito'), new Word('graffiti'));
|
||||
yield new Substitution(new Word('hippopotamus'), new Word('hippopotami'));
|
||||
yield new Substitution(new Word('hoof'), new Word('hoofs'));
|
||||
yield new Substitution(new Word('human'), new Word('humans'));
|
||||
yield new Substitution(new Word('iris'), new Word('irises'));
|
||||
yield new Substitution(new Word('larva'), new Word('larvae'));
|
||||
yield new Substitution(new Word('leaf'), new Word('leaves'));
|
||||
yield new Substitution(new Word('lens'), new Word('lenses'));
|
||||
yield new Substitution(new Word('loaf'), new Word('loaves'));
|
||||
yield new Substitution(new Word('man'), new Word('men'));
|
||||
yield new Substitution(new Word('medium'), new Word('media'));
|
||||
yield new Substitution(new Word('memorandum'), new Word('memoranda'));
|
||||
yield new Substitution(new Word('money'), new Word('monies'));
|
||||
yield new Substitution(new Word('mongoose'), new Word('mongooses'));
|
||||
yield new Substitution(new Word('motto'), new Word('mottoes'));
|
||||
yield new Substitution(new Word('move'), new Word('moves'));
|
||||
yield new Substitution(new Word('mythos'), new Word('mythoi'));
|
||||
yield new Substitution(new Word('niche'), new Word('niches'));
|
||||
yield new Substitution(new Word('nucleus'), new Word('nuclei'));
|
||||
yield new Substitution(new Word('numen'), new Word('numina'));
|
||||
yield new Substitution(new Word('occiput'), new Word('occiputs'));
|
||||
yield new Substitution(new Word('octopus'), new Word('octopuses'));
|
||||
yield new Substitution(new Word('opus'), new Word('opuses'));
|
||||
yield new Substitution(new Word('ox'), new Word('oxen'));
|
||||
yield new Substitution(new Word('passerby'), new Word('passersby'));
|
||||
yield new Substitution(new Word('penis'), new Word('penises'));
|
||||
yield new Substitution(new Word('person'), new Word('people'));
|
||||
yield new Substitution(new Word('plateau'), new Word('plateaux'));
|
||||
yield new Substitution(new Word('runner-up'), new Word('runners-up'));
|
||||
yield new Substitution(new Word('safe'), new Word('safes'));
|
||||
yield new Substitution(new Word('sex'), new Word('sexes'));
|
||||
yield new Substitution(new Word('soliloquy'), new Word('soliloquies'));
|
||||
yield new Substitution(new Word('son-in-law'), new Word('sons-in-law'));
|
||||
yield new Substitution(new Word('syllabus'), new Word('syllabi'));
|
||||
yield new Substitution(new Word('testis'), new Word('testes'));
|
||||
yield new Substitution(new Word('thief'), new Word('thieves'));
|
||||
yield new Substitution(new Word('tooth'), new Word('teeth'));
|
||||
yield new Substitution(new Word('tornado'), new Word('tornadoes'));
|
||||
yield new Substitution(new Word('trilby'), new Word('trilbys'));
|
||||
yield new Substitution(new Word('turf'), new Word('turfs'));
|
||||
yield new Substitution(new Word('valve'), new Word('valves'));
|
||||
yield new Substitution(new Word('volcano'), new Word('volcanoes'));
|
||||
yield new Substitution(new Word('abuse'), new Word('abuses'));
|
||||
yield new Substitution(new Word('avalanche'), new Word('avalanches'));
|
||||
yield new Substitution(new Word('cache'), new Word('caches'));
|
||||
yield new Substitution(new Word('criterion'), new Word('criteria'));
|
||||
yield new Substitution(new Word('curve'), new Word('curves'));
|
||||
yield new Substitution(new Word('emphasis'), new Word('emphases'));
|
||||
yield new Substitution(new Word('foe'), new Word('foes'));
|
||||
yield new Substitution(new Word('grave'), new Word('graves'));
|
||||
yield new Substitution(new Word('hoax'), new Word('hoaxes'));
|
||||
yield new Substitution(new Word('medium'), new Word('media'));
|
||||
yield new Substitution(new Word('neurosis'), new Word('neuroses'));
|
||||
yield new Substitution(new Word('save'), new Word('saves'));
|
||||
yield new Substitution(new Word('wave'), new Word('waves'));
|
||||
yield new Substitution(new Word('oasis'), new Word('oases'));
|
||||
yield new Substitution(new Word('valve'), new Word('valves'));
|
||||
yield new Substitution(new Word('zombie'), new Word('zombies'));
|
||||
}
|
||||
}
|
||||
21
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/InflectorFactory.php
vendored
Normal file
21
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/InflectorFactory.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset(): Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset(): Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
31
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Rules.php
vendored
Normal file
31
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Rules.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset(): Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset(): Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
193
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Uninflected.php
vendored
Normal file
193
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Uninflected.php
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular(): iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
|
||||
yield new Pattern('.*ss');
|
||||
yield new Pattern('clothes');
|
||||
yield new Pattern('data');
|
||||
yield new Pattern('fascia');
|
||||
yield new Pattern('fuchsia');
|
||||
yield new Pattern('galleria');
|
||||
yield new Pattern('mafia');
|
||||
yield new Pattern('militia');
|
||||
yield new Pattern('pants');
|
||||
yield new Pattern('petunia');
|
||||
yield new Pattern('sepia');
|
||||
yield new Pattern('trivia');
|
||||
yield new Pattern('utopia');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural(): iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
|
||||
yield new Pattern('people');
|
||||
yield new Pattern('trivia');
|
||||
yield new Pattern('\w+ware$');
|
||||
yield new Pattern('media');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault(): iterable
|
||||
{
|
||||
yield new Pattern('\w+media');
|
||||
yield new Pattern('advice');
|
||||
yield new Pattern('aircraft');
|
||||
yield new Pattern('amoyese');
|
||||
yield new Pattern('art');
|
||||
yield new Pattern('audio');
|
||||
yield new Pattern('baggage');
|
||||
yield new Pattern('bison');
|
||||
yield new Pattern('borghese');
|
||||
yield new Pattern('bream');
|
||||
yield new Pattern('breeches');
|
||||
yield new Pattern('britches');
|
||||
yield new Pattern('buffalo');
|
||||
yield new Pattern('butter');
|
||||
yield new Pattern('cantus');
|
||||
yield new Pattern('carp');
|
||||
yield new Pattern('chassis');
|
||||
yield new Pattern('clippers');
|
||||
yield new Pattern('clothing');
|
||||
yield new Pattern('coal');
|
||||
yield new Pattern('cod');
|
||||
yield new Pattern('coitus');
|
||||
yield new Pattern('compensation');
|
||||
yield new Pattern('congoese');
|
||||
yield new Pattern('contretemps');
|
||||
yield new Pattern('coreopsis');
|
||||
yield new Pattern('corps');
|
||||
yield new Pattern('cotton');
|
||||
yield new Pattern('data');
|
||||
yield new Pattern('debris');
|
||||
yield new Pattern('deer');
|
||||
yield new Pattern('diabetes');
|
||||
yield new Pattern('djinn');
|
||||
yield new Pattern('education');
|
||||
yield new Pattern('eland');
|
||||
yield new Pattern('elk');
|
||||
yield new Pattern('emoji');
|
||||
yield new Pattern('equipment');
|
||||
yield new Pattern('evidence');
|
||||
yield new Pattern('faroese');
|
||||
yield new Pattern('feedback');
|
||||
yield new Pattern('fish');
|
||||
yield new Pattern('flounder');
|
||||
yield new Pattern('flour');
|
||||
yield new Pattern('foochowese');
|
||||
yield new Pattern('food');
|
||||
yield new Pattern('furniture');
|
||||
yield new Pattern('gallows');
|
||||
yield new Pattern('genevese');
|
||||
yield new Pattern('genoese');
|
||||
yield new Pattern('gilbertese');
|
||||
yield new Pattern('gold');
|
||||
yield new Pattern('headquarters');
|
||||
yield new Pattern('herpes');
|
||||
yield new Pattern('hijinks');
|
||||
yield new Pattern('homework');
|
||||
yield new Pattern('hottentotese');
|
||||
yield new Pattern('impatience');
|
||||
yield new Pattern('information');
|
||||
yield new Pattern('innings');
|
||||
yield new Pattern('jackanapes');
|
||||
yield new Pattern('jeans');
|
||||
yield new Pattern('jedi');
|
||||
yield new Pattern('kiplingese');
|
||||
yield new Pattern('knowledge');
|
||||
yield new Pattern('kongoese');
|
||||
yield new Pattern('leather');
|
||||
yield new Pattern('love');
|
||||
yield new Pattern('lucchese');
|
||||
yield new Pattern('luggage');
|
||||
yield new Pattern('mackerel');
|
||||
yield new Pattern('Maltese');
|
||||
yield new Pattern('management');
|
||||
yield new Pattern('metadata');
|
||||
yield new Pattern('mews');
|
||||
yield new Pattern('money');
|
||||
yield new Pattern('moose');
|
||||
yield new Pattern('mumps');
|
||||
yield new Pattern('music');
|
||||
yield new Pattern('nankingese');
|
||||
yield new Pattern('news');
|
||||
yield new Pattern('nexus');
|
||||
yield new Pattern('niasese');
|
||||
yield new Pattern('nutrition');
|
||||
yield new Pattern('offspring');
|
||||
yield new Pattern('oil');
|
||||
yield new Pattern('patience');
|
||||
yield new Pattern('pekingese');
|
||||
yield new Pattern('piedmontese');
|
||||
yield new Pattern('pincers');
|
||||
yield new Pattern('pistoiese');
|
||||
yield new Pattern('plankton');
|
||||
yield new Pattern('pliers');
|
||||
yield new Pattern('pokemon');
|
||||
yield new Pattern('police');
|
||||
yield new Pattern('polish');
|
||||
yield new Pattern('portuguese');
|
||||
yield new Pattern('proceedings');
|
||||
yield new Pattern('progress');
|
||||
yield new Pattern('rabies');
|
||||
yield new Pattern('rain');
|
||||
yield new Pattern('research');
|
||||
yield new Pattern('rhinoceros');
|
||||
yield new Pattern('rice');
|
||||
yield new Pattern('salmon');
|
||||
yield new Pattern('sand');
|
||||
yield new Pattern('sarawakese');
|
||||
yield new Pattern('scissors');
|
||||
yield new Pattern('sea[- ]bass');
|
||||
yield new Pattern('series');
|
||||
yield new Pattern('shavese');
|
||||
yield new Pattern('shears');
|
||||
yield new Pattern('sheep');
|
||||
yield new Pattern('siemens');
|
||||
yield new Pattern('silk');
|
||||
yield new Pattern('sms');
|
||||
yield new Pattern('soap');
|
||||
yield new Pattern('social media');
|
||||
yield new Pattern('spam');
|
||||
yield new Pattern('species');
|
||||
yield new Pattern('staff');
|
||||
yield new Pattern('sugar');
|
||||
yield new Pattern('swine');
|
||||
yield new Pattern('talent');
|
||||
yield new Pattern('toothpaste');
|
||||
yield new Pattern('traffic');
|
||||
yield new Pattern('travel');
|
||||
yield new Pattern('trousers');
|
||||
yield new Pattern('trout');
|
||||
yield new Pattern('tuna');
|
||||
yield new Pattern('us');
|
||||
yield new Pattern('vermontese');
|
||||
yield new Pattern('vinegar');
|
||||
yield new Pattern('weather');
|
||||
yield new Pattern('wenchowese');
|
||||
yield new Pattern('wheat');
|
||||
yield new Pattern('whiting');
|
||||
yield new Pattern('wildebeest');
|
||||
yield new Pattern('wood');
|
||||
yield new Pattern('wool');
|
||||
yield new Pattern('yengeese');
|
||||
}
|
||||
}
|
||||
49
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Inflectible.php
vendored
Normal file
49
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Inflectible.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\1ail');
|
||||
yield new Transformation(new Pattern('/ails$/'), 'ail');
|
||||
yield new Transformation(new Pattern('/(journ|chev)aux$/'), '\1al');
|
||||
yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/'), '\1');
|
||||
yield new Transformation(new Pattern('/s$/'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/(s|x|z)$/'), '\1');
|
||||
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/'), '\1aux');
|
||||
yield new Transformation(new Pattern('/ail$/'), 'ails');
|
||||
yield new Transformation(new Pattern('/al$/'), 'aux');
|
||||
yield new Transformation(new Pattern('/(bleu|émeu|landau|lieu|pneu|sarrau)$/'), '\1s');
|
||||
yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)$/'), '\1x');
|
||||
yield new Transformation(new Pattern('/$/'), 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular(): iterable
|
||||
{
|
||||
yield new Substitution(new Word('monsieur'), new Word('messieurs'));
|
||||
yield new Substitution(new Word('madame'), new Word('mesdames'));
|
||||
yield new Substitution(new Word('mademoiselle'), new Word('mesdemoiselles'));
|
||||
}
|
||||
}
|
||||
21
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/InflectorFactory.php
vendored
Normal file
21
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/InflectorFactory.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset(): Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset(): Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
31
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Rules.php
vendored
Normal file
31
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Rules.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset(): Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset(): Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
34
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Uninflected.php
vendored
Normal file
34
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Uninflected.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular(): iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural(): iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault(): iterable
|
||||
{
|
||||
yield new Pattern('');
|
||||
}
|
||||
}
|
||||
40
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Inflectible.php
vendored
Normal file
40
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Inflectible.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/re$/i'), 'r');
|
||||
yield new Transformation(new Pattern('/er$/i'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/e$/i'), 'er');
|
||||
yield new Transformation(new Pattern('/r$/i'), 're');
|
||||
yield new Transformation(new Pattern('/$/'), 'er');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular(): iterable
|
||||
{
|
||||
yield new Substitution(new Word('konto'), new Word('konti'));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset(): Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset(): Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
31
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Rules.php
vendored
Normal file
31
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Rules.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset(): Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset(): Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
36
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Uninflected.php
vendored
Normal file
36
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Uninflected.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular(): iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural(): iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault(): iterable
|
||||
{
|
||||
yield new Pattern('barn');
|
||||
yield new Pattern('fjell');
|
||||
yield new Pattern('hus');
|
||||
}
|
||||
}
|
||||
42
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Pattern.php
vendored
Normal file
42
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Pattern.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
use function preg_match;
|
||||
|
||||
final class Pattern
|
||||
{
|
||||
/** @var string */
|
||||
private $pattern;
|
||||
|
||||
/** @var string */
|
||||
private $regex;
|
||||
|
||||
public function __construct(string $pattern)
|
||||
{
|
||||
$this->pattern = $pattern;
|
||||
|
||||
if (isset($this->pattern[0]) && $this->pattern[0] === '/') {
|
||||
$this->regex = $this->pattern;
|
||||
} else {
|
||||
$this->regex = '/' . $this->pattern . '/i';
|
||||
}
|
||||
}
|
||||
|
||||
public function getPattern(): string
|
||||
{
|
||||
return $this->pattern;
|
||||
}
|
||||
|
||||
public function getRegex(): string
|
||||
{
|
||||
return $this->regex;
|
||||
}
|
||||
|
||||
public function matches(string $word): bool
|
||||
{
|
||||
return preg_match($this->getRegex(), $word) === 1;
|
||||
}
|
||||
}
|
||||
34
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Patterns.php
vendored
Normal file
34
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Patterns.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
use function array_map;
|
||||
use function implode;
|
||||
use function preg_match;
|
||||
|
||||
class Patterns
|
||||
{
|
||||
/** @var Pattern[] */
|
||||
private $patterns;
|
||||
|
||||
/** @var string */
|
||||
private $regex;
|
||||
|
||||
public function __construct(Pattern ...$patterns)
|
||||
{
|
||||
$this->patterns = $patterns;
|
||||
|
||||
$patterns = array_map(static function (Pattern $pattern): string {
|
||||
return $pattern->getPattern();
|
||||
}, $this->patterns);
|
||||
|
||||
$this->regex = '/^(?:' . implode('|', $patterns) . ')$/i';
|
||||
}
|
||||
|
||||
public function matches(string $word): bool
|
||||
{
|
||||
return preg_match($this->regex, $word, $regs) === 1;
|
||||
}
|
||||
}
|
||||
104
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Inflectible.php
vendored
Normal file
104
libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Inflectible.php
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Portuguese;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/^(g|)ases$/i'), '\1ás');
|
||||
yield new Transformation(new Pattern('/(japon|escoc|ingl|dinamarqu|fregu|portugu)eses$/i'), '\1ês');
|
||||
yield new Transformation(new Pattern('/(ae|ao|oe)s$/'), 'ao');
|
||||
yield new Transformation(new Pattern('/(ãe|ão|õe)s$/'), 'ão');
|
||||
yield new Transformation(new Pattern('/^(.*[^s]s)es$/i'), '\1');
|
||||
yield new Transformation(new Pattern('/sses$/i'), 'sse');
|
||||
yield new Transformation(new Pattern('/ns$/i'), 'm');
|
||||
yield new Transformation(new Pattern('/(r|t|f|v)is$/i'), '\1il');
|
||||
yield new Transformation(new Pattern('/uis$/i'), 'ul');
|
||||
yield new Transformation(new Pattern('/ois$/i'), 'ol');
|
||||
yield new Transformation(new Pattern('/eis$/i'), 'ei');
|
||||
yield new Transformation(new Pattern('/éis$/i'), 'el');
|
||||
yield new Transformation(new Pattern('/([^p])ais$/i'), '\1al');
|
||||
yield new Transformation(new Pattern('/(r|z)es$/i'), '\1');
|
||||
yield new Transformation(new Pattern('/^(á|gá)s$/i'), '\1s');
|
||||
yield new Transformation(new Pattern('/([^ê])s$/i'), '\1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural(): iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\1aes');
|
||||
yield new Transformation(new Pattern('/^(irm|m)ao$/i'), '\1aos');
|
||||
yield new Transformation(new Pattern('/ao$/i'), 'oes');
|
||||
yield new Transformation(new Pattern('/^(alem|c|p)ão$/i'), '\1ães');
|
||||
yield new Transformation(new Pattern('/^(irm|m)ão$/i'), '\1ãos');
|
||||
yield new Transformation(new Pattern('/ão$/i'), 'ões');
|
||||
yield new Transformation(new Pattern('/^(|g)ás$/i'), '\1ases');
|
||||
yield new Transformation(new Pattern('/^(japon|escoc|ingl|dinamarqu|fregu|portugu)ês$/i'), '\1eses');
|
||||
yield new Transformation(new Pattern('/m$/i'), 'ns');
|
||||
yield new Transformation(new Pattern('/([^aeou])il$/i'), '\1is');
|
||||
yield new Transformation(new Pattern('/ul$/i'), 'uis');
|
||||
yield new Transformation(new Pattern('/ol$/i'), 'ois');
|
||||
yield new Transformation(new Pattern('/el$/i'), 'eis');
|
||||
yield new Transformation(new Pattern('/al$/i'), 'ais');
|
||||
yield new Transformation(new Pattern('/(z|r)$/i'), '\1es');
|
||||
yield new Transformation(new Pattern('/(s)$/i'), '\1');
|
||||
yield new Transformation(new Pattern('/$/'), 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular(): iterable
|
||||
{
|
||||
yield new Substitution(new Word('abdomen'), new Word('abdomens'));
|
||||
yield new Substitution(new Word('alemão'), new Word('alemães'));
|
||||
yield new Substitution(new Word('artesã'), new Word('artesãos'));
|
||||
yield new Substitution(new Word('álcool'), new Word('álcoois'));
|
||||
yield new Substitution(new Word('árvore'), new Word('árvores'));
|
||||
yield new Substitution(new Word('bencão'), new Word('bencãos'));
|
||||
yield new Substitution(new Word('cão'), new Word('cães'));
|
||||
yield new Substitution(new Word('campus'), new Word('campi'));
|
||||
yield new Substitution(new Word('cadáver'), new Word('cadáveres'));
|
||||
yield new Substitution(new Word('capelão'), new Word('capelães'));
|
||||
yield new Substitution(new Word('capitão'), new Word('capitães'));
|
||||
yield new Substitution(new Word('chão'), new Word('chãos'));
|
||||
yield new Substitution(new Word('charlatão'), new Word('charlatães'));
|
||||
yield new Substitution(new Word('cidadão'), new Word('cidadãos'));
|
||||
yield new Substitution(new Word('consul'), new Word('consules'));
|
||||
yield new Substitution(new Word('cristão'), new Word('cristãos'));
|
||||
yield new Substitution(new Word('difícil'), new Word('difíceis'));
|
||||
yield new Substitution(new Word('email'), new Word('emails'));
|
||||
yield new Substitution(new Word('escrivão'), new Word('escrivães'));
|
||||
yield new Substitution(new Word('fóssil'), new Word('fósseis'));
|
||||
yield new Substitution(new Word('gás'), new Word('gases'));
|
||||
yield new Substitution(new Word('germens'), new Word('germen'));
|
||||
yield new Substitution(new Word('grão'), new Word('grãos'));
|
||||
yield new Substitution(new Word('hífen'), new Word('hífens'));
|
||||
yield new Substitution(new Word('irmão'), new Word('irmãos'));
|
||||
yield new Substitution(new Word('liquens'), new Word('liquen'));
|
||||
yield new Substitution(new Word('mal'), new Word('males'));
|
||||
yield new Substitution(new Word('mão'), new Word('mãos'));
|
||||
yield new Substitution(new Word('orfão'), new Word('orfãos'));
|
||||
yield new Substitution(new Word('país'), new Word('países'));
|
||||
yield new Substitution(new Word('pai'), new Word('pais'));
|
||||
yield new Substitution(new Word('pão'), new Word('pães'));
|
||||
yield new Substitution(new Word('projétil'), new Word('projéteis'));
|
||||
yield new Substitution(new Word('réptil'), new Word('répteis'));
|
||||
yield new Substitution(new Word('sacristão'), new Word('sacristães'));
|
||||
yield new Substitution(new Word('sotão'), new Word('sotãos'));
|
||||
yield new Substitution(new Word('tabelião'), new Word('tabeliães'));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user