This commit is contained in:
Javier Casares 2026-01-29 09:59:19 +00:00
commit 7bcda55ebb
3158 changed files with 140643 additions and 130380 deletions

674
LICENSE Normal file
View file

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View file

@ -1,6 +1,14 @@
== Changelog == = 2.0.0 =
= 1.0.0 = * Added Reply-To header support for emails sent via Amazon SES.
* Improved error handling and validation.
* Initial release with Amazon SES credential management, region selection, and live validation inside the SMTP plugin settings. * Enhanced compatibility with core SMTP plugin 2.0.0.
* Routes WordPress and SMTP test emails through Amazon SES whenever credentials are configured and verified. * Improved credential handling and encryption.
* Code quality improvements and documentation.
* **BREAKING CHANGE**: Minimum PHP version increased to 8.2 (required by AWS SDK for PHP).
* Updated AWS SDK for PHP to latest version with security updates.
= 1.0.0 =
* Initial release with Amazon SES credential management, region selection, and live validation inside the SMTP plugin settings.
* Routes WordPress and SMTP test emails through Amazon SES whenever credentials are configured and verified.

View file

@ -1,5 +0,0 @@
{
"require": {
"aws/aws-sdk-php": "^3.356"
}
}

917
composer.lock generated
View file

@ -1,917 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1cb93c989568529d7573d019c613b48f",
"packages": [
{
"name": "aws/aws-crt-php",
"version": "v1.2.7",
"source": {
"type": "git",
"url": "https://github.com/awslabs/aws-crt-php.git",
"reference": "d71d9906c7bb63a28295447ba12e74723bd3730e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e",
"reference": "d71d9906c7bb63a28295447ba12e74723bd3730e",
"shasum": ""
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35||^5.6.3||^9.5",
"yoast/phpunit-polyfills": "^1.0"
},
"suggest": {
"ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality."
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "AWS SDK Common Runtime Team",
"email": "aws-sdk-common-runtime@amazon.com"
}
],
"description": "AWS Common Runtime for PHP",
"homepage": "https://github.com/awslabs/aws-crt-php",
"keywords": [
"amazon",
"aws",
"crt",
"sdk"
],
"support": {
"issues": "https://github.com/awslabs/aws-crt-php/issues",
"source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7"
},
"time": "2024-10-18T22:15:13+00:00"
},
{
"name": "aws/aws-sdk-php",
"version": "3.356.23",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "e9253cf6073f06080a7458af54e18fc474f0c864"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e9253cf6073f06080a7458af54e18fc474f0c864",
"reference": "e9253cf6073f06080a7458af54e18fc474f0c864",
"shasum": ""
},
"require": {
"aws/aws-crt-php": "^1.2.3",
"ext-json": "*",
"ext-pcre": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^7.4.5",
"guzzlehttp/promises": "^2.0",
"guzzlehttp/psr7": "^2.4.5",
"mtdowling/jmespath.php": "^2.8.0",
"php": ">=8.1",
"psr/http-message": "^1.0 || ^2.0"
},
"require-dev": {
"andrewsville/php-token-reflection": "^1.4",
"aws/aws-php-sns-message-validator": "~1.0",
"behat/behat": "~3.0",
"composer/composer": "^2.7.8",
"dms/phpunit-arraysubset-asserts": "^0.4.0",
"doctrine/cache": "~1.4",
"ext-dom": "*",
"ext-openssl": "*",
"ext-pcntl": "*",
"ext-sockets": "*",
"phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
"psr/cache": "^2.0 || ^3.0",
"psr/simple-cache": "^2.0 || ^3.0",
"sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0",
"symfony/filesystem": "^v6.4.0 || ^v7.1.0",
"yoast/phpunit-polyfills": "^2.0"
},
"suggest": {
"aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
"doctrine/cache": "To use the DoctrineCacheAdapter",
"ext-curl": "To send requests using cURL",
"ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages",
"ext-sockets": "To use client-side monitoring"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Aws\\": "src/"
},
"exclude-from-classmap": [
"src/data/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Amazon Web Services",
"homepage": "http://aws.amazon.com"
}
],
"description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
"homepage": "http://aws.amazon.com/sdkforphp",
"keywords": [
"amazon",
"aws",
"cloud",
"dynamodb",
"ec2",
"glacier",
"s3",
"sdk"
],
"support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.356.23"
},
"time": "2025-09-22T18:10:31+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "7.10.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4",
"reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^2.3",
"guzzlehttp/psr7": "^2.8",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"ext-curl": "*",
"guzzle/client-integration-tests": "3.0.2",
"php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle is a PHP HTTP client library",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"psr-18",
"psr-7",
"rest",
"web service"
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.10.0"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
"type": "tidelift"
}
],
"time": "2025-08-23T22:36:01+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "481557b130ef3790cf82b713667b43030dc9c957"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957",
"reference": "481557b130ef3790cf82b713667b43030dc9c957",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.44 || ^9.6.25"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.3.0"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
"type": "tidelift"
}
],
"time": "2025-08-22T14:34:08+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "2.8.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "21dc724a0583619cd1652f673303492272778051"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051",
"reference": "21dc724a0583619cd1652f673303492272778051",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0"
},
"provide": {
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "0.9.0",
"phpunit/phpunit": "^8.5.44 || ^9.6.25"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.8.0"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
"type": "tidelift"
}
],
"time": "2025-08-23T21:21:41+00:00"
},
{
"name": "mtdowling/jmespath.php",
"version": "2.8.0",
"source": {
"type": "git",
"url": "https://github.com/jmespath/jmespath.php.git",
"reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc",
"reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"symfony/polyfill-mbstring": "^1.17"
},
"require-dev": {
"composer/xdebug-handler": "^3.0.3",
"phpunit/phpunit": "^8.5.33"
},
"bin": [
"bin/jp.php"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"files": [
"src/JmesPath.php"
],
"psr-4": {
"JmesPath\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Declaratively specify how to extract elements from a JSON document",
"keywords": [
"json",
"jsonpath"
],
"support": {
"issues": "https://github.com/jmespath/jmespath.php/issues",
"source": "https://github.com/jmespath/jmespath.php/tree/2.8.0"
},
"time": "2024-09-04T18:46:31+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"shasum": ""
},
"require": {
"php": ">=7.1",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory"
},
"time": "2024-04-15T12:06:14+00:00"
},
{
"name": "psr/http-message",
"version": "2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/2.0"
},
"time": "2023-04-04T09:54:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"support": {
"issues": "https://github.com/ralouphie/getallheaders/issues",
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.6-dev"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-25T14:21:43+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"php": ">=7.2"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-12-23T08:48:59+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.6.0"
}

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -0,0 +1,315 @@
msgid ""
msgstr ""
"Project-Id-Version: SMTP (by ROBOTSTXT) Amazon SES\n"
"POT-Creation-Date: 2026-01-29 10:03+0100\n"
"PO-Revision-Date: 2026-01-29 09:30+0100\n"
"Last-Translator: ROBOTSTXT <robotstxt@robotstxt.es>\n"
"Language-Team: Catalan\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Manual\n"
#: includes/class-plugin.php:151
msgid "Amazon SES could not send the email because no recipient was provided."
msgstr "Amazon SES no ha pogut enviar l'email perquè no s'ha proporcionat cap destinatari."
#: includes/class-plugin.php:224
#, php-format
msgid "Amazon SES could not prepare the email: %s"
msgstr "Amazon SES no ha pogut preparar l'email: %s"
#: includes/class-plugin.php:265
#, php-format
msgid "Amazon SES could not send the email: %s"
msgstr "Amazon SES no ha pogut enviar l'email: %s"
#: includes/class-plugin.php:282
#, php-format
msgid "An unexpected error occurred while sending through Amazon SES: %s"
msgstr "S'ha produït un error inesperat en enviar a través d'Amazon SES: %s"
#: includes/class-plugin.php:330
#, php-format
msgid "Amazon SES rejected the \"From\" address: %s"
msgstr "Amazon SES ha rebutjat l'adreça \"De\": %s"
#: includes/class-plugin.php:351
#, php-format
msgid "Amazon SES rejected the recipient address: %s"
msgstr "Amazon SES ha rebutjat l'adreça del destinatari: %s"
#: includes/class-plugin.php:373
#, php-format
msgid "Amazon SES rejected the CC address: %s"
msgstr "Amazon SES ha rebutjat l'adreça CC: %s"
#: includes/class-plugin.php:395
#, php-format
msgid "Amazon SES rejected the BCC address: %s"
msgstr "Amazon SES ha rebutjat l'adreça CCO: %s"
#: includes/class-plugin.php:417
#, php-format
msgid "Amazon SES rejected the reply-to address: %s"
msgstr "Amazon SES ha rebutjat l'adreça de resposta: %s"
#: includes/class-plugin.php:446
#, php-format
msgid "Amazon SES rejected the configured reply-to address: %s"
msgstr "Amazon SES ha rebutjat l'adreça de resposta configurada: %s"
#: includes/class-plugin.php:497
#, php-format
msgid "Amazon SES could not include the attachment: %s"
msgstr "Amazon SES no ha pogut incloure l'adjunt: %s"
#: includes/class-plugin.php:833
msgid "Security check failed."
msgstr "Ha fallat la comprovació de seguretat."
#: includes/class-plugin.php:841 robotstxt-updater.php:367
msgid "You do not have sufficient permissions to access this page."
msgstr "No tens permisos suficients per accedir a aquesta pàgina."
#: includes/class-plugin.php:854
msgid "Amazon SES quotas refreshed successfully."
msgstr "Quotes d'Amazon SES actualitzades correctament."
#: includes/class-plugin.php:861
msgid "Unable to fetch quotas from Amazon SES. Check debug log for details."
msgstr "No s'han pogut obtenir les quotes d'Amazon SES. Verifica el registre de depuració per a més detalls."
#: includes/class-plugin.php:900
msgid "Access Key ID"
msgstr "ID de clau d'accés"
#: includes/class-plugin.php:906
msgid "Secret Access Key"
msgstr "Clau d'accés secreta"
#: includes/class-plugin.php:912
msgid "Region"
msgstr "Regió"
#: includes/class-plugin.php:918
msgid "From Email"
msgstr "Email remitent"
#: includes/class-plugin.php:924
msgid "From Name"
msgstr "Nom remitent"
#: includes/class-plugin.php:930
msgid "Reply-To Email"
msgstr "Email de resposta"
#: includes/class-plugin.php:936
msgid "Reply-To Name"
msgstr "Nom de resposta"
#: includes/class-plugin.php:951
msgid "Leave empty to keep the stored access key."
msgstr "Deixar buit per mantenir la clau d'accés emmagatzemada."
#: includes/class-plugin.php:962
msgid "Provide the IAM access key ID with permissions to send email through Amazon SES. Leave the field empty to retain the existing value."
msgstr "Proporciona l'ID de clau d'accés IAM amb permisos per enviar email a través d'Amazon SES. Deixa el camp buit per mantenir el valor existent."
#: includes/class-plugin.php:974
msgid "Leave empty to keep the stored secret access key."
msgstr "Deixar buit per mantenir la clau d'accés secreta emmagatzemada."
#: includes/class-plugin.php:985
msgid "Enter the secret access key associated with the IAM user. Leave the field empty to retain the existing value."
msgstr "Introdueix la clau d'accés secreta associada amb l'usuari IAM. Deixa el camp buit per mantenir el valor existent."
#: includes/class-plugin.php:1000
msgid "Select a region"
msgstr "Selecciona una regió"
#: includes/class-plugin.php:1005
msgid "Choose the AWS region where your Amazon SES account is hosted."
msgstr "Tria la regió d'AWS on està allotjat el teu compte d'Amazon SES."
#: includes/class-plugin.php:1082
msgid "The selected Amazon SES region is not available."
msgstr "La regió d'Amazon SES seleccionada no està disponible."
#: includes/class-plugin.php:1102
msgid "Amazon SES credentials were not saved. Provide an access key, secret key, and region."
msgstr "Les credencials d'Amazon SES no s'han desat. Proporciona una clau d'accés, clau secreta i regió."
#: includes/class-plugin.php:1126
msgid "Amazon SES credentials verified successfully."
msgstr "Credencials d'Amazon SES verificades correctament."
#: includes/class-plugin.php:1281
msgid "US East (Ohio)"
msgstr "EUA Est (Ohio)"
#: includes/class-plugin.php:1282
msgid "US East (N. Virginia)"
msgstr "EUA Est (N. Virgínia)"
#: includes/class-plugin.php:1283
msgid "US West (N. California)"
msgstr "EUA Oest (N. Califòrnia)"
#: includes/class-plugin.php:1284
msgid "US West (Oregon)"
msgstr "EUA Oest (Oregon)"
#: includes/class-plugin.php:1285
msgid "Africa (Cape Town)"
msgstr "Àfrica (Ciutat del Cap)"
#: includes/class-plugin.php:1286
msgid "Asia Pacific (Hyderabad)"
msgstr "Àsia Pacífic (Hyderabad)"
#: includes/class-plugin.php:1287
msgid "Asia Pacific (Jakarta)"
msgstr "Àsia Pacífic (Jakarta)"
#: includes/class-plugin.php:1288
msgid "Asia Pacific (Mumbai)"
msgstr "Àsia Pacífic (Mumbai)"
#: includes/class-plugin.php:1289
msgid "Asia Pacific (Osaka)"
msgstr "Àsia Pacífic (Osaka)"
#: includes/class-plugin.php:1290
msgid "Asia Pacific (Seoul)"
msgstr "Àsia Pacífic (Seül)"
#: includes/class-plugin.php:1291
msgid "Asia Pacific (Singapore)"
msgstr "Àsia Pacífic (Singapur)"
#: includes/class-plugin.php:1292
msgid "Asia Pacific (Sydney)"
msgstr "Àsia Pacífic (Sydney)"
#: includes/class-plugin.php:1293
msgid "Asia Pacific (Tokyo)"
msgstr "Àsia Pacífic (Tòquio)"
#: includes/class-plugin.php:1294
msgid "Canada (Central)"
msgstr "Canadà (Central)"
#: includes/class-plugin.php:1295
msgid "Europe (Frankfurt)"
msgstr "Europa (Frankfurt)"
#: includes/class-plugin.php:1296
msgid "Europe (Ireland)"
msgstr "Europa (Irlanda)"
#: includes/class-plugin.php:1297
msgid "Europe (London)"
msgstr "Europa (Londres)"
#: includes/class-plugin.php:1298
msgid "Europe (Milan)"
msgstr "Europa (Milà)"
#: includes/class-plugin.php:1299
msgid "Europe (Paris)"
msgstr "Europa (París)"
#: includes/class-plugin.php:1300
msgid "Europe (Stockholm)"
msgstr "Europa (Estocolm)"
#: includes/class-plugin.php:1301
msgid "Europe (Zurich)"
msgstr "Europa (Zuric)"
#: includes/class-plugin.php:1302
msgid "Israel (Tel Aviv)"
msgstr "Israel (Tel Aviv)"
#: includes/class-plugin.php:1303
msgid "Middle East (Bahrain)"
msgstr "Orient Mitjà (Bahrain)"
#: includes/class-plugin.php:1304
msgid "Middle East (UAE)"
msgstr "Orient Mitjà (EAU)"
#: includes/class-plugin.php:1305
msgid "South America (São Paulo)"
msgstr "Sud-amèrica (São Paulo)"
#: includes/class-plugin.php:1306
msgid "AWS GovCloud (US-East)"
msgstr "AWS GovCloud (EUA-Est)"
#: includes/class-plugin.php:1307
msgid "AWS GovCloud (US-West)"
msgstr "AWS GovCloud (EUA-Oest)"
#: includes/class-plugin.php:1322
#, php-format
msgid "%1$s (%2$s)"
msgstr "%1$s (%2$s)"
#: includes/class-plugin.php:1338
#, php-format
msgid "Region %s"
msgstr "Regió %s"
#: includes/class-plugin.php:1389
#, php-format
msgid "Invalid Amazon SES credentials: %s"
msgstr "Credencials d'Amazon SES invàlides: %s"
#: includes/class-plugin.php:1400
#, php-format
msgid "Could not verify Amazon SES credentials: %s"
msgstr "No s'han pogut verificar les credencials d'Amazon SES: %s"
#: includes/class-plugin.php:1411
#, php-format
msgid "An unexpected error occurred while validating Amazon SES credentials: %s"
msgstr "S'ha produït un error inesperat en validar les credencials d'Amazon SES: %s"
#: includes/class-plugin.php:1470 includes/class-plugin.php:1492
msgid "Amazon SES credentials are not configured."
msgstr "Les credencials d'Amazon SES no estan configurades."
#: includes/class-plugin.php:1506
msgid "Amazon SES did not return quota data."
msgstr "Amazon SES no ha retornat dades de quota."
#: includes/class-plugin.php:1524
msgid "Cannot fetch SES quotas: IAM user lacks ses:GetAccount permission."
msgstr "No es poden obtenir les quotes de SES: l'usuari IAM no té el permís ses:GetAccount."
#: includes/class-plugin.php:1532
#, php-format
msgid "Amazon SES API error: %s"
msgstr "Error d'API d'Amazon SES: %s"
#: includes/class-plugin.php:1541
#, php-format
msgid "Failed to fetch SES quota: %s"
msgstr "Ha fallat en obtenir la quota de SES: %s"
#: robotstxt-updater.php:362
msgid "Security check failed"
msgstr "Ha fallat la comprovació de seguretat"
msgid "SMTP (by ROBOTSTXT) Amazon SES"
msgstr "SMTP (by ROBOTSTXT) Amazon SES"
msgid "Adds Amazon SES configuration support to the ROBOTSTXT SMTP plugin."
msgstr "Afegeix suport de configuració d'Amazon SES al plugin ROBOTSTXT SMTP."
msgid "ROBOTSTXT"
msgstr "ROBOTSTXT"

Binary file not shown.

View file

@ -0,0 +1,315 @@
msgid ""
msgstr ""
"Project-Id-Version: SMTP (by ROBOTSTXT) Amazon SES\n"
"POT-Creation-Date: 2026-01-29 10:03+0100\n"
"PO-Revision-Date: 2026-01-29 09:30+0100\n"
"Last-Translator: ROBOTSTXT <robotstxt@robotstxt.es>\n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Manual\n"
#: includes/class-plugin.php:151
msgid "Amazon SES could not send the email because no recipient was provided."
msgstr "Amazon SES no pudo enviar el email porque no se proporcionó ningún destinatario."
#: includes/class-plugin.php:224
#, php-format
msgid "Amazon SES could not prepare the email: %s"
msgstr "Amazon SES no pudo preparar el email: %s"
#: includes/class-plugin.php:265
#, php-format
msgid "Amazon SES could not send the email: %s"
msgstr "Amazon SES no pudo enviar el email: %s"
#: includes/class-plugin.php:282
#, php-format
msgid "An unexpected error occurred while sending through Amazon SES: %s"
msgstr "Ocurrió un error inesperado al enviar a través de Amazon SES: %s"
#: includes/class-plugin.php:330
#, php-format
msgid "Amazon SES rejected the \"From\" address: %s"
msgstr "Amazon SES rechazó la dirección \"De\": %s"
#: includes/class-plugin.php:351
#, php-format
msgid "Amazon SES rejected the recipient address: %s"
msgstr "Amazon SES rechazó la dirección del destinatario: %s"
#: includes/class-plugin.php:373
#, php-format
msgid "Amazon SES rejected the CC address: %s"
msgstr "Amazon SES rechazó la dirección CC: %s"
#: includes/class-plugin.php:395
#, php-format
msgid "Amazon SES rejected the BCC address: %s"
msgstr "Amazon SES rechazó la dirección CCO: %s"
#: includes/class-plugin.php:417
#, php-format
msgid "Amazon SES rejected the reply-to address: %s"
msgstr "Amazon SES rechazó la dirección de respuesta: %s"
#: includes/class-plugin.php:446
#, php-format
msgid "Amazon SES rejected the configured reply-to address: %s"
msgstr "Amazon SES rechazó la dirección de respuesta configurada: %s"
#: includes/class-plugin.php:497
#, php-format
msgid "Amazon SES could not include the attachment: %s"
msgstr "Amazon SES no pudo incluir el adjunto: %s"
#: includes/class-plugin.php:833
msgid "Security check failed."
msgstr "Falló la comprobación de seguridad."
#: includes/class-plugin.php:841 robotstxt-updater.php:367
msgid "You do not have sufficient permissions to access this page."
msgstr "No tienes permisos suficientes para acceder a esta página."
#: includes/class-plugin.php:854
msgid "Amazon SES quotas refreshed successfully."
msgstr "Cuotas de Amazon SES actualizadas correctamente."
#: includes/class-plugin.php:861
msgid "Unable to fetch quotas from Amazon SES. Check debug log for details."
msgstr "No se pudieron obtener las cuotas de Amazon SES. Verifica el registro de depuración para más detalles."
#: includes/class-plugin.php:900
msgid "Access Key ID"
msgstr "ID de clave de acceso"
#: includes/class-plugin.php:906
msgid "Secret Access Key"
msgstr "Clave de acceso secreta"
#: includes/class-plugin.php:912
msgid "Region"
msgstr "Región"
#: includes/class-plugin.php:918
msgid "From Email"
msgstr "Email remitente"
#: includes/class-plugin.php:924
msgid "From Name"
msgstr "Nombre remitente"
#: includes/class-plugin.php:930
msgid "Reply-To Email"
msgstr "Email de respuesta"
#: includes/class-plugin.php:936
msgid "Reply-To Name"
msgstr "Nombre de respuesta"
#: includes/class-plugin.php:951
msgid "Leave empty to keep the stored access key."
msgstr "Dejar vacío para mantener la clave de acceso almacenada."
#: includes/class-plugin.php:962
msgid "Provide the IAM access key ID with permissions to send email through Amazon SES. Leave the field empty to retain the existing value."
msgstr "Proporciona el ID de clave de acceso IAM con permisos para enviar email a través de Amazon SES. Deja el campo vacío para mantener el valor existente."
#: includes/class-plugin.php:974
msgid "Leave empty to keep the stored secret access key."
msgstr "Dejar vacío para mantener la clave de acceso secreta almacenada."
#: includes/class-plugin.php:985
msgid "Enter the secret access key associated with the IAM user. Leave the field empty to retain the existing value."
msgstr "Introduce la clave de acceso secreta asociada con el usuario IAM. Deja el campo vacío para mantener el valor existente."
#: includes/class-plugin.php:1000
msgid "Select a region"
msgstr "Selecciona una región"
#: includes/class-plugin.php:1005
msgid "Choose the AWS region where your Amazon SES account is hosted."
msgstr "Elige la región de AWS donde está alojada tu cuenta de Amazon SES."
#: includes/class-plugin.php:1082
msgid "The selected Amazon SES region is not available."
msgstr "La región de Amazon SES seleccionada no está disponible."
#: includes/class-plugin.php:1102
msgid "Amazon SES credentials were not saved. Provide an access key, secret key, and region."
msgstr "Las credenciales de Amazon SES no se guardaron. Proporciona una clave de acceso, clave secreta y región."
#: includes/class-plugin.php:1126
msgid "Amazon SES credentials verified successfully."
msgstr "Credenciales de Amazon SES verificadas correctamente."
#: includes/class-plugin.php:1281
msgid "US East (Ohio)"
msgstr "EE.UU. Este (Ohio)"
#: includes/class-plugin.php:1282
msgid "US East (N. Virginia)"
msgstr "EE.UU. Este (N. Virginia)"
#: includes/class-plugin.php:1283
msgid "US West (N. California)"
msgstr "EE.UU. Oeste (N. California)"
#: includes/class-plugin.php:1284
msgid "US West (Oregon)"
msgstr "EE.UU. Oeste (Oregón)"
#: includes/class-plugin.php:1285
msgid "Africa (Cape Town)"
msgstr "África (Ciudad del Cabo)"
#: includes/class-plugin.php:1286
msgid "Asia Pacific (Hyderabad)"
msgstr "Asia Pacífico (Hyderabad)"
#: includes/class-plugin.php:1287
msgid "Asia Pacific (Jakarta)"
msgstr "Asia Pacífico (Yakarta)"
#: includes/class-plugin.php:1288
msgid "Asia Pacific (Mumbai)"
msgstr "Asia Pacífico (Mumbai)"
#: includes/class-plugin.php:1289
msgid "Asia Pacific (Osaka)"
msgstr "Asia Pacífico (Osaka)"
#: includes/class-plugin.php:1290
msgid "Asia Pacific (Seoul)"
msgstr "Asia Pacífico (Seúl)"
#: includes/class-plugin.php:1291
msgid "Asia Pacific (Singapore)"
msgstr "Asia Pacífico (Singapur)"
#: includes/class-plugin.php:1292
msgid "Asia Pacific (Sydney)"
msgstr "Asia Pacífico (Sídney)"
#: includes/class-plugin.php:1293
msgid "Asia Pacific (Tokyo)"
msgstr "Asia Pacífico (Tokio)"
#: includes/class-plugin.php:1294
msgid "Canada (Central)"
msgstr "Canadá (Central)"
#: includes/class-plugin.php:1295
msgid "Europe (Frankfurt)"
msgstr "Europa (Fráncfort)"
#: includes/class-plugin.php:1296
msgid "Europe (Ireland)"
msgstr "Europa (Irlanda)"
#: includes/class-plugin.php:1297
msgid "Europe (London)"
msgstr "Europa (Londres)"
#: includes/class-plugin.php:1298
msgid "Europe (Milan)"
msgstr "Europa (Milán)"
#: includes/class-plugin.php:1299
msgid "Europe (Paris)"
msgstr "Europa (París)"
#: includes/class-plugin.php:1300
msgid "Europe (Stockholm)"
msgstr "Europa (Estocolmo)"
#: includes/class-plugin.php:1301
msgid "Europe (Zurich)"
msgstr "Europa (Zúrich)"
#: includes/class-plugin.php:1302
msgid "Israel (Tel Aviv)"
msgstr "Israel (Tel Aviv)"
#: includes/class-plugin.php:1303
msgid "Middle East (Bahrain)"
msgstr "Oriente Medio (Baréin)"
#: includes/class-plugin.php:1304
msgid "Middle East (UAE)"
msgstr "Oriente Medio (EAU)"
#: includes/class-plugin.php:1305
msgid "South America (São Paulo)"
msgstr "Sudamérica (São Paulo)"
#: includes/class-plugin.php:1306
msgid "AWS GovCloud (US-East)"
msgstr "AWS GovCloud (EE.UU.-Este)"
#: includes/class-plugin.php:1307
msgid "AWS GovCloud (US-West)"
msgstr "AWS GovCloud (EE.UU.-Oeste)"
#: includes/class-plugin.php:1322
#, php-format
msgid "%1$s (%2$s)"
msgstr "%1$s (%2$s)"
#: includes/class-plugin.php:1338
#, php-format
msgid "Region %s"
msgstr "Región %s"
#: includes/class-plugin.php:1389
#, php-format
msgid "Invalid Amazon SES credentials: %s"
msgstr "Credenciales de Amazon SES inválidas: %s"
#: includes/class-plugin.php:1400
#, php-format
msgid "Could not verify Amazon SES credentials: %s"
msgstr "No se pudieron verificar las credenciales de Amazon SES: %s"
#: includes/class-plugin.php:1411
#, php-format
msgid "An unexpected error occurred while validating Amazon SES credentials: %s"
msgstr "Ocurrió un error inesperado al validar las credenciales de Amazon SES: %s"
#: includes/class-plugin.php:1470 includes/class-plugin.php:1492
msgid "Amazon SES credentials are not configured."
msgstr "Las credenciales de Amazon SES no están configuradas."
#: includes/class-plugin.php:1506
msgid "Amazon SES did not return quota data."
msgstr "Amazon SES no devolvió datos de cuota."
#: includes/class-plugin.php:1524
msgid "Cannot fetch SES quotas: IAM user lacks ses:GetAccount permission."
msgstr "No se pueden obtener las cuotas de SES: el usuario IAM no tiene el permiso ses:GetAccount."
#: includes/class-plugin.php:1532
#, php-format
msgid "Amazon SES API error: %s"
msgstr "Error de API de Amazon SES: %s"
#: includes/class-plugin.php:1541
#, php-format
msgid "Failed to fetch SES quota: %s"
msgstr "Falló al obtener la cuota de SES: %s"
#: robotstxt-updater.php:362
msgid "Security check failed"
msgstr "Falló la comprobación de seguridad"
msgid "SMTP (by ROBOTSTXT) Amazon SES"
msgstr "SMTP (by ROBOTSTXT) Amazon SES"
msgid "Adds Amazon SES configuration support to the ROBOTSTXT SMTP plugin."
msgstr "Añade soporte de configuración de Amazon SES al plugin ROBOTSTXT SMTP."
msgid "ROBOTSTXT"
msgstr "ROBOTSTXT"

View file

@ -0,0 +1,359 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: SMTP (by ROBOTSTXT) Amazon SES\n"
"POT-Creation-Date: 2026-01-29 10:03+0100\n"
"PO-Revision-Date: 2026-01-29 10:03+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
"X-Generator: Poedit 3.8\n"
"X-Poedit-Basepath: ..\n"
"X-Poedit-Flags-xgettext: --add-comments=translators:\n"
"X-Poedit-WPHeader: robotstxt-smtp-amazonses.php\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: "
"__;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
"X-Poedit-SearchPath-0: .\n"
"X-Poedit-SearchPathExcluded-0: *.min.js\n"
"X-Poedit-SearchPathExcluded-1: vendor\n"
#: includes/class-plugin.php:151
msgid "Amazon SES could not send the email because no recipient was provided."
msgstr ""
#. translators: %s: Error details describing the email preparation failure.
#: includes/class-plugin.php:224
#, php-format
msgid "Amazon SES could not prepare the email: %s"
msgstr ""
#. translators: %s: Error message returned by Amazon SES.
#: includes/class-plugin.php:265
#, php-format
msgid "Amazon SES could not send the email: %s"
msgstr ""
#. translators: %s: Error message describing the unexpected failure.
#: includes/class-plugin.php:282
#, php-format
msgid "An unexpected error occurred while sending through Amazon SES: %s"
msgstr ""
#. translators: %s: Error details describing why the From header is invalid.
#: includes/class-plugin.php:330
#, php-format
msgid "Amazon SES rejected the \"From\" address: %s"
msgstr ""
#. translators: %s: Invalid recipient email address.
#: includes/class-plugin.php:351
#, php-format
msgid "Amazon SES rejected the recipient address: %s"
msgstr ""
#. translators: %s: Invalid CC email address.
#: includes/class-plugin.php:373
#, php-format
msgid "Amazon SES rejected the CC address: %s"
msgstr ""
#. translators: %s: Invalid BCC email address.
#: includes/class-plugin.php:395
#, php-format
msgid "Amazon SES rejected the BCC address: %s"
msgstr ""
#. translators: %s: Invalid reply-to email address.
#: includes/class-plugin.php:417
#, php-format
msgid "Amazon SES rejected the reply-to address: %s"
msgstr ""
#. translators: %s: Invalid reply-to email address from settings.
#: includes/class-plugin.php:446
#, php-format
msgid "Amazon SES rejected the configured reply-to address: %s"
msgstr ""
#. translators: %s: Attachment path that could not be added.
#: includes/class-plugin.php:497
#, php-format
msgid "Amazon SES could not include the attachment: %s"
msgstr ""
#: includes/class-plugin.php:833
msgid "Security check failed."
msgstr ""
#: includes/class-plugin.php:841 robotstxt-updater.php:367
msgid "You do not have sufficient permissions to access this page."
msgstr ""
#: includes/class-plugin.php:854
msgid "Amazon SES quotas refreshed successfully."
msgstr ""
#: includes/class-plugin.php:861
msgid "Unable to fetch quotas from Amazon SES. Check debug log for details."
msgstr ""
#: includes/class-plugin.php:900
msgid "Access Key ID"
msgstr ""
#: includes/class-plugin.php:906
msgid "Secret Access Key"
msgstr ""
#: includes/class-plugin.php:912
msgid "Region"
msgstr ""
#: includes/class-plugin.php:918
msgid "From Email"
msgstr ""
#: includes/class-plugin.php:924
msgid "From Name"
msgstr ""
#: includes/class-plugin.php:930
msgid "Reply-To Email"
msgstr ""
#: includes/class-plugin.php:936
msgid "Reply-To Name"
msgstr ""
#: includes/class-plugin.php:951
msgid "Leave empty to keep the stored access key."
msgstr ""
#: includes/class-plugin.php:962
msgid ""
"Provide the IAM access key ID with permissions to send email through Amazon "
"SES. Leave the field empty to retain the existing value."
msgstr ""
#: includes/class-plugin.php:974
msgid "Leave empty to keep the stored secret access key."
msgstr ""
#: includes/class-plugin.php:985
msgid ""
"Enter the secret access key associated with the IAM user. Leave the field "
"empty to retain the existing value."
msgstr ""
#: includes/class-plugin.php:1000
msgid "Select a region"
msgstr ""
#: includes/class-plugin.php:1005
msgid "Choose the AWS region where your Amazon SES account is hosted."
msgstr ""
#: includes/class-plugin.php:1082
msgid "The selected Amazon SES region is not available."
msgstr ""
#: includes/class-plugin.php:1102
msgid ""
"Amazon SES credentials were not saved. Provide an access key, secret key, "
"and region."
msgstr ""
#: includes/class-plugin.php:1126
msgid "Amazon SES credentials verified successfully."
msgstr ""
#: includes/class-plugin.php:1281
msgid "US East (Ohio)"
msgstr ""
#: includes/class-plugin.php:1282
msgid "US East (N. Virginia)"
msgstr ""
#: includes/class-plugin.php:1283
msgid "US West (N. California)"
msgstr ""
#: includes/class-plugin.php:1284
msgid "US West (Oregon)"
msgstr ""
#: includes/class-plugin.php:1285
msgid "Africa (Cape Town)"
msgstr ""
#: includes/class-plugin.php:1286
msgid "Asia Pacific (Hyderabad)"
msgstr ""
#: includes/class-plugin.php:1287
msgid "Asia Pacific (Jakarta)"
msgstr ""
#: includes/class-plugin.php:1288
msgid "Asia Pacific (Mumbai)"
msgstr ""
#: includes/class-plugin.php:1289
msgid "Asia Pacific (Osaka)"
msgstr ""
#: includes/class-plugin.php:1290
msgid "Asia Pacific (Seoul)"
msgstr ""
#: includes/class-plugin.php:1291
msgid "Asia Pacific (Singapore)"
msgstr ""
#: includes/class-plugin.php:1292
msgid "Asia Pacific (Sydney)"
msgstr ""
#: includes/class-plugin.php:1293
msgid "Asia Pacific (Tokyo)"
msgstr ""
#: includes/class-plugin.php:1294
msgid "Canada (Central)"
msgstr ""
#: includes/class-plugin.php:1295
msgid "Europe (Frankfurt)"
msgstr ""
#: includes/class-plugin.php:1296
msgid "Europe (Ireland)"
msgstr ""
#: includes/class-plugin.php:1297
msgid "Europe (London)"
msgstr ""
#: includes/class-plugin.php:1298
msgid "Europe (Milan)"
msgstr ""
#: includes/class-plugin.php:1299
msgid "Europe (Paris)"
msgstr ""
#: includes/class-plugin.php:1300
msgid "Europe (Stockholm)"
msgstr ""
#: includes/class-plugin.php:1301
msgid "Europe (Zurich)"
msgstr ""
#: includes/class-plugin.php:1302
msgid "Israel (Tel Aviv)"
msgstr ""
#: includes/class-plugin.php:1303
msgid "Middle East (Bahrain)"
msgstr ""
#: includes/class-plugin.php:1304
msgid "Middle East (UAE)"
msgstr ""
#: includes/class-plugin.php:1305
msgid "South America (São Paulo)"
msgstr ""
#: includes/class-plugin.php:1306
msgid "AWS GovCloud (US-East)"
msgstr ""
#: includes/class-plugin.php:1307
msgid "AWS GovCloud (US-West)"
msgstr ""
#. translators: 1: AWS region display name. 2: AWS region code.
#: includes/class-plugin.php:1322
#, php-format
msgid "%1$s (%2$s)"
msgstr ""
#. translators: %s: AWS region code.
#: includes/class-plugin.php:1338
#, php-format
msgid "Region %s"
msgstr ""
#. translators: %s: Error message from Amazon SES.
#: includes/class-plugin.php:1389
#, php-format
msgid "Invalid Amazon SES credentials: %s"
msgstr ""
#. translators: %s: Error message from Amazon SES.
#: includes/class-plugin.php:1400
#, php-format
msgid "Could not verify Amazon SES credentials: %s"
msgstr ""
#. translators: %s: Error message describing the unexpected failure.
#: includes/class-plugin.php:1411
#, php-format
msgid ""
"An unexpected error occurred while validating Amazon SES credentials: %s"
msgstr ""
#: includes/class-plugin.php:1470 includes/class-plugin.php:1492
msgid "Amazon SES credentials are not configured."
msgstr ""
#: includes/class-plugin.php:1506
msgid "Amazon SES did not return quota data."
msgstr ""
#: includes/class-plugin.php:1524
msgid "Cannot fetch SES quotas: IAM user lacks ses:GetAccount permission."
msgstr ""
#. translators: %s: AWS error message
#: includes/class-plugin.php:1532
#, php-format
msgid "Amazon SES API error: %s"
msgstr ""
#. translators: %s: Error message
#: includes/class-plugin.php:1541
#, php-format
msgid "Failed to fetch SES quota: %s"
msgstr ""
#: robotstxt-updater.php:362
msgid "Security check failed"
msgstr ""
#. Plugin Name of the plugin/theme
msgid "SMTP (by ROBOTSTXT) Amazon SES"
msgstr ""
#. Plugin URI of the plugin/theme
msgid "https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-amazonses"
msgstr ""
#. Description of the plugin/theme
msgid "Adds Amazon SES configuration support to the ROBOTSTXT SMTP plugin."
msgstr ""
#. Author of the plugin/theme
msgid "ROBOTSTXT"
msgstr ""
#. Author URI of the plugin/theme
msgid "https://www.robotstxt.es/"
msgstr ""

View file

@ -1,49 +1,50 @@
=== SMTP (by ROBOTSTXT) Amazon SES === === SMTP (by ROBOTSTXT) Amazon SES ===
Contributors: robotstxt Contributors: javiercasares
Tags: amazon ses, smtp, email, transactional, deliverability Tags: amazon-ses, smtp, email, mail
Requires at least: 6.0 Requires at least: 6.5
Tested up to: 6.9 Tested up to: 6.9
Requires PHP: 8.2 Stable tag: 1.0.0
Stable tag: 1.0.0 Requires PHP: 8.2
License: GPLv3 or later Version: 1.0.0
License URI: https://www.gnu.org/licenses/gpl-3.0.html License: GPL-3.0-or-later
License URI: https://www.gnu.org/licenses/gpl-3.0.html
This private add-on connects the ROBOTSTXT SMTP plugin with Amazon Simple Email Service (SES).
This private add-on connects the ROBOTSTXT SMTP plugin with Amazon Simple Email Service (SES).
== Description ==
== Description ==
SMTP (by ROBOTSTXT) Amazon SES extends the core ROBOTSTXT SMTP plugin with a first-class Amazon SES transport. Configure the IAM credentials and region once to deliver transactional email securely and reliably through your AWS account. The extension keeps the familiar SMTP plugin interface while enforcing WordPress security best practices, validating credentials, and handling mail routing transparently.
SMTP (by ROBOTSTXT) Amazon SES extends the core ROBOTSTXT SMTP plugin with a first-class Amazon SES transport. Configure the IAM credentials and region once to deliver transactional email securely and reliably through your AWS account. The extension keeps the familiar SMTP plugin interface while enforcing WordPress security best practices, validating credentials, and handling mail routing transparently.
= Key features =
= Key features =
* Authenticate with IAM access and secret keys managed securely inside WordPress.
* Select from all supported Amazon SES regions with automatic discovery of newly available endpoints. * Authenticate with IAM access and secret keys managed securely inside WordPress.
* Send mail using the AWS SDK while preserving the original message structure, headers, and attachments. * Select from all supported Amazon SES regions with automatic discovery of newly available endpoints.
* Re-use the ROBOTSTXT SMTP logging tools to audit delivered messages. * Send mail using the AWS SDK while preserving the original message structure, headers, and attachments.
* Re-use the ROBOTSTXT SMTP logging tools to audit delivered messages.
== Installation ==
== Installation ==
1. Upload the plugin files to the `/wp-content/plugins/` directory or install the ZIP package via the WordPress admin.
2. Activate the plugin through the **Plugins** screen. The base **SMTP (by ROBOTSTXT)** plugin must remain active. 1. Upload the plugin files to the `/wp-content/plugins/` directory or install the ZIP package via the WordPress admin.
3. Navigate to **SMTP (by ROBOTSTXT) → Settings** and choose the Amazon SES integration. 2. Activate the plugin through the **Plugins** screen. The base **SMTP (by ROBOTSTXT)** plugin must remain active.
4. Provide the IAM access key, secret key, and select your Amazon SES region. Save the settings to verify your credentials. 3. Navigate to **SMTP (by ROBOTSTXT) → Settings** and choose the Amazon SES integration.
5. Send a test email from the SMTP settings page to confirm successful delivery. 4. Provide the IAM access key, secret key, and select your Amazon SES region. Save the settings to verify your credentials.
5. Send a test email from the SMTP settings page to confirm successful delivery.
== Frequently Asked Questions ==
== Frequently Asked Questions ==
= Do I need the base SMTP plugin? =
= Do I need the base SMTP plugin? =
Yes. This add-on depends on the core **SMTP (by ROBOTSTXT)** plugin for the settings interface, logging, and overall mail routing logic.
Yes. This add-on depends on the core **SMTP (by ROBOTSTXT)** plugin for the settings interface, logging, and overall mail routing logic.
= Are my credentials validated? =
= Are my credentials validated? =
The plugin validates Amazon SES credentials during saving to prevent misconfigurations. Errors appear directly on the SMTP settings page if authentication fails.
The plugin validates Amazon SES credentials during saving to prevent misconfigurations. Errors appear directly on the SMTP settings page if authentication fails.
= Does the plugin support multisite? =
= Does the plugin support multisite? =
Yes. Network administrators can manage credentials centrally or allow individual sites to configure their own Amazon SES connection.
Yes. Network administrators can manage credentials centrally or allow individual sites to configure their own Amazon SES connection.
== Changelog ==
== Changelog ==
= 1.0.0 =
* Initial release. = 1.0.0 =
* Initial release.

View file

@ -1,115 +1,66 @@
<?php <?php
/** /**
* Plugin Name: SMTP Amazon SES (by ROBOTSTXT) * Plugin Name: SMTP (by ROBOTSTXT) Amazon SES
* Plugin URI: https://www.robotstxt.es/ * Plugin URI: https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-amazonses
* Description: Adds Amazon SES configuration support to the ROBOTSTXT SMTP plugin. * Description: Adds Amazon SES configuration support to the ROBOTSTXT SMTP plugin.
* Version: 1.0.0 * Version: 2.0.0
* Requires at least: 6.0 * Requires at least: 6.5
* Requires PHP: 8.2 * Requires PHP: 8.2
* Author: ROBOTSTXT * Network: true
* Author URI: https://www.robotstxt.es/ * Security: robotstxt@robotstxt.es
* Text Domain: robotstxt-smtp-amazonses * Author: ROBOTSTXT
* Domain Path: /languages * Author URI: https://www.robotstxt.es/
* Requires Plugins: robotstxt-smtp * Text Domain: robotstxt-smtp-amazonses
* License: GPL-3.0-or-later * Requires Plugins: robotstxt-smtp
* License URI: https://www.gnu.org/licenses/gpl-3.0.html * Domain Path: /languages
* Gitea Plugin URI: ROBOTSTXT/robotstxt-smtp-amazonses * License: GPL-3.0-or-later
* Gitea Plugin URI: https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-amazonses * License URI: https://www.gnu.org/licenses/gpl-3.0.html
* Plugin ID: did:plc:z74fjcsglfynz7grselq5xos * Gitea Plugin URI: https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-amazonses
* * Primary Branch: main
* @package Robotstxt_SMTP_AmazonSES *
*/ * @package Robotstxt_SMTP_AmazonSES
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; if ( ! defined( 'ABSPATH' ) ) {
} exit;
}
if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_VERSION' ) ) {
define( 'ROBOTSTXT_SMTP_AMAZONSES_VERSION', '1.0.0' ); if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_VERSION' ) ) {
} define( 'ROBOTSTXT_SMTP_AMAZONSES_VERSION', '2.0.0' );
}
if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_FILE' ) ) {
define( 'ROBOTSTXT_SMTP_AMAZONSES_FILE', __FILE__ ); if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_FILE' ) ) {
} define( 'ROBOTSTXT_SMTP_AMAZONSES_FILE', __FILE__ );
}
if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_PATH' ) ) {
define( 'ROBOTSTXT_SMTP_AMAZONSES_PATH', plugin_dir_path( __FILE__ ) ); if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_PATH' ) ) {
} define( 'ROBOTSTXT_SMTP_AMAZONSES_PATH', plugin_dir_path( __FILE__ ) );
}
if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_URL' ) ) {
define( 'ROBOTSTXT_SMTP_AMAZONSES_URL', plugin_dir_url( __FILE__ ) ); if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_URL' ) ) {
} define( 'ROBOTSTXT_SMTP_AMAZONSES_URL', plugin_dir_url( __FILE__ ) );
}
if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_SLUG' ) ) {
define( 'ROBOTSTXT_SMTP_AMAZONSES_SLUG', 'robotstxt-smtp-amazonses' ); if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_SLUG' ) ) {
} define( 'ROBOTSTXT_SMTP_AMAZONSES_SLUG', 'robotstxt-smtp-amazonses' );
}
if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_BASENAME' ) ) {
define( 'ROBOTSTXT_SMTP_AMAZONSES_BASENAME', plugin_basename( ROBOTSTXT_SMTP_AMAZONSES_FILE ) ); if ( ! defined( 'ROBOTSTXT_SMTP_AMAZONSES_BASENAME' ) ) {
} define( 'ROBOTSTXT_SMTP_AMAZONSES_BASENAME', plugin_basename( ROBOTSTXT_SMTP_AMAZONSES_FILE ) );
}
$autoload = ROBOTSTXT_SMTP_AMAZONSES_PATH . 'vendor/autoload.php';
$autoload = ROBOTSTXT_SMTP_AMAZONSES_PATH . 'vendor/autoload.php';
if ( \is_readable( $autoload ) ) {
require_once $autoload; if ( \is_readable( $autoload ) ) {
} require_once $autoload;
}
require_once ROBOTSTXT_SMTP_AMAZONSES_PATH . 'includes/class-plugin.php';
require_once ROBOTSTXT_SMTP_AMAZONSES_PATH . 'includes/class-plugin.php';
if ( ! function_exists( 'robotstxt_smtp_amazonses_dependencies_satisfied' ) ) {
/** // Initialize the plugin.
* Determines whether all plugin dependencies are available. // Dependency checking is handled by the "Requires Plugins" header in WordPress 6.5+.
* \Robotstxt_SMTP_AmazonSES\Plugin::get_instance()->run();
* @since 1.0.1
* // Initialize ROBOTSTXT updater (auto-configures from plugin headers).
* @return bool require_once __DIR__ . '/robotstxt-updater.php';
*/ Robotstxt_Updater::init( __FILE__ );
function robotstxt_smtp_amazonses_dependencies_satisfied(): bool {
return class_exists( '\\Robotstxt_SMTP\\Plugin' ) && class_exists( '\\Robotstxt_SMTP\\Admin\\Settings_Page' );
}
}
if ( ! function_exists( 'robotstxt_smtp_amazonses_register_dependency_notice' ) ) {
/**
* Registers the admin notice shown when the core plugin is missing.
*
* @since 1.0.1
*
* @return void
*/
function robotstxt_smtp_amazonses_register_dependency_notice(): void {
if ( ! is_admin() ) {
return;
}
$callback = static function (): void {
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
if ( $screen && 'plugins' !== $screen->id && 'plugins-network' !== $screen->id ) {
return;
}
$message = sprintf(
/* translators: %s: plugin name. */
esc_html__( 'The %s add-on requires the ROBOTSTXT SMTP plugin to be installed and active.', 'robotstxt-smtp-amazonses' ),
esc_html__( 'ROBOTSTXT SMTP Amazon SES', 'robotstxt-smtp-amazonses' )
);
?>
<div class="notice notice-error">
<p><?php echo esc_html( $message ); ?></p>
</div>
<?php
};
add_action( 'admin_notices', $callback );
add_action( 'network_admin_notices', $callback );
}
}
if ( robotstxt_smtp_amazonses_dependencies_satisfied() ) {
\Robotstxt_SMTP_AmazonSES\Plugin::get_instance()->run();
} else {
robotstxt_smtp_amazonses_register_dependency_notice();
}

383
robotstxt-updater.php Normal file
View file

@ -0,0 +1,383 @@
<?php
/**
* Generic JSON-based updater for ROBOTSTXT plugins.
*
* This file is designed to be copied to any ROBOTSTXT plugin.
* It auto-configures itself by reading the plugin headers.
*
* @package ROBOTSTXT
* @version 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'Robotstxt_Updater' ) ) {
/**
* Class Robotstxt_Updater
*
* Generic updater that works with any plugin.
* Reads plugin headers and constructs update URL automatically.
*/
class Robotstxt_Updater {
/**
* Plugin file path.
*
* @var string
*/
private string $plugin_file_path;
/**
* Plugin basename (e.g., 'my-plugin/my-plugin.php').
*
* @var string
*/
private string $plugin_basename;
/**
* Plugin slug (directory name).
*
* @var string
*/
private string $plugin_slug;
/**
* Remote JSON URL.
*
* @var string
*/
private string $json_url;
/**
* Cache key.
*
* @var string
*/
private string $cache_key;
/**
* Plugin headers.
*
* @var array
*/
private array $plugin_data;
/**
* Initialize the updater.
*
* Usage in your main plugin file:
* require_once __DIR__ . '/robotstxt-updater.php';
* Robotstxt_Updater::init( __FILE__ );
*
* @param string $plugin_file_path Absolute path to the main plugin file.
*/
public static function init( string $plugin_file_path ): void {
$instance = new self( $plugin_file_path );
$instance->register();
}
/**
* Constructor.
*
* @param string $plugin_file_path Absolute path to the main plugin file.
*/
private function __construct( string $plugin_file_path ) {
$this->plugin_file_path = $plugin_file_path;
$this->plugin_basename = plugin_basename( $plugin_file_path );
$this->plugin_slug = dirname( $this->plugin_basename );
$this->plugin_data = $this->get_plugin_data();
$this->json_url = $this->build_json_url();
$this->cache_key = 'robotstxt_updater_' . md5( $this->plugin_basename );
}
/**
* Register WordPress hooks.
*/
private function register(): void {
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'inject_update_info' ) );
add_filter( 'plugins_api', array( $this, 'provide_plugin_details' ), 10, 3 );
add_action( 'admin_init', array( $this, 'handle_cache_clear' ) );
add_action( 'robotstxt_updater_clear_cache', array( $this, 'clear_cache' ) );
}
/**
* Get plugin headers.
*
* @return array Plugin data.
*/
private function get_plugin_data(): array {
if ( ! function_exists( 'get_plugin_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
return get_plugin_data( $this->plugin_file_path, false, false );
}
/**
* Build JSON URL from plugin headers.
*
* Tries to use "Gitea Plugin URI" header to construct the URL.
* Falls back to Plugin URI if Gitea URI is not available.
*
* @return string JSON URL.
*/
private function build_json_url(): string {
// Try Gitea Plugin URI (format: "OWNER/REPO" or full URL).
if ( ! empty( $this->plugin_data['Gitea Plugin URI'] ) ) {
$gitea_uri = $this->plugin_data['Gitea Plugin URI'];
// If it's already a full URL, use it.
if ( str_starts_with( $gitea_uri, 'http' ) ) {
// Extract base URL and construct JSON path.
return rtrim( $gitea_uri, '/' ) . '/raw/branch/main/update.json';
}
// If it's in format "OWNER/REPO", construct full URL.
if ( preg_match( '#^[^/]+/[^/]+$#', $gitea_uri ) ) {
return "https://git.robotstxt.es/{$gitea_uri}/raw/branch/main/update.json";
}
}
// Fallback: try to extract from Plugin URI.
if ( ! empty( $this->plugin_data['PluginURI'] ) ) {
$plugin_uri = $this->plugin_data['PluginURI'];
if ( str_contains( $plugin_uri, 'git.robotstxt.es' ) ) {
return rtrim( $plugin_uri, '/' ) . '/raw/branch/main/update.json';
}
}
// Last resort: construct from plugin slug.
return "https://git.robotstxt.es/ROBOTSTXT/{$this->plugin_slug}/raw/branch/main/update.json";
}
/**
* Inject update info into WP's plugin update transient.
*
* @param object|mixed $transient The update_plugins transient.
*
* @return object The modified transient.
*/
public function inject_update_info( $transient ) {
if ( ! is_object( $transient ) ) {
$transient = new stdClass();
}
if ( empty( $transient->checked ) || ! is_array( $transient->checked ) ) {
return $transient;
}
if ( empty( $transient->checked[ $this->plugin_basename ] ) ) {
return $transient;
}
$current_version = $transient->checked[ $this->plugin_basename ];
$remote = $this->get_remote_data();
if ( empty( $remote['version'] ) || empty( $remote['download_url'] ) ) {
return $transient;
}
if ( ! $this->is_compatible( $remote ) ) {
return $transient;
}
if ( version_compare( $remote['version'], $current_version, '>' ) ) {
$update = (object) array(
'slug' => $remote['slug'] ?? $this->plugin_slug,
'plugin' => $this->plugin_basename,
'new_version' => $remote['version'],
'url' => $remote['homepage'] ?? $this->plugin_data['PluginURI'] ?? '',
'package' => $remote['download_url'],
'tested' => $remote['tested'] ?? '',
'requires' => $remote['requires'] ?? '',
'requires_php' => $remote['requires_php'] ?? '',
);
$transient->response[ $this->plugin_basename ] = $update;
}
return $transient;
}
/**
* Provide "View details" modal content.
*
* @param false|object|array $result The result object or array.
* @param string $action The type of information being requested.
* @param object $args Plugin API arguments.
*
* @return false|object The plugin information object or false.
*/
public function provide_plugin_details( $result, string $action, object $args ) {
if ( 'plugin_information' !== $action ) {
return $result;
}
if ( empty( $args->slug ) || $args->slug !== $this->plugin_slug ) {
return $result;
}
$remote = $this->get_remote_data();
if ( empty( $remote['version'] ) ) {
return $result;
}
return (object) array(
'name' => $remote['name'] ?? $this->plugin_data['Name'] ?? $this->plugin_slug,
'slug' => $remote['slug'] ?? $this->plugin_slug,
'version' => $remote['version'],
'author' => $remote['author'] ?? $this->plugin_data['Author'] ?? '',
'homepage' => $remote['homepage'] ?? $this->plugin_data['PluginURI'] ?? '',
'requires' => $remote['requires'] ?? '',
'tested' => $remote['tested'] ?? '',
'requires_php' => $remote['requires_php'] ?? '',
'sections' => array(
'description' => $remote['description'] ?? $this->plugin_data['Description'] ?? '',
'changelog' => $remote['changelog'] ?? '',
),
'download_link' => $remote['download_url'] ?? '',
);
}
/**
* Get remote data with caching and HMAC signature verification.
*
* @return array Remote data.
*/
private function get_remote_data(): array {
$cached = get_site_transient( $this->cache_key );
// Verify HMAC signature if AUTH_SALT is defined and cache has signature.
if ( false !== $cached && defined( 'AUTH_SALT' ) && '' !== AUTH_SALT ) {
if ( is_array( $cached ) && isset( $cached['signature'], $cached['data'] ) ) {
$expected_sig = hash_hmac( 'sha256', $this->cache_key . serialize( $cached['data'] ), AUTH_SALT );
if ( hash_equals( $expected_sig, $cached['signature'] ) ) {
// Signature valid, return data.
return is_array( $cached['data'] ) ? $cached['data'] : array();
}
// Signature invalid, delete corrupted cache.
delete_site_transient( $this->cache_key );
$cached = false;
}
}
// If no valid cache, fetch fresh data.
if ( false === $cached ) {
$remote = $this->fetch_json();
// Store with HMAC signature if AUTH_SALT is available.
if ( defined( 'AUTH_SALT' ) && '' !== AUTH_SALT ) {
$payload = array(
'data' => $remote ?: array(),
'timestamp' => time(),
'signature' => hash_hmac( 'sha256', $this->cache_key . serialize( $remote ?: array() ), AUTH_SALT ),
);
set_site_transient( $this->cache_key, $payload, 6 * HOUR_IN_SECONDS );
} else {
// Fallback to standard caching.
set_site_transient( $this->cache_key, $remote ?: array(), 6 * HOUR_IN_SECONDS );
}
return is_array( $remote ) ? $remote : array();
}
// Legacy cache format without signature (backward compatibility).
return is_array( $cached ) ? $cached : array();
}
/**
* Fetch JSON from remote URL.
*
* @return array Decoded JSON data.
*/
private function fetch_json(): array {
$response = wp_remote_get(
$this->json_url,
array(
'timeout' => 10,
'headers' => array(
'Accept' => 'application/json',
),
)
);
if ( is_wp_error( $response ) ) {
return array();
}
$code = (int) wp_remote_retrieve_response_code( $response );
if ( $code < 200 || $code >= 300 ) {
return array();
}
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
return is_array( $data ) ? $data : array();
}
/**
* Check compatibility.
*
* @param array $remote Remote data.
*
* @return bool True if compatible.
*/
private function is_compatible( array $remote ): bool {
if ( ! empty( $remote['requires_php'] ) ) {
if ( version_compare( PHP_VERSION, $remote['requires_php'], '<' ) ) {
return false;
}
}
if ( ! empty( $remote['requires'] ) ) {
if ( version_compare( get_bloginfo( 'version' ), $remote['requires'], '<' ) ) {
return false;
}
}
return true;
}
/**
* Handle manual cache clear via URL parameter.
*/
public function handle_cache_clear(): void {
// Check if this is a cache clear request first.
$clear_cache = filter_input( INPUT_GET, 'robotstxt_clear_update_cache', FILTER_UNSAFE_RAW );
if ( null === $clear_cache ) {
return;
}
// This is a cache clear request - now verify nonce.
$nonce_raw = filter_input( INPUT_GET, '_wpnonce', FILTER_UNSAFE_RAW );
$nonce = $nonce_raw ? sanitize_text_field( wp_unslash( $nonce_raw ) ) : '';
if ( ! wp_verify_nonce( $nonce, 'robotstxt_clear_update_cache' ) ) {
wp_die( esc_html__( 'Security check failed', 'robotstxt-smtp-amazonses' ) );
}
// Check permissions.
if ( ! current_user_can( 'update_plugins' ) ) {
wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'robotstxt-smtp-amazonses' ) );
}
$this->clear_cache();
wp_safe_redirect( remove_query_arg( array( 'robotstxt_clear_update_cache', '_wpnonce' ) ) );
exit;
}
/**
* Clear update cache.
*/
public function clear_cache(): void {
delete_site_transient( $this->cache_key );
delete_site_transient( 'update_plugins' );
}
}
}

View file

@ -1 +0,0 @@
{ "security_contact": "robotstxt@robotstxt.es" }

View file

@ -1,136 +1,136 @@
<?php <?php
/** /**
* Uninstall routines for the Amazon SES extension. * Uninstall routines for the Amazon SES extension.
* *
* @package Robotstxt_SMTP_AmazonSES * @package Robotstxt_SMTP_AmazonSES
*/ */
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
exit; exit;
} }
$option_keys = array( $option_keys = array(
'amazon_ses_access_key', 'amazon_ses_access_key',
'amazon_ses_secret_key', 'amazon_ses_secret_key',
'amazon_ses_region', 'amazon_ses_region',
); );
robotstxt_smtp_amazonses_delete_network_settings( $option_keys ); robotstxt_smtp_amazonses_delete_network_settings( $option_keys );
if ( function_exists( 'is_multisite' ) && is_multisite() ) { if ( function_exists( 'is_multisite' ) && is_multisite() ) {
$sites = get_sites( array( 'fields' => 'ids' ) ); $sites = get_sites( array( 'fields' => 'ids' ) );
foreach ( $sites as $site_id ) { foreach ( $sites as $site_id ) {
switch_to_blog( (int) $site_id ); switch_to_blog( (int) $site_id );
robotstxt_smtp_amazonses_delete_site_settings( $option_keys ); robotstxt_smtp_amazonses_delete_site_settings( $option_keys );
restore_current_blog(); restore_current_blog();
} }
} else { } else {
robotstxt_smtp_amazonses_delete_site_settings( $option_keys ); robotstxt_smtp_amazonses_delete_site_settings( $option_keys );
} }
if ( ! function_exists( 'robotstxt_smtp_amazonses_delete_site_settings' ) ) { if ( ! function_exists( 'robotstxt_smtp_amazonses_delete_site_settings' ) ) {
/** /**
* Deletes Amazon SES settings and logs for the current site. * Deletes Amazon SES settings and logs for the current site.
* *
* @param array<int, string> $keys Option keys to remove. * @param array<int, string> $keys Option keys to remove.
* *
* @return void * @return void
*/ */
function robotstxt_smtp_amazonses_delete_site_settings( array $keys ): void { function robotstxt_smtp_amazonses_delete_site_settings( array $keys ): void {
robotstxt_smtp_amazonses_remove_keys_from_option( 'robotstxt_smtp_options', $keys ); robotstxt_smtp_amazonses_remove_keys_from_option( 'robotstxt_smtp_options', $keys );
robotstxt_smtp_amazonses_delete_logs(); robotstxt_smtp_amazonses_delete_logs();
} }
} }
if ( ! function_exists( 'robotstxt_smtp_amazonses_delete_network_settings' ) ) { if ( ! function_exists( 'robotstxt_smtp_amazonses_delete_network_settings' ) ) {
/** /**
* Removes Amazon SES values stored in the network-wide settings. * Removes Amazon SES values stored in the network-wide settings.
* *
* @param array<int, string> $keys Option keys to remove. * @param array<int, string> $keys Option keys to remove.
* *
* @return void * @return void
*/ */
function robotstxt_smtp_amazonses_delete_network_settings( array $keys ): void { function robotstxt_smtp_amazonses_delete_network_settings( array $keys ): void {
$settings = get_site_option( 'robotstxt_smtp_network_options', array() ); $settings = get_site_option( 'robotstxt_smtp_network_options', array() );
if ( ! is_array( $settings ) || empty( $settings ) ) { if ( ! is_array( $settings ) || empty( $settings ) ) {
return; return;
} }
$clean_settings = robotstxt_smtp_amazonses_remove_keys( $settings, $keys ); $clean_settings = robotstxt_smtp_amazonses_remove_keys( $settings, $keys );
if ( $clean_settings !== $settings ) { if ( $clean_settings !== $settings ) {
update_site_option( 'robotstxt_smtp_network_options', $clean_settings ); update_site_option( 'robotstxt_smtp_network_options', $clean_settings );
} }
} }
} }
if ( ! function_exists( 'robotstxt_smtp_amazonses_remove_keys_from_option' ) ) { if ( ! function_exists( 'robotstxt_smtp_amazonses_remove_keys_from_option' ) ) {
/** /**
* Removes specific keys from an option array if it exists. * Removes specific keys from an option array if it exists.
* *
* @param string $option_name Option identifier. * @param string $option_name Option identifier.
* @param array<int, string> $keys Keys to remove. * @param array<int, string> $keys Keys to remove.
* *
* @return void * @return void
*/ */
function robotstxt_smtp_amazonses_remove_keys_from_option( string $option_name, array $keys ): void { function robotstxt_smtp_amazonses_remove_keys_from_option( string $option_name, array $keys ): void {
$settings = get_option( $option_name, array() ); $settings = get_option( $option_name, array() );
if ( ! is_array( $settings ) || empty( $settings ) ) { if ( ! is_array( $settings ) || empty( $settings ) ) {
return; return;
} }
$clean_settings = robotstxt_smtp_amazonses_remove_keys( $settings, $keys ); $clean_settings = robotstxt_smtp_amazonses_remove_keys( $settings, $keys );
if ( $clean_settings !== $settings ) { if ( $clean_settings !== $settings ) {
update_option( $option_name, $clean_settings ); update_option( $option_name, $clean_settings );
} }
} }
} }
if ( ! function_exists( 'robotstxt_smtp_amazonses_remove_keys' ) ) { if ( ! function_exists( 'robotstxt_smtp_amazonses_remove_keys' ) ) {
/** /**
* Returns an array without the provided keys. * Returns an array without the provided keys.
* *
* @param array<string, mixed> $settings Option values. * @param array<string, mixed> $settings Option values.
* @param array<int, string> $keys Keys to remove. * @param array<int, string> $keys Keys to remove.
* *
* @return array<string, mixed> * @return array<string, mixed>
*/ */
function robotstxt_smtp_amazonses_remove_keys( array $settings, array $keys ): array { function robotstxt_smtp_amazonses_remove_keys( array $settings, array $keys ): array {
foreach ( $keys as $key ) { foreach ( $keys as $key ) {
unset( $settings[ $key ] ); unset( $settings[ $key ] );
} }
return $settings; return $settings;
} }
} }
if ( ! function_exists( 'robotstxt_smtp_amazonses_delete_logs' ) ) { if ( ! function_exists( 'robotstxt_smtp_amazonses_delete_logs' ) ) {
/** /**
* Deletes all stored SMTP logs for the current site. * Deletes all stored SMTP logs for the current site.
* *
* @return void * @return void
*/ */
function robotstxt_smtp_amazonses_delete_logs(): void { function robotstxt_smtp_amazonses_delete_logs(): void {
do { do {
$logs = get_posts( $logs = get_posts(
array( array(
'post_type' => 'robotstxt_smtp_log', 'post_type' => 'robotstxt_smtp_log',
'post_status' => 'any', 'post_status' => 'any',
'fields' => 'ids', 'fields' => 'ids',
'posts_per_page' => 100, 'posts_per_page' => 100,
'orderby' => 'ID', 'orderby' => 'ID',
'order' => 'ASC', 'order' => 'ASC',
) )
); );
foreach ( $logs as $log_id ) { foreach ( $logs as $log_id ) {
wp_delete_post( (int) $log_id, true ); wp_delete_post( (int) $log_id, true );
} }
} while ( ! empty( $logs ) ); } while ( ! empty( $logs ) );
} }
} }

28
update.json Normal file
View file

@ -0,0 +1,28 @@
{
"name": "SMTP (by ROBOTSTXT) Amazon SES",
"slug": "robotstxt-smtp-amazonses",
"version": "2.0.0",
"download_url": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-amazonses/releases/download/2.0.0/robotstxt-smtp-amazonses-2.0.0.zip",
"requires": "6.5",
"requires_php": "8.2",
"tested": "6.9",
"last_updated": "2026-01-29",
"author": "ROBOTSTXT",
"author_profile": "https://www.robotstxt.es/",
"homepage": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-amazonses",
"requires_plugins": ["robotstxt-smtp"],
"description": "Adds Amazon SES (Simple Email Service) configuration support to the ROBOTSTXT SMTP plugin. Integrates seamlessly with AWS SDK for PHP to send emails through Amazon SES infrastructure.",
"changelog": "<h3>2.0.0 - 2026-01-29</h3><p><strong>⚠️ BREAKING CHANGE:</strong> This version requires PHP 8.2 or higher due to AWS SDK requirements.</p><ul><li><strong>Added:</strong> Reply-To header support for emails sent via Amazon SES</li><li><strong>Fixed:</strong> Improved error handling and validation</li><li><strong>Fixed:</strong> Enhanced compatibility with core SMTP plugin 2.0.0</li><li><strong>Security:</strong> Improved credential handling and encryption</li><li><strong>Security:</strong> Updated AWS SDK for PHP to latest version (3.369.20) with security patches</li><li><strong>Changed:</strong> Minimum PHP version increased to 8.2</li><li><strong>Improved:</strong> Code quality and documentation</li></ul><h3>1.0.0 - 2026-01-27</h3><ul><li>Initial release</li><li>Amazon SES integration via AWS SDK v3</li><li>Full compatibility with ROBOTSTXT SMTP plugin</li><li>Support for AWS regions and credentials configuration</li><li>Automatic dependency management with Composer</li></ul>",
"sections": {
"description": "Adds Amazon SES (Simple Email Service) configuration support to the ROBOTSTXT SMTP plugin. Integrates seamlessly with AWS SDK for PHP to send emails through Amazon SES infrastructure.",
"changelog": "<h3>2.0.0 - 2026-01-29</h3><p><strong>⚠️ BREAKING CHANGE:</strong> This version requires PHP 8.2 or higher due to AWS SDK requirements.</p><ul><li><strong>Added:</strong> Reply-To header support for emails sent via Amazon SES</li><li><strong>Fixed:</strong> Improved error handling and validation</li><li><strong>Fixed:</strong> Enhanced compatibility with core SMTP plugin 2.0.0</li><li><strong>Security:</strong> Improved credential handling and encryption</li><li><strong>Security:</strong> Updated AWS SDK for PHP to latest version (3.369.20) with security patches</li><li><strong>Changed:</strong> Minimum PHP version increased to 8.2</li><li><strong>Improved:</strong> Code quality and documentation</li></ul><h3>1.0.0 - 2026-01-27</h3><ul><li>Initial release</li><li>Amazon SES integration via AWS SDK v3</li><li>Full compatibility with ROBOTSTXT SMTP plugin</li><li>Support for AWS regions and credentials configuration</li><li>Automatic dependency management with Composer</li></ul>"
},
"banners": {
"low": "",
"high": ""
},
"icons": {
"1x": "",
"2x": ""
}
}

50
vendor/autoload.php vendored
View file

@ -1,25 +1,25 @@
<?php <?php
// autoload.php @generated by Composer // autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) { if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) { if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error'); 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; $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 (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err); fwrite(STDERR, $err);
} elseif (!headers_sent()) { } elseif (!headers_sent()) {
echo $err; echo $err;
} }
} }
trigger_error( trigger_error(
$err, $err,
E_USER_ERROR E_USER_ERROR
); );
} }
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit85325c0f13ef626582fea9d1df635a9d::getLoader(); return ComposerAutoloaderInit85325c0f13ef626582fea9d1df635a9d::getLoader();

View file

@ -1,4 +0,0 @@
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.

View file

@ -1,175 +1,175 @@
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004
http://www.apache.org/licenses/ http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions. 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, "License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document. and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by "Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License. the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all "Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition, control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the "control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity. outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity "You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License. exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, "Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation including but not limited to software source code, documentation
source, and configuration files. source, and configuration files.
"Object" form shall mean any form resulting from mechanical "Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation, not limited to compiled object code, generated documentation,
and conversions to other media types. and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or "Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work copyright notice that is included in or attached to the work
(an example is provided in the Appendix below). (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object "Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of, separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof. the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including "Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted" the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution." designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity "Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work. subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of 2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of, copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form. Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of 3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made, (except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work, use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s) Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate granted to You under this License for that Work shall terminate
as of the date such litigation is filed. as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the 4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You modifications, and in Source or Object form, provided that You
meet the following conditions: meet the following conditions:
(a) You must give any other recipients of the Work or (a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices (b) You must cause any modified files to carry prominent notices
stating that You changed the files; and stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works (c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work, attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of excluding those notices that do not pertain to any part of
the Derivative Works; and the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its (d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or, documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed that such additional attribution notices cannot be construed
as modifying the License. as modifying the License.
You may add Your own copyright statement to Your modifications and You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use, for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License. the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, 5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions. this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions. with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade 6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor, names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file. origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or 7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS, Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License. risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, 8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise, whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill, Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages. has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing 9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer, the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity, and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify, of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability. of your accepting any such warranty or additional liability.

View file

@ -1 +1 @@
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

View file

@ -1,117 +0,0 @@
# AWS Common Runtime PHP bindings
## Requirements
* PHP 5.5+ on UNIX platforms, 7.2+ on Windows
* CMake 3.x
* GCC 4.4+, clang 3.8+ on UNIX, Visual Studio build tools on Windows
* Tests require [Composer](https://getcomposer.org)
## Installing with Composer and PECL
The package has two different package published to [composer](https://packagist.org/packages/aws/aws-crt-php) and [PECL](https://pecl.php.net/package/awscrt).
On UNIX, you can get the package from package manager or build from source:
```
pecl install awscrt
composer require aws/aws-crt-php
```
On Windows, you need to build from source as instruction written below for the native extension `php_awscrt.dll` . And, follow https://www.php.net/manual/en/install.pecl.windows.php#install.pecl.windows.loading to load extension. After that:
```
composer require aws/aws-crt-php
```
## Building from Github source
```sh
$ git clone --recursive https://github.com/awslabs/aws-crt-php.git
$ cd aws-crt-php
$ phpize
$ ./configure
$ make
$ ./dev-scripts/run_tests.sh
```
## Building on Windows
### Requirements for Windows
* Ensure you have the [windows PHP SDK](https://github.com/microsoft/php-sdk-binary-tools) (this example assumes installation of the SDK to C:\php-sdk and that you've checked out the PHP source to php-src within the build directory) and it works well on your machine.
* Ensure you have "Development package (SDK to develop PHP extensions)" and PHP available from your system path. You can download them from https://windows.php.net/download/. You can check if they are available by running `phpize -v` and `php -v`
### Instructions
From Command Prompt (not powershell). The instruction is based on Visual Studio 2019 on 64bit Windows.
```bat
> git clone --recursive https://github.com/awslabs/aws-crt-php.git
> git clone https://github.com/microsoft/php-sdk-binary-tools.git C:\php-sdk
> C:\php-sdk\phpsdk-vs16-x64.bat
C:\php-sdk\
$ cd <your-path-to-aws-crt-php>
<your-path-to-aws-crt-php>\
$ phpize
# --with-prefix only required when your php runtime in system path is different than the runtime you wish to use.
<your-path-to-aws-crt-php>\
$ configure --enable-awscrt=shared --with-prefix=<your-path-to-php-prefix>
<your-path-to-aws-crt-php>\
$ nmake
<your-path-to-aws-crt-php>\
$ nmake generate-php-ini
# check .\php-win.ini, it now has the full path to php_awscrt.dll that you can manually load to your php runtime, or you can run the following command to run tests and load the required native extension for awscrt.
<your-path-to-aws-crt-php>\
$ .\dev-scripts\run_tests.bat <your-path-to-php-binary>
```
Note: for VS2017, Cmake will default to build for Win32, refer to [here](https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2015%202017.html). If you are building for x64 php, you can set environment variable as follow to let cmake pick x64 compiler.
```bat
set CMAKE_GENERATOR=Visual Studio 15 2017
set CMAKE_GENERATOR_PLATFORM=x64
```
## Debugging
Using [PHPBrew](https://github.com/phpbrew/phpbrew) to build/manage multiple versions of PHP is helpful.
Note: You must use a debug build of PHP to debug native extensions.
See the [PHP Internals Book](https://www.phpinternalsbook.com/php7/build_system/building_php.html) for more info
```shell
# PHP 8 example
$ phpbrew install --stdout -j 8 8.0 +default -- CFLAGS=-Wno-error --disable-cgi --enable-debug
# PHP 5.5 example
$ phpbrew install --stdout -j 8 5.5 +default -openssl -mbstring -- CFLAGS="-w -Wno-error" --enable-debug --with-zlib=/usr/local/opt/zlib
$ phpbrew switch php-8.0.6 # or whatever version is current, it'll be at the end of the build output
$ phpize
$ ./configure
$ make CMAKE_BUILD_TYPE=Debug
```
Ensure that the php you launch from your debugger is the result of `which php` , not just
the system default php.
## Security
See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
## Known OpenSSL related issue (Unix only)
* When your php loads a different version of openssl than your system openssl version, awscrt may fail to load or weirdly crash. You can find the openssl version php linked via: `php -i | grep 'OpenSSL'`, and awscrt linked from the build log, which will be `Found OpenSSL: * (found version *)`
The easiest workaround to those issue is to build from source and get aws-lc for awscrt to depend on instead.
TO do that, same instructions as [here](#building-from-github-source), but use `USE_OPENSSL=OFF make` instead of `make`
## License
This project is licensed under the Apache-2.0 License.

View file

@ -1,35 +0,0 @@
{
"name": "aws/aws-crt-php",
"homepage": "https://github.com/awslabs/aws-crt-php",
"description": "AWS Common Runtime for PHP",
"keywords": ["aws","amazon","sdk","crt"],
"type": "library",
"authors": [
{
"name": "AWS SDK Common Runtime Team",
"email": "aws-sdk-common-runtime@amazon.com"
}
],
"minimum-stability": "alpha",
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit":"^4.8.35||^5.6.3||^9.5",
"yoast/phpunit-polyfills": "^1.0"
},
"autoload": {
"classmap": [
"src/"
]
},
"suggest": {
"ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality."
},
"scripts": {
"test": "./dev-scripts/run_tests.sh",
"test-extension": "@test",
"test-win": ".\\dev-scripts\\run_tests.bat"
},
"license": "Apache-2.0"
}

View file

@ -1,46 +1,46 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
import os import os
from pathlib import Path from pathlib import Path
import re import re
from subprocess import list2cmdline, run from subprocess import list2cmdline, run
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
CLANG_FORMAT_VERSION = '18.1.6' CLANG_FORMAT_VERSION = '18.1.6'
INCLUDE_REGEX = re.compile(r'^ext/.*\.(c|h|inl)$') INCLUDE_REGEX = re.compile(r'^ext/.*\.(c|h|inl)$')
EXCLUDE_REGEX = re.compile(r'^$') EXCLUDE_REGEX = re.compile(r'^$')
arg_parser = argparse.ArgumentParser(description="Check with clang-format") arg_parser = argparse.ArgumentParser(description="Check with clang-format")
arg_parser.add_argument('-i', '--inplace-edit', action='store_true', arg_parser.add_argument('-i', '--inplace-edit', action='store_true',
help="Edit files inplace") help="Edit files inplace")
args = arg_parser.parse_args() args = arg_parser.parse_args()
os.chdir(Path(__file__).parent) os.chdir(Path(__file__).parent)
# create file containing list of all files to format # create file containing list of all files to format
filepaths_file = NamedTemporaryFile(delete=False) filepaths_file = NamedTemporaryFile(delete=False)
for dirpath, dirnames, filenames in os.walk('.'): for dirpath, dirnames, filenames in os.walk('.'):
for filename in filenames: for filename in filenames:
# our regexes expect filepath to use forward slash # our regexes expect filepath to use forward slash
filepath = Path(dirpath, filename).as_posix() filepath = Path(dirpath, filename).as_posix()
if not INCLUDE_REGEX.match(filepath): if not INCLUDE_REGEX.match(filepath):
continue continue
if EXCLUDE_REGEX.match(filepath): if EXCLUDE_REGEX.match(filepath):
continue continue
filepaths_file.write(f"{filepath}\n".encode()) filepaths_file.write(f"{filepath}\n".encode())
filepaths_file.close() filepaths_file.close()
# use pipx to run clang-format from PyPI # use pipx to run clang-format from PyPI
# this is a simple way to run the same clang-format version regardless of OS # this is a simple way to run the same clang-format version regardless of OS
cmd = ['pipx', 'run', f'clang-format=={CLANG_FORMAT_VERSION}', cmd = ['pipx', 'run', f'clang-format=={CLANG_FORMAT_VERSION}',
f'--files={filepaths_file.name}'] f'--files={filepaths_file.name}']
if args.inplace_edit: if args.inplace_edit:
cmd += ['-i'] cmd += ['-i']
else: else:
cmd += ['--Werror', '--dry-run'] cmd += ['--Werror', '--dry-run']
print(f"{Path.cwd()}$ {list2cmdline(cmd)}") print(f"{Path.cwd()}$ {list2cmdline(cmd)}")
if run(cmd).returncode: if run(cmd).returncode:
exit(1) exit(1)

View file

@ -1,69 +1,69 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
use AWS\CRT\NativeResource as NativeResource; use AWS\CRT\NativeResource as NativeResource;
use AWS\CRT\Options as Options; use AWS\CRT\Options as Options;
/** /**
* Represents a set of AWS credentials * Represents a set of AWS credentials
* *
* @param array options: * @param array options:
* - string access_key_id - AWS Access Key Id * - string access_key_id - AWS Access Key Id
* - string secret_access_key - AWS Secret Access Key * - string secret_access_key - AWS Secret Access Key
* - string session_token - Optional STS session token * - string session_token - Optional STS session token
* - int expiration_timepoint_seconds - Optional time to expire these credentials * - int expiration_timepoint_seconds - Optional time to expire these credentials
*/ */
final class AwsCredentials extends NativeResource { final class AwsCredentials extends NativeResource {
static function defaults() { static function defaults() {
return [ return [
'access_key_id' => '', 'access_key_id' => '',
'secret_access_key' => '', 'secret_access_key' => '',
'session_token' => '', 'session_token' => '',
'expiration_timepoint_seconds' => 0, 'expiration_timepoint_seconds' => 0,
]; ];
} }
private $access_key_id; private $access_key_id;
private $secret_access_key; private $secret_access_key;
private $session_token; private $session_token;
private $expiration_timepoint_seconds = 0; private $expiration_timepoint_seconds = 0;
public function __get($name) { public function __get($name) {
return $this->$name; return $this->$name;
} }
function __construct(array $options = []) { function __construct(array $options = []) {
parent::__construct(); parent::__construct();
$options = new Options($options, self::defaults()); $options = new Options($options, self::defaults());
$this->access_key_id = $options->access_key_id->asString(); $this->access_key_id = $options->access_key_id->asString();
$this->secret_access_key = $options->secret_access_key->asString(); $this->secret_access_key = $options->secret_access_key->asString();
$this->session_token = $options->session_token ? $options->session_token->asString() : null; $this->session_token = $options->session_token ? $options->session_token->asString() : null;
$this->expiration_timepoint_seconds = $options->expiration_timepoint_seconds->asInt(); $this->expiration_timepoint_seconds = $options->expiration_timepoint_seconds->asInt();
if (strlen($this->access_key_id) == 0) { if (strlen($this->access_key_id) == 0) {
throw new \InvalidArgumentException("access_key_id must be provided"); throw new \InvalidArgumentException("access_key_id must be provided");
} }
if (strlen($this->secret_access_key) == 0) { if (strlen($this->secret_access_key) == 0) {
throw new \InvalidArgumentException("secret_access_key must be provided"); throw new \InvalidArgumentException("secret_access_key must be provided");
} }
$creds_options = self::$crt->aws_credentials_options_new(); $creds_options = self::$crt->aws_credentials_options_new();
self::$crt->aws_credentials_options_set_access_key_id($creds_options, $this->access_key_id); self::$crt->aws_credentials_options_set_access_key_id($creds_options, $this->access_key_id);
self::$crt->aws_credentials_options_set_secret_access_key($creds_options, $this->secret_access_key); self::$crt->aws_credentials_options_set_secret_access_key($creds_options, $this->secret_access_key);
self::$crt->aws_credentials_options_set_session_token($creds_options, $this->session_token); self::$crt->aws_credentials_options_set_session_token($creds_options, $this->session_token);
self::$crt->aws_credentials_options_set_expiration_timepoint_seconds($creds_options, $this->expiration_timepoint_seconds); self::$crt->aws_credentials_options_set_expiration_timepoint_seconds($creds_options, $this->expiration_timepoint_seconds);
$this->acquire(self::$crt->aws_credentials_new($creds_options)); $this->acquire(self::$crt->aws_credentials_new($creds_options));
self::$crt->aws_credentials_options_release($creds_options); self::$crt->aws_credentials_options_release($creds_options);
} }
function __destruct() { function __destruct() {
self::$crt->aws_credentials_release($this->release()); self::$crt->aws_credentials_release($this->release());
parent::__destruct(); parent::__destruct();
} }
} }

View file

@ -1,23 +1,23 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
use AWS\CRT\NativeResource as NativeResource; use AWS\CRT\NativeResource as NativeResource;
/** /**
* Base class for credentials providers * Base class for credentials providers
*/ */
abstract class CredentialsProvider extends NativeResource { abstract class CredentialsProvider extends NativeResource {
function __construct(array $options = []) { function __construct(array $options = []) {
parent::__construct(); parent::__construct();
} }
function __destruct() { function __destruct() {
self::$crt->credentials_provider_release($this->release()); self::$crt->credentials_provider_release($this->release());
parent::__destruct(); parent::__destruct();
} }
} }

View file

@ -1,43 +1,43 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
use AWS\CRT\IO\InputStream; use AWS\CRT\IO\InputStream;
use AWS\CRT\NativeResource as NativeResource; use AWS\CRT\NativeResource as NativeResource;
class Signable extends NativeResource { class Signable extends NativeResource {
public static function fromHttpRequest($http_message) { public static function fromHttpRequest($http_message) {
return new Signable(function() use ($http_message) { return new Signable(function() use ($http_message) {
return self::$crt->signable_new_from_http_request($http_message->native); return self::$crt->signable_new_from_http_request($http_message->native);
}); });
} }
public static function fromChunk($chunk_stream, $previous_signature="") { public static function fromChunk($chunk_stream, $previous_signature="") {
if (!($chunk_stream instanceof InputStream)) { if (!($chunk_stream instanceof InputStream)) {
$chunk_stream = new InputStream($chunk_stream); $chunk_stream = new InputStream($chunk_stream);
} }
return new Signable(function() use($chunk_stream, $previous_signature) { return new Signable(function() use($chunk_stream, $previous_signature) {
return self::$crt->signable_new_from_chunk($chunk_stream->native, $previous_signature); return self::$crt->signable_new_from_chunk($chunk_stream->native, $previous_signature);
}); });
} }
public static function fromCanonicalRequest($canonical_request) { public static function fromCanonicalRequest($canonical_request) {
return new Signable(function() use($canonical_request) { return new Signable(function() use($canonical_request) {
return self::$crt->signable_new_from_canonical_request($canonical_request); return self::$crt->signable_new_from_canonical_request($canonical_request);
}); });
} }
protected function __construct($ctor) { protected function __construct($ctor) {
parent::__construct(); parent::__construct();
$this->acquire($ctor()); $this->acquire($ctor());
} }
function __destruct() { function __destruct() {
self::$crt->signable_release($this->release()); self::$crt->signable_release($this->release());
parent::__destruct(); parent::__destruct();
} }
} }

View file

@ -1,15 +1,15 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
class SignatureType { class SignatureType {
const HTTP_REQUEST_HEADERS = 0; const HTTP_REQUEST_HEADERS = 0;
const HTTP_REQUEST_QUERY_PARAMS = 1; const HTTP_REQUEST_QUERY_PARAMS = 1;
const HTTP_REQUEST_CHUNK = 2; const HTTP_REQUEST_CHUNK = 2;
const HTTP_REQUEST_EVENT = 3; const HTTP_REQUEST_EVENT = 3;
const CANONICAL_REQUEST_HEADERS = 4; const CANONICAL_REQUEST_HEADERS = 4;
const CANONICAL_REQUEST_QUERY_PARAMS = 5; const CANONICAL_REQUEST_QUERY_PARAMS = 5;
} }

View file

@ -1,11 +1,11 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
class SignedBodyHeaderType { class SignedBodyHeaderType {
const NONE = 0; const NONE = 0;
const X_AMZ_CONTENT_SHA256 = 1; const X_AMZ_CONTENT_SHA256 = 1;
} }

View file

@ -1,22 +1,22 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
use AWS\CRT\NativeResource; use AWS\CRT\NativeResource;
abstract class Signing extends NativeResource { abstract class Signing extends NativeResource {
static function signRequestAws($signable, $signing_config, $on_complete) { static function signRequestAws($signable, $signing_config, $on_complete) {
return self::$crt->sign_request_aws($signable->native, $signing_config->native, return self::$crt->sign_request_aws($signable->native, $signing_config->native,
function($result, $error_code) use ($on_complete) { function($result, $error_code) use ($on_complete) {
$signing_result = SigningResult::fromNative($result); $signing_result = SigningResult::fromNative($result);
$on_complete($signing_result, $error_code); $on_complete($signing_result, $error_code);
}, null); }, null);
} }
static function testVerifySigV4ASigning($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y) { static function testVerifySigV4ASigning($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y) {
return self::$crt->test_verify_sigv4a_signing($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y); return self::$crt->test_verify_sigv4a_signing($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y);
} }
} }

View file

@ -1,11 +1,11 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
class SigningAlgorithm { class SigningAlgorithm {
const SIGv4 = 0; const SIGv4 = 0;
const SIGv4_ASYMMETRIC = 1; const SIGv4_ASYMMETRIC = 1;
} }

View file

@ -1,75 +1,75 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
use AWS\CRT\NativeResource as NativeResource; use AWS\CRT\NativeResource as NativeResource;
use AWS\CRT\Options as Options; use AWS\CRT\Options as Options;
class SigningConfigAWS extends NativeResource { class SigningConfigAWS extends NativeResource {
public static function defaults() { public static function defaults() {
return [ return [
'algorithm' => SigningAlgorithm::SIGv4, 'algorithm' => SigningAlgorithm::SIGv4,
'signature_type' => SignatureType::HTTP_REQUEST_HEADERS, 'signature_type' => SignatureType::HTTP_REQUEST_HEADERS,
'credentials_provider' => null, 'credentials_provider' => null,
'region' => null, 'region' => null,
'service' => null, 'service' => null,
'use_double_uri_encode' => false, 'use_double_uri_encode' => false,
'should_normalize_uri_path' => false, 'should_normalize_uri_path' => false,
'omit_session_token' => false, 'omit_session_token' => false,
'signed_body_value' => null, 'signed_body_value' => null,
'signed_body_header_type' => SignedBodyHeaderType::NONE, 'signed_body_header_type' => SignedBodyHeaderType::NONE,
'expiration_in_seconds' => 0, 'expiration_in_seconds' => 0,
'date' => time(), 'date' => time(),
'should_sign_header' => null, 'should_sign_header' => null,
]; ];
} }
private $options; private $options;
public function __construct(array $options = []) { public function __construct(array $options = []) {
parent::__construct(); parent::__construct();
$this->options = $options = new Options($options, self::defaults()); $this->options = $options = new Options($options, self::defaults());
$sc = $this->acquire(self::$crt->signing_config_aws_new()); $sc = $this->acquire(self::$crt->signing_config_aws_new());
self::$crt->signing_config_aws_set_algorithm($sc, $options->algorithm->asInt()); self::$crt->signing_config_aws_set_algorithm($sc, $options->algorithm->asInt());
self::$crt->signing_config_aws_set_signature_type($sc, $options->signature_type->asInt()); self::$crt->signing_config_aws_set_signature_type($sc, $options->signature_type->asInt());
if ($credentials_provider = $options->credentials_provider->asObject()) { if ($credentials_provider = $options->credentials_provider->asObject()) {
self::$crt->signing_config_aws_set_credentials_provider( self::$crt->signing_config_aws_set_credentials_provider(
$sc, $sc,
$credentials_provider->native); $credentials_provider->native);
} }
self::$crt->signing_config_aws_set_region( self::$crt->signing_config_aws_set_region(
$sc, $options->region->asString()); $sc, $options->region->asString());
self::$crt->signing_config_aws_set_service( self::$crt->signing_config_aws_set_service(
$sc, $options->service->asString()); $sc, $options->service->asString());
self::$crt->signing_config_aws_set_use_double_uri_encode( self::$crt->signing_config_aws_set_use_double_uri_encode(
$sc, $options->use_double_uri_encode->asBool()); $sc, $options->use_double_uri_encode->asBool());
self::$crt->signing_config_aws_set_should_normalize_uri_path( self::$crt->signing_config_aws_set_should_normalize_uri_path(
$sc, $options->should_normalize_uri_path->asBool()); $sc, $options->should_normalize_uri_path->asBool());
self::$crt->signing_config_aws_set_omit_session_token( self::$crt->signing_config_aws_set_omit_session_token(
$sc, $options->omit_session_token->asBool()); $sc, $options->omit_session_token->asBool());
self::$crt->signing_config_aws_set_signed_body_value( self::$crt->signing_config_aws_set_signed_body_value(
$sc, $options->signed_body_value->asString()); $sc, $options->signed_body_value->asString());
self::$crt->signing_config_aws_set_signed_body_header_type( self::$crt->signing_config_aws_set_signed_body_header_type(
$sc, $options->signed_body_header_type->asInt()); $sc, $options->signed_body_header_type->asInt());
self::$crt->signing_config_aws_set_expiration_in_seconds( self::$crt->signing_config_aws_set_expiration_in_seconds(
$sc, $options->expiration_in_seconds->asInt()); $sc, $options->expiration_in_seconds->asInt());
self::$crt->signing_config_aws_set_date($sc, $options->date->asInt()); self::$crt->signing_config_aws_set_date($sc, $options->date->asInt());
if ($should_sign_header = $options->should_sign_header->asCallable()) { if ($should_sign_header = $options->should_sign_header->asCallable()) {
self::$crt->signing_config_aws_set_should_sign_header_fn($sc, $should_sign_header); self::$crt->signing_config_aws_set_should_sign_header_fn($sc, $should_sign_header);
} }
} }
function __destruct() function __destruct()
{ {
self::$crt->signing_config_aws_release($this->release()); self::$crt->signing_config_aws_release($this->release());
parent::__destruct(); parent::__destruct();
} }
public function __get($name) { public function __get($name) {
return $this->options->get($name); return $this->options->get($name);
} }
} }

View file

@ -1,33 +1,33 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
use AWS\CRT\NativeResource; use AWS\CRT\NativeResource;
use AWS\CRT\HTTP\Request; use AWS\CRT\HTTP\Request;
class SigningResult extends NativeResource { class SigningResult extends NativeResource {
protected function __construct($native) { protected function __construct($native) {
parent::__construct(); parent::__construct();
$this->acquire($native); $this->acquire($native);
} }
function __destruct() { function __destruct() {
// No destruction necessary, SigningResults are transient, just release // No destruction necessary, SigningResults are transient, just release
$this->release(); $this->release();
parent::__destruct(); parent::__destruct();
} }
public static function fromNative($ptr) { public static function fromNative($ptr) {
return new SigningResult($ptr); return new SigningResult($ptr);
} }
public function applyToHttpRequest(&$http_request) { public function applyToHttpRequest(&$http_request) {
self::$crt->signing_result_apply_to_http_request($this->native, $http_request->native); self::$crt->signing_result_apply_to_http_request($this->native, $http_request->native);
// Update http_request from native // Update http_request from native
$http_request = Request::unmarshall($http_request->toBlob()); $http_request = Request::unmarshall($http_request->toBlob());
} }
} }

View file

@ -1,35 +1,35 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Auth; namespace AWS\CRT\Auth;
/** /**
* Provides a static set of AWS credentials * Provides a static set of AWS credentials
* *
* @param array options: * @param array options:
* - string access_key_id - AWS Access Key Id * - string access_key_id - AWS Access Key Id
* - string secret_access_key - AWS Secret Access Key * - string secret_access_key - AWS Secret Access Key
* - string session_token - Optional STS session token * - string session_token - Optional STS session token
*/ */
final class StaticCredentialsProvider extends CredentialsProvider { final class StaticCredentialsProvider extends CredentialsProvider {
private $credentials; private $credentials;
public function __get($name) { public function __get($name) {
return $this->$name; return $this->$name;
} }
function __construct(array $options = []) { function __construct(array $options = []) {
parent::__construct(); parent::__construct();
$this->credentials = new AwsCredentials($options); $this->credentials = new AwsCredentials($options);
$provider_options = self::$crt->credentials_provider_static_options_new(); $provider_options = self::$crt->credentials_provider_static_options_new();
self::$crt->credentials_provider_static_options_set_access_key_id($provider_options, $this->credentials->access_key_id); self::$crt->credentials_provider_static_options_set_access_key_id($provider_options, $this->credentials->access_key_id);
self::$crt->credentials_provider_static_options_set_secret_access_key($provider_options, $this->credentials->secret_access_key); self::$crt->credentials_provider_static_options_set_secret_access_key($provider_options, $this->credentials->secret_access_key);
self::$crt->credentials_provider_static_options_set_session_token($provider_options, $this->credentials->session_token); self::$crt->credentials_provider_static_options_set_session_token($provider_options, $this->credentials->session_token);
$this->acquire(self::$crt->credentials_provider_static_new($provider_options)); $this->acquire(self::$crt->credentials_provider_static_new($provider_options));
self::$crt->credentials_provider_static_options_release($provider_options); self::$crt->credentials_provider_static_options_release($provider_options);
} }
} }

View file

@ -1,358 +1,358 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT; namespace AWS\CRT;
use AWS\CRT\Internal\Extension; use AWS\CRT\Internal\Extension;
use \RuntimeException; use \RuntimeException;
/** /**
* Wrapper for the interface to the CRT. There only ever needs to be one of these, but * Wrapper for the interface to the CRT. There only ever needs to be one of these, but
* additional instances won't cost anything other than their memory. * additional instances won't cost anything other than their memory.
* Creating an instance of any NativeResource will activate the CRT binding. User code * Creating an instance of any NativeResource will activate the CRT binding. User code
* should only need to create one of these if they are only accessing CRT:: static functions. * should only need to create one of these if they are only accessing CRT:: static functions.
*/ */
final class CRT { final class CRT {
private static $impl = null; private static $impl = null;
private static $refcount = 0; private static $refcount = 0;
function __construct() { function __construct() {
if (is_null(self::$impl)) { if (is_null(self::$impl)) {
try { try {
self::$impl = new Extension(); self::$impl = new Extension();
} catch (RuntimeException $rex) { } catch (RuntimeException $rex) {
throw new RuntimeException("Unable to initialize AWS CRT via awscrt extension: \n$rex", -1); throw new RuntimeException("Unable to initialize AWS CRT via awscrt extension: \n$rex", -1);
} }
} }
++self::$refcount; ++self::$refcount;
} }
function __destruct() { function __destruct() {
if (--self::$refcount == 0) { if (--self::$refcount == 0) {
self::$impl = null; self::$impl = null;
} }
} }
/** /**
* @return bool whether or not the CRT is currently loaded * @return bool whether or not the CRT is currently loaded
*/ */
public static function isLoaded() { public static function isLoaded() {
return !is_null(self::$impl); return !is_null(self::$impl);
} }
/** /**
* @return bool whether or not the CRT is available via one of the possible backends * @return bool whether or not the CRT is available via one of the possible backends
*/ */
public static function isAvailable() { public static function isAvailable() {
try { try {
new CRT(); new CRT();
return true; return true;
} catch (RuntimeException $ex) { } catch (RuntimeException $ex) {
return false; return false;
} }
} }
/** /**
* @return integer last error code reported within the CRT * @return integer last error code reported within the CRT
*/ */
public static function last_error() { public static function last_error() {
return self::$impl->aws_crt_last_error(); return self::$impl->aws_crt_last_error();
} }
/** /**
* @param integer $error Error code from the CRT, usually delivered via callback or {@see last_error} * @param integer $error Error code from the CRT, usually delivered via callback or {@see last_error}
* @return string Human-readable description of the provided error code * @return string Human-readable description of the provided error code
*/ */
public static function error_str($error) { public static function error_str($error) {
return self::$impl->aws_crt_error_str((int) $error); return self::$impl->aws_crt_error_str((int) $error);
} }
/** /**
* @param integer $error Error code from the CRT, usually delivered via callback or {@see last_error} * @param integer $error Error code from the CRT, usually delivered via callback or {@see last_error}
* @return string Name/enum identifier for the provided error code * @return string Name/enum identifier for the provided error code
*/ */
public static function error_name($error) { public static function error_name($error) {
return self::$impl->aws_crt_error_name((int) $error); return self::$impl->aws_crt_error_name((int) $error);
} }
public static function log_to_stdout() { public static function log_to_stdout() {
return self::$impl->aws_crt_log_to_stdout(); return self::$impl->aws_crt_log_to_stdout();
} }
public static function log_to_stderr() { public static function log_to_stderr() {
return self::$impl->aws_crt_log_to_stderr(); return self::$impl->aws_crt_log_to_stderr();
} }
public static function log_to_file($filename) { public static function log_to_file($filename) {
return self::$impl->aws_crt_log_to_file($filename); return self::$impl->aws_crt_log_to_file($filename);
} }
public static function log_to_stream($stream) { public static function log_to_stream($stream) {
return self::$impl->aws_crt_log_to_stream($stream); return self::$impl->aws_crt_log_to_stream($stream);
} }
public static function log_set_level($level) { public static function log_set_level($level) {
return self::$impl->aws_crt_log_set_level($level); return self::$impl->aws_crt_log_set_level($level);
} }
public static function log_stop() { public static function log_stop() {
return self::$impl->aws_crt_log_stop(); return self::$impl->aws_crt_log_stop();
} }
public static function log_message($level, $message) { public static function log_message($level, $message) {
return self::$impl->aws_crt_log_message($level, $message); return self::$impl->aws_crt_log_message($level, $message);
} }
/** /**
* @return object Pointer to native event_loop_group_options * @return object Pointer to native event_loop_group_options
*/ */
function event_loop_group_options_new() { function event_loop_group_options_new() {
return self::$impl->aws_crt_event_loop_group_options_new(); return self::$impl->aws_crt_event_loop_group_options_new();
} }
/** /**
* @param object $elg_options Pointer to native event_loop_group_options * @param object $elg_options Pointer to native event_loop_group_options
*/ */
function event_loop_group_options_release($elg_options) { function event_loop_group_options_release($elg_options) {
self::$impl->aws_crt_event_loop_group_options_release($elg_options); self::$impl->aws_crt_event_loop_group_options_release($elg_options);
} }
/** /**
* @param object $elg_options Pointer to native event_loop_group_options * @param object $elg_options Pointer to native event_loop_group_options
* @param integer $max_threads Maximum number of threads to allow the event loop group to use, default: 0/1 per CPU core * @param integer $max_threads Maximum number of threads to allow the event loop group to use, default: 0/1 per CPU core
*/ */
function event_loop_group_options_set_max_threads($elg_options, $max_threads) { function event_loop_group_options_set_max_threads($elg_options, $max_threads) {
self::$impl->aws_crt_event_loop_group_options_set_max_threads($elg_options, (int)$max_threads); self::$impl->aws_crt_event_loop_group_options_set_max_threads($elg_options, (int)$max_threads);
} }
/** /**
* @param object Pointer to event_loop_group_options, {@see event_loop_group_options_new} * @param object Pointer to event_loop_group_options, {@see event_loop_group_options_new}
* @return object Pointer to the new event loop group * @return object Pointer to the new event loop group
*/ */
function event_loop_group_new($options) { function event_loop_group_new($options) {
return self::$impl->aws_crt_event_loop_group_new($options); return self::$impl->aws_crt_event_loop_group_new($options);
} }
/** /**
* @param object $elg Pointer to the event loop group to release * @param object $elg Pointer to the event loop group to release
*/ */
function event_loop_group_release($elg) { function event_loop_group_release($elg) {
self::$impl->aws_crt_event_loop_group_release($elg); self::$impl->aws_crt_event_loop_group_release($elg);
} }
/** /**
* return object Pointer to native AWS credentials options * return object Pointer to native AWS credentials options
*/ */
function aws_credentials_options_new() { function aws_credentials_options_new() {
return self::$impl->aws_crt_credentials_options_new(); return self::$impl->aws_crt_credentials_options_new();
} }
function aws_credentials_options_release($options) { function aws_credentials_options_release($options) {
self::$impl->aws_crt_credentials_options_release($options); self::$impl->aws_crt_credentials_options_release($options);
} }
function aws_credentials_options_set_access_key_id($options, $access_key_id) { function aws_credentials_options_set_access_key_id($options, $access_key_id) {
self::$impl->aws_crt_credentials_options_set_access_key_id($options, $access_key_id); self::$impl->aws_crt_credentials_options_set_access_key_id($options, $access_key_id);
} }
function aws_credentials_options_set_secret_access_key($options, $secret_access_key) { function aws_credentials_options_set_secret_access_key($options, $secret_access_key) {
self::$impl->aws_crt_credentials_options_set_secret_access_key($options, $secret_access_key); self::$impl->aws_crt_credentials_options_set_secret_access_key($options, $secret_access_key);
} }
function aws_credentials_options_set_session_token($options, $session_token) { function aws_credentials_options_set_session_token($options, $session_token) {
self::$impl->aws_crt_credentials_options_set_session_token($options, $session_token); self::$impl->aws_crt_credentials_options_set_session_token($options, $session_token);
} }
function aws_credentials_options_set_expiration_timepoint_seconds($options, $expiration_timepoint_seconds) { function aws_credentials_options_set_expiration_timepoint_seconds($options, $expiration_timepoint_seconds) {
self::$impl->aws_crt_credentials_options_set_expiration_timepoint_seconds($options, $expiration_timepoint_seconds); self::$impl->aws_crt_credentials_options_set_expiration_timepoint_seconds($options, $expiration_timepoint_seconds);
} }
function aws_credentials_new($options) { function aws_credentials_new($options) {
return self::$impl->aws_crt_credentials_new($options); return self::$impl->aws_crt_credentials_new($options);
} }
function aws_credentials_release($credentials) { function aws_credentials_release($credentials) {
self::$impl->aws_crt_credentials_release($credentials); self::$impl->aws_crt_credentials_release($credentials);
} }
function credentials_provider_release($provider) { function credentials_provider_release($provider) {
self::$impl->aws_crt_credentials_provider_release($provider); self::$impl->aws_crt_credentials_provider_release($provider);
} }
function credentials_provider_static_options_new() { function credentials_provider_static_options_new() {
return self::$impl->aws_crt_credentials_provider_static_options_new(); return self::$impl->aws_crt_credentials_provider_static_options_new();
} }
function credentials_provider_static_options_release($options) { function credentials_provider_static_options_release($options) {
self::$impl->aws_crt_credentials_provider_static_options_release($options); self::$impl->aws_crt_credentials_provider_static_options_release($options);
} }
function credentials_provider_static_options_set_access_key_id($options, $access_key_id) { function credentials_provider_static_options_set_access_key_id($options, $access_key_id) {
self::$impl->aws_crt_credentials_provider_static_options_set_access_key_id($options, $access_key_id); self::$impl->aws_crt_credentials_provider_static_options_set_access_key_id($options, $access_key_id);
} }
function credentials_provider_static_options_set_secret_access_key($options, $secret_access_key) { function credentials_provider_static_options_set_secret_access_key($options, $secret_access_key) {
self::$impl->aws_crt_credentials_provider_static_options_set_secret_access_key($options, $secret_access_key); self::$impl->aws_crt_credentials_provider_static_options_set_secret_access_key($options, $secret_access_key);
} }
function credentials_provider_static_options_set_session_token($options, $session_token) { function credentials_provider_static_options_set_session_token($options, $session_token) {
self::$impl->aws_crt_credentials_provider_static_options_set_session_token($options, $session_token); self::$impl->aws_crt_credentials_provider_static_options_set_session_token($options, $session_token);
} }
function credentials_provider_static_new($options) { function credentials_provider_static_new($options) {
return self::$impl->aws_crt_credentials_provider_static_new($options); return self::$impl->aws_crt_credentials_provider_static_new($options);
} }
function input_stream_options_new() { function input_stream_options_new() {
return self::$impl->aws_crt_input_stream_options_new(); return self::$impl->aws_crt_input_stream_options_new();
} }
function input_stream_options_release($options) { function input_stream_options_release($options) {
self::$impl->aws_crt_input_stream_options_release($options); self::$impl->aws_crt_input_stream_options_release($options);
} }
function input_stream_options_set_user_data($options, $user_data) { function input_stream_options_set_user_data($options, $user_data) {
self::$impl->aws_crt_input_stream_options_set_user_data($options, $user_data); self::$impl->aws_crt_input_stream_options_set_user_data($options, $user_data);
} }
function input_stream_new($options) { function input_stream_new($options) {
return self::$impl->aws_crt_input_stream_new($options); return self::$impl->aws_crt_input_stream_new($options);
} }
function input_stream_release($stream) { function input_stream_release($stream) {
self::$impl->aws_crt_input_stream_release($stream); self::$impl->aws_crt_input_stream_release($stream);
} }
function input_stream_seek($stream, $offset, $basis) { function input_stream_seek($stream, $offset, $basis) {
return self::$impl->aws_crt_input_stream_seek($stream, $offset, $basis); return self::$impl->aws_crt_input_stream_seek($stream, $offset, $basis);
} }
function input_stream_read($stream, $length) { function input_stream_read($stream, $length) {
return self::$impl->aws_crt_input_stream_read($stream, $length); return self::$impl->aws_crt_input_stream_read($stream, $length);
} }
function input_stream_eof($stream) { function input_stream_eof($stream) {
return self::$impl->aws_crt_input_stream_eof($stream); return self::$impl->aws_crt_input_stream_eof($stream);
} }
function input_stream_get_length($stream) { function input_stream_get_length($stream) {
return self::$impl->aws_crt_input_stream_get_length($stream); return self::$impl->aws_crt_input_stream_get_length($stream);
} }
function http_message_new_from_blob($blob) { function http_message_new_from_blob($blob) {
return self::$impl->aws_crt_http_message_new_from_blob($blob); return self::$impl->aws_crt_http_message_new_from_blob($blob);
} }
function http_message_to_blob($message) { function http_message_to_blob($message) {
return self::$impl->aws_crt_http_message_to_blob($message); return self::$impl->aws_crt_http_message_to_blob($message);
} }
function http_message_release($message) { function http_message_release($message) {
self::$impl->aws_crt_http_message_release($message); self::$impl->aws_crt_http_message_release($message);
} }
function signing_config_aws_new() { function signing_config_aws_new() {
return self::$impl->aws_crt_signing_config_aws_new(); return self::$impl->aws_crt_signing_config_aws_new();
} }
function signing_config_aws_release($signing_config) { function signing_config_aws_release($signing_config) {
return self::$impl->aws_crt_signing_config_aws_release($signing_config); return self::$impl->aws_crt_signing_config_aws_release($signing_config);
} }
function signing_config_aws_set_algorithm($signing_config, $algorithm) { function signing_config_aws_set_algorithm($signing_config, $algorithm) {
self::$impl->aws_crt_signing_config_aws_set_algorithm($signing_config, (int)$algorithm); self::$impl->aws_crt_signing_config_aws_set_algorithm($signing_config, (int)$algorithm);
} }
function signing_config_aws_set_signature_type($signing_config, $signature_type) { function signing_config_aws_set_signature_type($signing_config, $signature_type) {
self::$impl->aws_crt_signing_config_aws_set_signature_type($signing_config, (int)$signature_type); self::$impl->aws_crt_signing_config_aws_set_signature_type($signing_config, (int)$signature_type);
} }
function signing_config_aws_set_credentials_provider($signing_config, $credentials_provider) { function signing_config_aws_set_credentials_provider($signing_config, $credentials_provider) {
self::$impl->aws_crt_signing_config_aws_set_credentials_provider($signing_config, $credentials_provider); self::$impl->aws_crt_signing_config_aws_set_credentials_provider($signing_config, $credentials_provider);
} }
function signing_config_aws_set_region($signing_config, $region) { function signing_config_aws_set_region($signing_config, $region) {
self::$impl->aws_crt_signing_config_aws_set_region($signing_config, $region); self::$impl->aws_crt_signing_config_aws_set_region($signing_config, $region);
} }
function signing_config_aws_set_service($signing_config, $service) { function signing_config_aws_set_service($signing_config, $service) {
self::$impl->aws_crt_signing_config_aws_set_service($signing_config, $service); self::$impl->aws_crt_signing_config_aws_set_service($signing_config, $service);
} }
function signing_config_aws_set_use_double_uri_encode($signing_config, $use_double_uri_encode) { function signing_config_aws_set_use_double_uri_encode($signing_config, $use_double_uri_encode) {
self::$impl->aws_crt_signing_config_aws_set_use_double_uri_encode($signing_config, $use_double_uri_encode); self::$impl->aws_crt_signing_config_aws_set_use_double_uri_encode($signing_config, $use_double_uri_encode);
} }
function signing_config_aws_set_should_normalize_uri_path($signing_config, $should_normalize_uri_path) { function signing_config_aws_set_should_normalize_uri_path($signing_config, $should_normalize_uri_path) {
self::$impl->aws_crt_signing_config_aws_set_should_normalize_uri_path($signing_config, $should_normalize_uri_path); self::$impl->aws_crt_signing_config_aws_set_should_normalize_uri_path($signing_config, $should_normalize_uri_path);
} }
function signing_config_aws_set_omit_session_token($signing_config, $omit_session_token) { function signing_config_aws_set_omit_session_token($signing_config, $omit_session_token) {
self::$impl->aws_crt_signing_config_aws_set_omit_session_token($signing_config, $omit_session_token); self::$impl->aws_crt_signing_config_aws_set_omit_session_token($signing_config, $omit_session_token);
} }
function signing_config_aws_set_signed_body_value($signing_config, $signed_body_value) { function signing_config_aws_set_signed_body_value($signing_config, $signed_body_value) {
self::$impl->aws_crt_signing_config_aws_set_signed_body_value($signing_config, $signed_body_value); self::$impl->aws_crt_signing_config_aws_set_signed_body_value($signing_config, $signed_body_value);
} }
function signing_config_aws_set_signed_body_header_type($signing_config, $signed_body_header_type) { function signing_config_aws_set_signed_body_header_type($signing_config, $signed_body_header_type) {
self::$impl->aws_crt_signing_config_aws_set_signed_body_header_type($signing_config, $signed_body_header_type); self::$impl->aws_crt_signing_config_aws_set_signed_body_header_type($signing_config, $signed_body_header_type);
} }
function signing_config_aws_set_expiration_in_seconds($signing_config, $expiration_in_seconds) { function signing_config_aws_set_expiration_in_seconds($signing_config, $expiration_in_seconds) {
self::$impl->aws_crt_signing_config_aws_set_expiration_in_seconds($signing_config, $expiration_in_seconds); self::$impl->aws_crt_signing_config_aws_set_expiration_in_seconds($signing_config, $expiration_in_seconds);
} }
function signing_config_aws_set_date($signing_config, $timestamp) { function signing_config_aws_set_date($signing_config, $timestamp) {
self::$impl->aws_crt_signing_config_aws_set_date($signing_config, $timestamp); self::$impl->aws_crt_signing_config_aws_set_date($signing_config, $timestamp);
} }
function signing_config_aws_set_should_sign_header_fn($signing_config, $should_sign_header_fn) { function signing_config_aws_set_should_sign_header_fn($signing_config, $should_sign_header_fn) {
self::$impl->aws_crt_signing_config_aws_set_should_sign_header_fn($signing_config, $should_sign_header_fn); self::$impl->aws_crt_signing_config_aws_set_should_sign_header_fn($signing_config, $should_sign_header_fn);
} }
function signable_new_from_http_request($http_message) { function signable_new_from_http_request($http_message) {
return self::$impl->aws_crt_signable_new_from_http_request($http_message); return self::$impl->aws_crt_signable_new_from_http_request($http_message);
} }
function signable_new_from_chunk($chunk_stream, $previous_signature) { function signable_new_from_chunk($chunk_stream, $previous_signature) {
return self::$impl->aws_crt_signable_new_from_chunk($chunk_stream, $previous_signature); return self::$impl->aws_crt_signable_new_from_chunk($chunk_stream, $previous_signature);
} }
function signable_new_from_canonical_request($canonical_request) { function signable_new_from_canonical_request($canonical_request) {
return self::$impl->aws_crt_signable_new_from_canonical_request($canonical_request); return self::$impl->aws_crt_signable_new_from_canonical_request($canonical_request);
} }
function signable_release($signable) { function signable_release($signable) {
self::$impl->aws_crt_signable_release($signable); self::$impl->aws_crt_signable_release($signable);
} }
function signing_result_release($signing_result) { function signing_result_release($signing_result) {
self::$impl->aws_crt_signing_result_release($signing_result); self::$impl->aws_crt_signing_result_release($signing_result);
} }
function signing_result_apply_to_http_request($signing_result, $http_message) { function signing_result_apply_to_http_request($signing_result, $http_message) {
return self::$impl->aws_crt_signing_result_apply_to_http_request( return self::$impl->aws_crt_signing_result_apply_to_http_request(
$signing_result, $http_message); $signing_result, $http_message);
} }
function sign_request_aws($signable, $signing_config, $on_complete, $user_data) { function sign_request_aws($signable, $signing_config, $on_complete, $user_data) {
return self::$impl->aws_crt_sign_request_aws($signable, $signing_config, $on_complete, $user_data); return self::$impl->aws_crt_sign_request_aws($signable, $signing_config, $on_complete, $user_data);
} }
function test_verify_sigv4a_signing($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y) { function test_verify_sigv4a_signing($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y) {
return self::$impl->aws_crt_test_verify_sigv4a_signing($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y); return self::$impl->aws_crt_test_verify_sigv4a_signing($signable, $signing_config, $expected_canonical_request, $signature, $ecc_key_pub_x, $ecc_key_pub_y);
} }
public static function crc32($input, $previous = 0) { public static function crc32($input, $previous = 0) {
return self::$impl->aws_crt_crc32($input, $previous); return self::$impl->aws_crt_crc32($input, $previous);
} }
public static function crc32c($input, $previous = 0) { public static function crc32c($input, $previous = 0) {
return self::$impl->aws_crt_crc32c($input, $previous); return self::$impl->aws_crt_crc32c($input, $previous);
} }
} }

View file

@ -1,50 +1,50 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\HTTP; namespace AWS\CRT\HTTP;
use AWS\CRT\Internal\Encoding; use AWS\CRT\Internal\Encoding;
final class Headers { final class Headers {
private $headers; private $headers;
public function __construct($headers = []) { public function __construct($headers = []) {
$this->headers = $headers; $this->headers = $headers;
} }
public static function marshall($headers) { public static function marshall($headers) {
$buf = ""; $buf = "";
foreach ($headers->headers as $header => $value) { foreach ($headers->headers as $header => $value) {
$buf .= Encoding::encodeString($header); $buf .= Encoding::encodeString($header);
$buf .= Encoding::encodeString($value); $buf .= Encoding::encodeString($value);
} }
return $buf; return $buf;
} }
public static function unmarshall($buf) { public static function unmarshall($buf) {
$strings = Encoding::readStrings($buf); $strings = Encoding::readStrings($buf);
$headers = []; $headers = [];
for ($idx = 0; $idx < count($strings);) { for ($idx = 0; $idx < count($strings);) {
$headers[$strings[$idx++]] = $strings[$idx++]; $headers[$strings[$idx++]] = $strings[$idx++];
} }
return new Headers($headers); return new Headers($headers);
} }
public function count() { public function count() {
return count($this->headers); return count($this->headers);
} }
public function get($header) { public function get($header) {
return isset($this->headers[$header]) ? $this->headers[$header] : null; return isset($this->headers[$header]) ? $this->headers[$header] : null;
} }
public function set($header, $value) { public function set($header, $value) {
$this->headers[$header] = $value; $this->headers[$header] = $value;
} }
public function toArray() { public function toArray() {
return $this->headers; return $this->headers;
} }
} }

View file

@ -1,95 +1,95 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\HTTP; namespace AWS\CRT\HTTP;
use AWS\CRT\NativeResource; use AWS\CRT\NativeResource;
use AWS\CRT\Internal\Encoding; use AWS\CRT\Internal\Encoding;
abstract class Message extends NativeResource { abstract class Message extends NativeResource {
private $method; private $method;
private $path; private $path;
private $query; private $query;
private $headers; private $headers;
public function __construct($method, $path, $query = [], $headers = []) { public function __construct($method, $path, $query = [], $headers = []) {
parent::__construct(); parent::__construct();
$this->method = $method; $this->method = $method;
$this->path = $path; $this->path = $path;
$this->query = $query; $this->query = $query;
$this->headers = new Headers($headers); $this->headers = new Headers($headers);
$this->acquire(self::$crt->http_message_new_from_blob(self::marshall($this))); $this->acquire(self::$crt->http_message_new_from_blob(self::marshall($this)));
} }
public function __destruct() { public function __destruct() {
self::$crt->http_message_release($this->release()); self::$crt->http_message_release($this->release());
parent::__destruct(); parent::__destruct();
} }
public function toBlob() { public function toBlob() {
return self::$crt->http_message_to_blob($this->native); return self::$crt->http_message_to_blob($this->native);
} }
protected static function marshall($msg) { protected static function marshall($msg) {
$buf = ""; $buf = "";
$buf .= Encoding::encodeString($msg->method); $buf .= Encoding::encodeString($msg->method);
$buf .= Encoding::encodeString($msg->pathAndQuery()); $buf .= Encoding::encodeString($msg->pathAndQuery());
$buf .= Headers::marshall($msg->headers); $buf .= Headers::marshall($msg->headers);
return $buf; return $buf;
} }
protected static function _unmarshall($buf, $class=Message::class) { protected static function _unmarshall($buf, $class=Message::class) {
$method = Encoding::readString($buf); $method = Encoding::readString($buf);
$path_and_query = Encoding::readString($buf); $path_and_query = Encoding::readString($buf);
$parts = explode("?", $path_and_query, 2); $parts = explode("?", $path_and_query, 2);
$path = isset($parts[0]) ? $parts[0] : ""; $path = isset($parts[0]) ? $parts[0] : "";
$query = isset($parts[1]) ? $parts[1] : ""; $query = isset($parts[1]) ? $parts[1] : "";
$headers = Headers::unmarshall($buf); $headers = Headers::unmarshall($buf);
// Turn query params back into a dictionary // Turn query params back into a dictionary
if (strlen($query)) { if (strlen($query)) {
$query = rawurldecode($query); $query = rawurldecode($query);
$query = explode("&", $query); $query = explode("&", $query);
$query = array_reduce($query, function($params, $pair) { $query = array_reduce($query, function($params, $pair) {
list($param, $value) = explode("=", $pair, 2); list($param, $value) = explode("=", $pair, 2);
$params[$param] = $value; $params[$param] = $value;
return $params; return $params;
}, []); }, []);
} else { } else {
$query = []; $query = [];
} }
return new $class($method, $path, $query, $headers->toArray()); return new $class($method, $path, $query, $headers->toArray());
} }
public function pathAndQuery() { public function pathAndQuery() {
$path = $this->path; $path = $this->path;
$queries = []; $queries = [];
foreach ($this->query as $param => $value) { foreach ($this->query as $param => $value) {
$queries []= urlencode($param) . "=" . urlencode($value); $queries []= urlencode($param) . "=" . urlencode($value);
} }
$query = implode("&", $queries); $query = implode("&", $queries);
if (strlen($query)) { if (strlen($query)) {
$path = implode("?", [$path, $query]); $path = implode("?", [$path, $query]);
} }
return $path; return $path;
} }
public function method() { public function method() {
return $this->method; return $this->method;
} }
public function path() { public function path() {
return $this->path; return $this->path;
} }
public function query() { public function query() {
return $this->query; return $this->query;
} }
public function headers() { public function headers() {
return $this->headers; return $this->headers;
} }
} }

View file

@ -1,32 +1,32 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\HTTP; namespace AWS\CRT\HTTP;
use AWS\CRT\IO\InputStream; use AWS\CRT\IO\InputStream;
class Request extends Message { class Request extends Message {
private $body_stream = null; private $body_stream = null;
public function __construct($method, $path, $query = [], $headers = [], $body_stream = null) { public function __construct($method, $path, $query = [], $headers = [], $body_stream = null) {
parent::__construct($method, $path, $query, $headers); parent::__construct($method, $path, $query, $headers);
if (!is_null($body_stream) && !($body_stream instanceof InputStream)) { if (!is_null($body_stream) && !($body_stream instanceof InputStream)) {
throw new \InvalidArgumentException('body_stream must be an instance of ' . InputStream::class); throw new \InvalidArgumentException('body_stream must be an instance of ' . InputStream::class);
} }
$this->body_stream = $body_stream; $this->body_stream = $body_stream;
} }
public static function marshall($request) { public static function marshall($request) {
return parent::marshall($request); return parent::marshall($request);
} }
public static function unmarshall($buf) { public static function unmarshall($buf) {
return parent::_unmarshall($buf, Request::class); return parent::_unmarshall($buf, Request::class);
} }
public function body_stream() { public function body_stream() {
return $this->body_stream; return $this->body_stream;
} }
} }

View file

@ -1,27 +1,27 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\HTTP; namespace AWS\CRT\HTTP;
class Response extends Message { class Response extends Message {
private $status_code; private $status_code;
public function __construct($method, $path, $query, $headers, $status_code) { public function __construct($method, $path, $query, $headers, $status_code) {
parent::__construct($method, $path, $query, $headers); parent::__construct($method, $path, $query, $headers);
$this->status_code = $status_code; $this->status_code = $status_code;
} }
public static function marshall($response) { public static function marshall($response) {
return parent::marshall($response); return parent::marshall($response);
} }
public static function unmarshall($buf) { public static function unmarshall($buf) {
return parent::_unmarshall($buf, Response::class); return parent::_unmarshall($buf, Response::class);
} }
public function status_code() { public function status_code() {
return $this->status_code; return $this->status_code;
} }
} }

View file

@ -1,39 +1,39 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\IO; namespace AWS\CRT\IO;
use AWS\CRT\NativeResource as NativeResource; use AWS\CRT\NativeResource as NativeResource;
use AWS\CRT\Options as Options; use AWS\CRT\Options as Options;
/** /**
* Represents 1 or more event loops (1 per thread) for doing I/O and background tasks. * Represents 1 or more event loops (1 per thread) for doing I/O and background tasks.
* Typically, every application has one EventLoopGroup. * Typically, every application has one EventLoopGroup.
* *
* @param array options: * @param array options:
* - int num_threads - Number of worker threads in the EventLoopGroup. Defaults to 0/1 per logical core. * - int num_threads - Number of worker threads in the EventLoopGroup. Defaults to 0/1 per logical core.
*/ */
final class EventLoopGroup extends NativeResource { final class EventLoopGroup extends NativeResource {
static function defaults() { static function defaults() {
return [ return [
'max_threads' => 0, 'max_threads' => 0,
]; ];
} }
function __construct(array $options = []) { function __construct(array $options = []) {
parent::__construct(); parent::__construct();
$options = new Options($options, self::defaults()); $options = new Options($options, self::defaults());
$elg_options = self::$crt->event_loop_group_options_new(); $elg_options = self::$crt->event_loop_group_options_new();
self::$crt->event_loop_group_options_set_max_threads($elg_options, $options->getInt('max_threads')); self::$crt->event_loop_group_options_set_max_threads($elg_options, $options->getInt('max_threads'));
$this->acquire(self::$crt->event_loop_group_new($elg_options)); $this->acquire(self::$crt->event_loop_group_new($elg_options));
self::$crt->event_loop_group_options_release($elg_options); self::$crt->event_loop_group_options_release($elg_options);
} }
function __destruct() { function __destruct() {
self::$crt->event_loop_group_release($this->release()); self::$crt->event_loop_group_release($this->release());
parent::__destruct(); parent::__destruct();
} }
} }

View file

@ -1,50 +1,50 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\IO; namespace AWS\CRT\IO;
use AWS\CRT\NativeResource as NativeResource; use AWS\CRT\NativeResource as NativeResource;
final class InputStream extends NativeResource { final class InputStream extends NativeResource {
private $stream = null; private $stream = null;
const SEEK_BEGIN = 0; const SEEK_BEGIN = 0;
const SEEK_END = 2; const SEEK_END = 2;
public function __construct($stream) { public function __construct($stream) {
parent::__construct(); parent::__construct();
$this->stream = $stream; $this->stream = $stream;
$options = self::$crt->input_stream_options_new(); $options = self::$crt->input_stream_options_new();
// The stream implementation in native just converts the PHP stream into // The stream implementation in native just converts the PHP stream into
// a native php_stream* and executes operations entirely in native // a native php_stream* and executes operations entirely in native
self::$crt->input_stream_options_set_user_data($options, $stream); self::$crt->input_stream_options_set_user_data($options, $stream);
$this->acquire(self::$crt->input_stream_new($options)); $this->acquire(self::$crt->input_stream_new($options));
self::$crt->input_stream_options_release($options); self::$crt->input_stream_options_release($options);
} }
public function __destruct() { public function __destruct() {
$this->release(); $this->release();
parent::__destruct(); parent::__destruct();
} }
public function eof() { public function eof() {
return self::$crt->input_stream_eof($this->native); return self::$crt->input_stream_eof($this->native);
} }
public function length() { public function length() {
return self::$crt->input_stream_get_length($this->native); return self::$crt->input_stream_get_length($this->native);
} }
public function read($length = 0) { public function read($length = 0) {
if ($length == 0) { if ($length == 0) {
$length = $this->length(); $length = $this->length();
} }
return self::$crt->input_stream_read($this->native, $length); return self::$crt->input_stream_read($this->native, $length);
} }
public function seek($offset, $basis) { public function seek($offset, $basis) {
return self::$crt->input_stream_seek($this->native, $offset, $basis); return self::$crt->input_stream_seek($this->native, $offset, $basis);
} }
} }

View file

@ -1,37 +1,37 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Internal; namespace AWS\CRT\Internal;
final class Encoding { final class Encoding {
public static function readString(&$buffer) { public static function readString(&$buffer) {
list($len, $str) = self::decodeString($buffer); list($len, $str) = self::decodeString($buffer);
// Advance by sizeof(length) + strlen(str) // Advance by sizeof(length) + strlen(str)
$buffer = substr($buffer, 4 + $len); $buffer = substr($buffer, 4 + $len);
return $str; return $str;
} }
public static function readStrings($buffer) { public static function readStrings($buffer) {
$strings = []; $strings = [];
while (strlen($buffer)) { while (strlen($buffer)) {
$strings []= self::readString($buffer); $strings []= self::readString($buffer);
} }
return $strings; return $strings;
} }
public static function decodeString($buffer) { public static function decodeString($buffer) {
$len = unpack("N", $buffer)[1]; $len = unpack("N", $buffer)[1];
$buffer = substr($buffer, 4); $buffer = substr($buffer, 4);
$str = unpack("a{$len}", $buffer)[1]; $str = unpack("a{$len}", $buffer)[1];
return [$len, $str]; return [$len, $str];
} }
public static function encodeString($str) { public static function encodeString($str) {
if (is_array($str)) { if (is_array($str)) {
$str = $str[0]; $str = $str[0];
} }
return pack("Na*", strlen($str), $str); return pack("Na*", strlen($str), $str);
} }
} }

View file

@ -1,29 +1,29 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT\Internal; namespace AWS\CRT\Internal;
use \RuntimeException; use \RuntimeException;
/** /**
* @internal * @internal
* Forwards calls on to awscrt PHP extension functions * Forwards calls on to awscrt PHP extension functions
*/ */
final class Extension { final class Extension {
function __construct() { function __construct() {
if (!extension_loaded('awscrt')) { if (!extension_loaded('awscrt')) {
throw new RuntimeException('awscrt extension is not loaded'); throw new RuntimeException('awscrt extension is not loaded');
} }
} }
/** /**
* Forwards any call made on this object to the extension function of the * Forwards any call made on this object to the extension function of the
* same name with the supplied arguments. Argument type hinting and checking * same name with the supplied arguments. Argument type hinting and checking
* occurs at the CRT wrapper. * occurs at the CRT wrapper.
*/ */
function __call($name, $args) { function __call($name, $args) {
return call_user_func_array($name, $args); return call_user_func_array($name, $args);
} }
} }

View file

@ -1,47 +1,47 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT; namespace AWS\CRT;
use AWS\CRT\CRT; use AWS\CRT\CRT;
final class Log { final class Log {
const NONE = 0; const NONE = 0;
const FATAL = 1; const FATAL = 1;
const ERROR = 2; const ERROR = 2;
const WARN = 3; const WARN = 3;
const INFO = 4; const INFO = 4;
const DEBUG = 5; const DEBUG = 5;
const TRACE = 6; const TRACE = 6;
public static function toStdout() { public static function toStdout() {
CRT::log_to_stdout(); CRT::log_to_stdout();
} }
public static function toStderr() { public static function toStderr() {
CRT::log_to_stderr(); CRT::log_to_stderr();
} }
public static function toFile($filename) { public static function toFile($filename) {
CRT::log_to_file($filename); CRT::log_to_file($filename);
} }
public static function toStream($stream) { public static function toStream($stream) {
assert(get_resource_type($stream) == "stream"); assert(get_resource_type($stream) == "stream");
CRT::log_to_stream($stream); CRT::log_to_stream($stream);
} }
public static function stop() { public static function stop() {
CRT::log_stop(); CRT::log_stop();
} }
public static function setLogLevel($level) { public static function setLogLevel($level) {
assert($level >= self::NONE && $level <= self::TRACE); assert($level >= self::NONE && $level <= self::TRACE);
CRT::log_set_level($level); CRT::log_set_level($level);
} }
public static function log($level, $message) { public static function log($level, $message) {
CRT::log_message($level, $message); CRT::log_message($level, $message);
} }
} }

View file

@ -1,42 +1,42 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT; namespace AWS\CRT;
use AWS\CRT\CRT as CRT; use AWS\CRT\CRT as CRT;
/** /**
* Base class for all native resources, tracks all outstanding resources * Base class for all native resources, tracks all outstanding resources
* and provides basic leak checking * and provides basic leak checking
*/ */
abstract class NativeResource { abstract class NativeResource {
protected static $crt = null; protected static $crt = null;
protected static $resources = []; protected static $resources = [];
protected $native = null; protected $native = null;
protected function __construct() { protected function __construct() {
if (is_null(self::$crt)) { if (is_null(self::$crt)) {
self::$crt = new CRT(); self::$crt = new CRT();
} }
self::$resources[spl_object_hash($this)] = 1; self::$resources[spl_object_hash($this)] = 1;
} }
protected function acquire($handle) { protected function acquire($handle) {
return $this->native = $handle; return $this->native = $handle;
} }
protected function release() { protected function release() {
$native = $this->native; $native = $this->native;
$this->native = null; $this->native = null;
return $native; return $native;
} }
function __destruct() { function __destruct() {
// Should have been destroyed and released by derived resource // Should have been destroyed and released by derived resource
assert($this->native == null); assert($this->native == null);
unset(self::$resources[spl_object_hash($this)]); unset(self::$resources[spl_object_hash($this)]);
} }
} }

View file

@ -1,77 +1,77 @@
<?php <?php
/** /**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
namespace AWS\CRT; namespace AWS\CRT;
final class OptionValue { final class OptionValue {
private $value; private $value;
function __construct($value) { function __construct($value) {
$this->value = $value; $this->value = $value;
} }
public function asObject() { public function asObject() {
return $this->value; return $this->value;
} }
public function asMixed() { public function asMixed() {
return $this->value; return $this->value;
} }
public function asInt() { public function asInt() {
return empty($this->value) ? 0 : (int)$this->value; return empty($this->value) ? 0 : (int)$this->value;
} }
public function asBool() { public function asBool() {
return boolval($this->value); return boolval($this->value);
} }
public function asString() { public function asString() {
return !empty($this->value) ? strval($this->value) : ""; return !empty($this->value) ? strval($this->value) : "";
} }
public function asArray() { public function asArray() {
return is_array($this->value) ? $this->value : (!empty($this->value) ? [$this->value] : []); return is_array($this->value) ? $this->value : (!empty($this->value) ? [$this->value] : []);
} }
public function asCallable() { public function asCallable() {
return is_callable($this->value) ? $this->value : null; return is_callable($this->value) ? $this->value : null;
} }
} }
final class Options { final class Options {
private $options; private $options;
public function __construct($opts = [], $defaults = []) { public function __construct($opts = [], $defaults = []) {
$this->options = array_replace($defaults, empty($opts) ? [] : $opts); $this->options = array_replace($defaults, empty($opts) ? [] : $opts);
} }
public function __get($name) { public function __get($name) {
return $this->get($name); return $this->get($name);
} }
public function asArray() { public function asArray() {
return $this->options; return $this->options;
} }
public function toArray() { public function toArray() {
return array_merge_recursive([], $this->options); return array_merge_recursive([], $this->options);
} }
public function get($name) { public function get($name) {
return new OptionValue($this->options[$name]); return new OptionValue($this->options[$name]);
} }
public function getInt($name) { public function getInt($name) {
return $this->get($name)->asInt(); return $this->get($name)->asInt();
} }
public function getString($name) { public function getString($name) {
return $this->get($name)->asString(); return $this->get($name)->asString();
} }
public function getBool($name) { public function getBool($name) {
return $this->get($name)->asBool(); return $this->get($name)->asBool();
} }
} }

View file

@ -1,4 +1,4 @@
## Code of Conduct ## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments. opensource-codeofconduct@amazon.com with any additional questions or comments.

View file

@ -1,4 +1,4 @@
## Building and enabling the Common Run Time ## Building and enabling the Common Run Time
1. **Follow instructions on crt repo** Clone and build the repo as shown [here][https://github.com/awslabs/aws-crt-php]. 1. **Follow instructions on crt repo** Clone and build the repo as shown [here][https://github.com/awslabs/aws-crt-php].
1. **Enable the CRT** add the following line to your php.ini file `extension=path/to/aws-crt-php/modules/awscrt.so` 1. **Enable the CRT** add the following line to your php.ini file `extension=path/to/aws-crt-php/modules/awscrt.so`

View file

@ -1,141 +1,141 @@
# Apache License # Apache License
Version 2.0, January 2004 Version 2.0, January 2004
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
## 1. Definitions. ## 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1
through 9 of this document. through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the
License. License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled
by, or are under common control with that entity. For the purposes of this definition, "control" means by, or are under common control with that entity. For the purposes of this definition, "control" means
(i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract
or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity. ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software "Source" form shall mean the preferred form for making modifications, including but not limited to software
source code, documentation source, and configuration files. source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form,
including but not limited to compiled object code, generated documentation, and conversions to other media including but not limited to compiled object code, generated documentation, and conversions to other media
types. types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License,
as indicated by a copyright notice that is included in or attached to the work (an example is provided in the as indicated by a copyright notice that is included in or attached to the work (an example is provided in the
Appendix below). Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from)
the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent,
as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not
include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work
and Derivative Works thereof. and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any "Contribution" shall mean any work of authorship, including the original version of the Work and any
modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to
Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to
submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of
electronic, verbal, or written communication sent to the Licensor or its representatives, including but not electronic, verbal, or written communication sent to the Licensor or its representatives, including but not
limited to communication on electronic mailing lists, source code control systems, and issue tracking systems limited to communication on electronic mailing lists, source code control systems, and issue tracking systems
that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise designated in writing by the copyright excluding communication that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution." owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been
received by Licensor and subsequently incorporated within the Work. received by Licensor and subsequently incorporated within the Work.
## 2. Grant of Copyright License. ## 2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form. Derivative Works in Source or Object form.
## 3. Grant of Patent License. ## 3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent
license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such
license applies only to those patent claims licensable by such Contributor that are necessarily infringed by license applies only to those patent claims licensable by such Contributor that are necessarily infringed by
their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such
Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim
or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work
constitutes direct or contributory patent infringement, then any patent licenses granted to You under this constitutes direct or contributory patent infringement, then any patent licenses granted to You under this
License for that Work shall terminate as of the date such litigation is filed. License for that Work shall terminate as of the date such litigation is filed.
## 4. Redistribution. ## 4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You meet the following conditions: modifications, and in Source or Object form, provided that You meet the following conditions:
1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
2. You must cause any modified files to carry prominent notices stating that You changed the files; and 2. You must cause any modified files to carry prominent notices stating that You changed the files; and
3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent,
trademark, and attribution notices from the Source form of the Work, excluding those notices that do trademark, and attribution notices from the Source form of the Work, excluding those notices that do
not pertain to any part of the Derivative Works; and not pertain to any part of the Derivative Works; and
4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that
You distribute must include a readable copy of the attribution notices contained within such NOTICE You distribute must include a readable copy of the attribution notices contained within such NOTICE
file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed as part of the Derivative Works; within of the following places: within a NOTICE text file distributed as part of the Derivative Works; within
the Source form or documentation, if provided along with the Derivative Works; or, within a display the Source form or documentation, if provided along with the Derivative Works; or, within a display
generated by the Derivative Works, if and wherever such third-party notices normally appear. The generated by the Derivative Works, if and wherever such third-party notices normally appear. The
contents of the NOTICE file are for informational purposes only and do not modify the License. You may contents of the NOTICE file are for informational purposes only and do not modify the License. You may
add Your own attribution notices within Derivative Works that You distribute, alongside or as an add Your own attribution notices within Derivative Works that You distribute, alongside or as an
addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be
construed as modifying the License. construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license You may add Your own copyright statement to Your modifications and may provide additional or different license
terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative
Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the
conditions stated in this License. conditions stated in this License.
## 5. Submission of Contributions. ## 5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by
You to the Licensor shall be under the terms and conditions of this License, without any additional terms or You to the Licensor shall be under the terms and conditions of this License, without any additional terms or
conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate
license agreement you may have executed with Licensor regarding such Contributions. license agreement you may have executed with Licensor regarding such Contributions.
## 6. Trademarks. ## 6. Trademarks.
This License does not grant permission to use the trade names, trademarks, service marks, or product names of This License does not grant permission to use the trade names, trademarks, service marks, or product names of
the Licensor, except as required for reasonable and customary use in describing the origin of the Work and the Licensor, except as required for reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file. reproducing the content of the NOTICE file.
## 7. Disclaimer of Warranty. ## 7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor
provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of
permissions under this License. permissions under this License.
## 8. Limitation of Liability. ## 8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless
required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any
Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential
damages of any character arising as a result of this License or out of the use or inability to use the Work damages of any character arising as a result of this License or out of the use or inability to use the Work
(including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has been advised of the possibility any and all other commercial damages or losses), even if such Contributor has been advised of the possibility
of such damages. of such damages.
## 9. Accepting Warranty or Additional Liability. ## 9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for,
acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole
responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold
each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability. of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS

View file

@ -1,17 +1,17 @@
# AWS SDK for PHP # AWS SDK for PHP
<http://aws.amazon.com/php> <http://aws.amazon.com/php>
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"). Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. You may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

View file

@ -1,84 +1,84 @@
The AWS SDK for PHP includes the following third-party software/licensing: The AWS SDK for PHP includes the following third-party software/licensing:
** Guzzle - https://github.com/guzzle/guzzle ** Guzzle - https://github.com/guzzle/guzzle
Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
---------------- ----------------
** jmespath.php - https://github.com/mtdowling/jmespath.php ** jmespath.php - https://github.com/mtdowling/jmespath.php
Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
---------------- ----------------
** phpunit-mock-objects -- https://github.com/sebastianbergmann/phpunit-mock-objects ** phpunit-mock-objects -- https://github.com/sebastianbergmann/phpunit-mock-objects
Copyright (c) 2002-2018, Sebastian Bergmann <sebastian@phpunit.de>. Copyright (c) 2002-2018, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
are met: are met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the the documentation and/or other materials provided with the
distribution. distribution.
* Neither the name of Sebastian Bergmann nor the names of his * Neither the name of Sebastian Bergmann nor the names of his
contributors may be used to endorse or promote products derived contributors may be used to endorse or promote products derived
from this software without specific prior written permission. from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,73 +0,0 @@
{
"name": "aws/aws-sdk-php",
"homepage": "http://aws.amazon.com/sdkforphp",
"description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
"keywords": ["aws","amazon","sdk","s3","ec2","dynamodb","cloud","glacier"],
"type": "library",
"license": "Apache-2.0",
"authors": [
{
"name": "Amazon Web Services",
"homepage": "http://aws.amazon.com"
}
],
"support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues"
},
"require": {
"php": ">=8.1",
"guzzlehttp/guzzle": "^7.4.5",
"guzzlehttp/psr7": "^2.4.5",
"guzzlehttp/promises": "^2.0",
"mtdowling/jmespath.php": "^2.8.0",
"ext-pcre": "*",
"ext-json": "*",
"ext-simplexml": "*",
"aws/aws-crt-php": "^1.2.3",
"psr/http-message": "^1.0 || ^2.0"
},
"require-dev": {
"composer/composer" : "^2.7.8",
"ext-openssl": "*",
"ext-dom": "*",
"ext-pcntl": "*",
"ext-sockets": "*",
"phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
"behat/behat": "~3.0",
"doctrine/cache": "~1.4",
"aws/aws-php-sns-message-validator": "~1.0",
"andrewsville/php-token-reflection": "^1.4",
"psr/cache": "^2.0 || ^3.0",
"psr/simple-cache": "^2.0 || ^3.0",
"sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0",
"symfony/filesystem": "^v6.4.0 || ^v7.1.0",
"yoast/phpunit-polyfills": "^2.0",
"dms/phpunit-arraysubset-asserts": "^0.4.0"
},
"suggest": {
"ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages",
"ext-curl": "To send requests using cURL",
"ext-sockets": "To use client-side monitoring",
"doctrine/cache": "To use the DoctrineCacheAdapter",
"aws/aws-php-sns-message-validator": "To validate incoming SNS notifications"
},
"autoload": {
"psr-4": {
"Aws\\": "src/"
},
"files": ["src/functions.php"],
"exclude-from-classmap": ["src/data/"]
},
"autoload-dev": {
"psr-4": {
"Aws\\Test\\": "tests/"
},
"classmap": ["build/"]
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
}
}

View file

@ -1,55 +1,55 @@
<?php <?php
namespace Aws\ACMPCA; namespace Aws\ACMPCA;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AWS Certificate Manager Private Certificate Authority** service. * This client is used to interact with the **AWS Certificate Manager Private Certificate Authority** service.
* @method \Aws\Result createCertificateAuthority(array $args = []) * @method \Aws\Result createCertificateAuthority(array $args = [])
* @method \GuzzleHttp\Promise\Promise createCertificateAuthorityAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createCertificateAuthorityAsync(array $args = [])
* @method \Aws\Result createCertificateAuthorityAuditReport(array $args = []) * @method \Aws\Result createCertificateAuthorityAuditReport(array $args = [])
* @method \GuzzleHttp\Promise\Promise createCertificateAuthorityAuditReportAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createCertificateAuthorityAuditReportAsync(array $args = [])
* @method \Aws\Result createPermission(array $args = []) * @method \Aws\Result createPermission(array $args = [])
* @method \GuzzleHttp\Promise\Promise createPermissionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createPermissionAsync(array $args = [])
* @method \Aws\Result deleteCertificateAuthority(array $args = []) * @method \Aws\Result deleteCertificateAuthority(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteCertificateAuthorityAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteCertificateAuthorityAsync(array $args = [])
* @method \Aws\Result deletePermission(array $args = []) * @method \Aws\Result deletePermission(array $args = [])
* @method \GuzzleHttp\Promise\Promise deletePermissionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deletePermissionAsync(array $args = [])
* @method \Aws\Result deletePolicy(array $args = []) * @method \Aws\Result deletePolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise deletePolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deletePolicyAsync(array $args = [])
* @method \Aws\Result describeCertificateAuthority(array $args = []) * @method \Aws\Result describeCertificateAuthority(array $args = [])
* @method \GuzzleHttp\Promise\Promise describeCertificateAuthorityAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise describeCertificateAuthorityAsync(array $args = [])
* @method \Aws\Result describeCertificateAuthorityAuditReport(array $args = []) * @method \Aws\Result describeCertificateAuthorityAuditReport(array $args = [])
* @method \GuzzleHttp\Promise\Promise describeCertificateAuthorityAuditReportAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise describeCertificateAuthorityAuditReportAsync(array $args = [])
* @method \Aws\Result getCertificate(array $args = []) * @method \Aws\Result getCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise getCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getCertificateAsync(array $args = [])
* @method \Aws\Result getCertificateAuthorityCertificate(array $args = []) * @method \Aws\Result getCertificateAuthorityCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise getCertificateAuthorityCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getCertificateAuthorityCertificateAsync(array $args = [])
* @method \Aws\Result getCertificateAuthorityCsr(array $args = []) * @method \Aws\Result getCertificateAuthorityCsr(array $args = [])
* @method \GuzzleHttp\Promise\Promise getCertificateAuthorityCsrAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getCertificateAuthorityCsrAsync(array $args = [])
* @method \Aws\Result getPolicy(array $args = []) * @method \Aws\Result getPolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise getPolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getPolicyAsync(array $args = [])
* @method \Aws\Result importCertificateAuthorityCertificate(array $args = []) * @method \Aws\Result importCertificateAuthorityCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise importCertificateAuthorityCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise importCertificateAuthorityCertificateAsync(array $args = [])
* @method \Aws\Result issueCertificate(array $args = []) * @method \Aws\Result issueCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise issueCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise issueCertificateAsync(array $args = [])
* @method \Aws\Result listCertificateAuthorities(array $args = []) * @method \Aws\Result listCertificateAuthorities(array $args = [])
* @method \GuzzleHttp\Promise\Promise listCertificateAuthoritiesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listCertificateAuthoritiesAsync(array $args = [])
* @method \Aws\Result listPermissions(array $args = []) * @method \Aws\Result listPermissions(array $args = [])
* @method \GuzzleHttp\Promise\Promise listPermissionsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listPermissionsAsync(array $args = [])
* @method \Aws\Result listTags(array $args = []) * @method \Aws\Result listTags(array $args = [])
* @method \GuzzleHttp\Promise\Promise listTagsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listTagsAsync(array $args = [])
* @method \Aws\Result putPolicy(array $args = []) * @method \Aws\Result putPolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise putPolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise putPolicyAsync(array $args = [])
* @method \Aws\Result restoreCertificateAuthority(array $args = []) * @method \Aws\Result restoreCertificateAuthority(array $args = [])
* @method \GuzzleHttp\Promise\Promise restoreCertificateAuthorityAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise restoreCertificateAuthorityAsync(array $args = [])
* @method \Aws\Result revokeCertificate(array $args = []) * @method \Aws\Result revokeCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise revokeCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise revokeCertificateAsync(array $args = [])
* @method \Aws\Result tagCertificateAuthority(array $args = []) * @method \Aws\Result tagCertificateAuthority(array $args = [])
* @method \GuzzleHttp\Promise\Promise tagCertificateAuthorityAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise tagCertificateAuthorityAsync(array $args = [])
* @method \Aws\Result untagCertificateAuthority(array $args = []) * @method \Aws\Result untagCertificateAuthority(array $args = [])
* @method \GuzzleHttp\Promise\Promise untagCertificateAuthorityAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise untagCertificateAuthorityAsync(array $args = [])
* @method \Aws\Result updateCertificateAuthority(array $args = []) * @method \Aws\Result updateCertificateAuthority(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateCertificateAuthorityAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateCertificateAuthorityAsync(array $args = [])
*/ */
class ACMPCAClient extends AwsClient {} class ACMPCAClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\ACMPCA\Exception; namespace Aws\ACMPCA\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AWS Certificate Manager Private Certificate Authority** service. * Represents an error interacting with the **AWS Certificate Manager Private Certificate Authority** service.
*/ */
class ACMPCAException extends AwsException {} class ACMPCAException extends AwsException {}

View file

@ -1,31 +1,31 @@
<?php <?php
namespace Aws\AIOps; namespace Aws\AIOps;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AWS AI Ops** service. * This client is used to interact with the **AWS AI Ops** service.
* @method \Aws\Result createInvestigationGroup(array $args = []) * @method \Aws\Result createInvestigationGroup(array $args = [])
* @method \GuzzleHttp\Promise\Promise createInvestigationGroupAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createInvestigationGroupAsync(array $args = [])
* @method \Aws\Result deleteInvestigationGroup(array $args = []) * @method \Aws\Result deleteInvestigationGroup(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteInvestigationGroupAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteInvestigationGroupAsync(array $args = [])
* @method \Aws\Result deleteInvestigationGroupPolicy(array $args = []) * @method \Aws\Result deleteInvestigationGroupPolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteInvestigationGroupPolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteInvestigationGroupPolicyAsync(array $args = [])
* @method \Aws\Result getInvestigationGroup(array $args = []) * @method \Aws\Result getInvestigationGroup(array $args = [])
* @method \GuzzleHttp\Promise\Promise getInvestigationGroupAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getInvestigationGroupAsync(array $args = [])
* @method \Aws\Result getInvestigationGroupPolicy(array $args = []) * @method \Aws\Result getInvestigationGroupPolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise getInvestigationGroupPolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getInvestigationGroupPolicyAsync(array $args = [])
* @method \Aws\Result listInvestigationGroups(array $args = []) * @method \Aws\Result listInvestigationGroups(array $args = [])
* @method \GuzzleHttp\Promise\Promise listInvestigationGroupsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listInvestigationGroupsAsync(array $args = [])
* @method \Aws\Result listTagsForResource(array $args = []) * @method \Aws\Result listTagsForResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
* @method \Aws\Result putInvestigationGroupPolicy(array $args = []) * @method \Aws\Result putInvestigationGroupPolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise putInvestigationGroupPolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise putInvestigationGroupPolicyAsync(array $args = [])
* @method \Aws\Result tagResource(array $args = []) * @method \Aws\Result tagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = [])
* @method \Aws\Result untagResource(array $args = []) * @method \Aws\Result untagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = [])
* @method \Aws\Result updateInvestigationGroup(array $args = []) * @method \Aws\Result updateInvestigationGroup(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateInvestigationGroupAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateInvestigationGroupAsync(array $args = [])
*/ */
class AIOpsClient extends AwsClient {} class AIOpsClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\AIOps\Exception; namespace Aws\AIOps\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AWS AI Ops** service. * Represents an error interacting with the **AWS AI Ops** service.
*/ */
class AIOpsException extends AwsException {} class AIOpsException extends AwsException {}

View file

@ -1,49 +1,51 @@
<?php <?php
namespace Aws\ARCRegionSwitch; namespace Aws\ARCRegionSwitch;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **ARC - Region switch** service. * This client is used to interact with the **ARC - Region switch** service.
* @method \Aws\Result approvePlanExecutionStep(array $args = []) * @method \Aws\Result approvePlanExecutionStep(array $args = [])
* @method \GuzzleHttp\Promise\Promise approvePlanExecutionStepAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise approvePlanExecutionStepAsync(array $args = [])
* @method \Aws\Result cancelPlanExecution(array $args = []) * @method \Aws\Result cancelPlanExecution(array $args = [])
* @method \GuzzleHttp\Promise\Promise cancelPlanExecutionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise cancelPlanExecutionAsync(array $args = [])
* @method \Aws\Result createPlan(array $args = []) * @method \Aws\Result createPlan(array $args = [])
* @method \GuzzleHttp\Promise\Promise createPlanAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createPlanAsync(array $args = [])
* @method \Aws\Result deletePlan(array $args = []) * @method \Aws\Result deletePlan(array $args = [])
* @method \GuzzleHttp\Promise\Promise deletePlanAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deletePlanAsync(array $args = [])
* @method \Aws\Result getPlan(array $args = []) * @method \Aws\Result getPlan(array $args = [])
* @method \GuzzleHttp\Promise\Promise getPlanAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getPlanAsync(array $args = [])
* @method \Aws\Result getPlanEvaluationStatus(array $args = []) * @method \Aws\Result getPlanEvaluationStatus(array $args = [])
* @method \GuzzleHttp\Promise\Promise getPlanEvaluationStatusAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getPlanEvaluationStatusAsync(array $args = [])
* @method \Aws\Result getPlanExecution(array $args = []) * @method \Aws\Result getPlanExecution(array $args = [])
* @method \GuzzleHttp\Promise\Promise getPlanExecutionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getPlanExecutionAsync(array $args = [])
* @method \Aws\Result getPlanInRegion(array $args = []) * @method \Aws\Result getPlanInRegion(array $args = [])
* @method \GuzzleHttp\Promise\Promise getPlanInRegionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getPlanInRegionAsync(array $args = [])
* @method \Aws\Result listPlanExecutionEvents(array $args = []) * @method \Aws\Result listPlanExecutionEvents(array $args = [])
* @method \GuzzleHttp\Promise\Promise listPlanExecutionEventsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listPlanExecutionEventsAsync(array $args = [])
* @method \Aws\Result listPlanExecutions(array $args = []) * @method \Aws\Result listPlanExecutions(array $args = [])
* @method \GuzzleHttp\Promise\Promise listPlanExecutionsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listPlanExecutionsAsync(array $args = [])
* @method \Aws\Result listPlans(array $args = []) * @method \Aws\Result listPlans(array $args = [])
* @method \GuzzleHttp\Promise\Promise listPlansAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listPlansAsync(array $args = [])
* @method \Aws\Result listPlansInRegion(array $args = []) * @method \Aws\Result listPlansInRegion(array $args = [])
* @method \GuzzleHttp\Promise\Promise listPlansInRegionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listPlansInRegionAsync(array $args = [])
* @method \Aws\Result listRoute53HealthChecks(array $args = []) * @method \Aws\Result listRoute53HealthChecks(array $args = [])
* @method \GuzzleHttp\Promise\Promise listRoute53HealthChecksAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listRoute53HealthChecksAsync(array $args = [])
* @method \Aws\Result listTagsForResource(array $args = []) * @method \Aws\Result listRoute53HealthChecksInRegion(array $args = [])
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listRoute53HealthChecksInRegionAsync(array $args = [])
* @method \Aws\Result startPlanExecution(array $args = []) * @method \Aws\Result listTagsForResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise startPlanExecutionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
* @method \Aws\Result tagResource(array $args = []) * @method \Aws\Result startPlanExecution(array $args = [])
* @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startPlanExecutionAsync(array $args = [])
* @method \Aws\Result untagResource(array $args = []) * @method \Aws\Result tagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = [])
* @method \Aws\Result updatePlan(array $args = []) * @method \Aws\Result untagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise updatePlanAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = [])
* @method \Aws\Result updatePlanExecution(array $args = []) * @method \Aws\Result updatePlan(array $args = [])
* @method \GuzzleHttp\Promise\Promise updatePlanExecutionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updatePlanAsync(array $args = [])
* @method \Aws\Result updatePlanExecutionStep(array $args = []) * @method \Aws\Result updatePlanExecution(array $args = [])
* @method \GuzzleHttp\Promise\Promise updatePlanExecutionStepAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updatePlanExecutionAsync(array $args = [])
*/ * @method \Aws\Result updatePlanExecutionStep(array $args = [])
class ARCRegionSwitchClient extends AwsClient {} * @method \GuzzleHttp\Promise\Promise updatePlanExecutionStepAsync(array $args = [])
*/
class ARCRegionSwitchClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\ARCRegionSwitch\Exception; namespace Aws\ARCRegionSwitch\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **ARC - Region switch** service. * Represents an error interacting with the **ARC - Region switch** service.
*/ */
class ARCRegionSwitchException extends AwsException {} class ARCRegionSwitchException extends AwsException {}

View file

@ -1,39 +1,39 @@
<?php <?php
namespace Aws\ARCZonalShift; namespace Aws\ARCZonalShift;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AWS ARC - Zonal Shift** service. * This client is used to interact with the **AWS ARC - Zonal Shift** service.
* @method \Aws\Result cancelPracticeRun(array $args = []) * @method \Aws\Result cancelPracticeRun(array $args = [])
* @method \GuzzleHttp\Promise\Promise cancelPracticeRunAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise cancelPracticeRunAsync(array $args = [])
* @method \Aws\Result cancelZonalShift(array $args = []) * @method \Aws\Result cancelZonalShift(array $args = [])
* @method \GuzzleHttp\Promise\Promise cancelZonalShiftAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise cancelZonalShiftAsync(array $args = [])
* @method \Aws\Result createPracticeRunConfiguration(array $args = []) * @method \Aws\Result createPracticeRunConfiguration(array $args = [])
* @method \GuzzleHttp\Promise\Promise createPracticeRunConfigurationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createPracticeRunConfigurationAsync(array $args = [])
* @method \Aws\Result deletePracticeRunConfiguration(array $args = []) * @method \Aws\Result deletePracticeRunConfiguration(array $args = [])
* @method \GuzzleHttp\Promise\Promise deletePracticeRunConfigurationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deletePracticeRunConfigurationAsync(array $args = [])
* @method \Aws\Result getAutoshiftObserverNotificationStatus(array $args = []) * @method \Aws\Result getAutoshiftObserverNotificationStatus(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAutoshiftObserverNotificationStatusAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAutoshiftObserverNotificationStatusAsync(array $args = [])
* @method \Aws\Result getManagedResource(array $args = []) * @method \Aws\Result getManagedResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise getManagedResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getManagedResourceAsync(array $args = [])
* @method \Aws\Result listAutoshifts(array $args = []) * @method \Aws\Result listAutoshifts(array $args = [])
* @method \GuzzleHttp\Promise\Promise listAutoshiftsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listAutoshiftsAsync(array $args = [])
* @method \Aws\Result listManagedResources(array $args = []) * @method \Aws\Result listManagedResources(array $args = [])
* @method \GuzzleHttp\Promise\Promise listManagedResourcesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listManagedResourcesAsync(array $args = [])
* @method \Aws\Result listZonalShifts(array $args = []) * @method \Aws\Result listZonalShifts(array $args = [])
* @method \GuzzleHttp\Promise\Promise listZonalShiftsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listZonalShiftsAsync(array $args = [])
* @method \Aws\Result startPracticeRun(array $args = []) * @method \Aws\Result startPracticeRun(array $args = [])
* @method \GuzzleHttp\Promise\Promise startPracticeRunAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startPracticeRunAsync(array $args = [])
* @method \Aws\Result startZonalShift(array $args = []) * @method \Aws\Result startZonalShift(array $args = [])
* @method \GuzzleHttp\Promise\Promise startZonalShiftAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startZonalShiftAsync(array $args = [])
* @method \Aws\Result updateAutoshiftObserverNotificationStatus(array $args = []) * @method \Aws\Result updateAutoshiftObserverNotificationStatus(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateAutoshiftObserverNotificationStatusAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateAutoshiftObserverNotificationStatusAsync(array $args = [])
* @method \Aws\Result updatePracticeRunConfiguration(array $args = []) * @method \Aws\Result updatePracticeRunConfiguration(array $args = [])
* @method \GuzzleHttp\Promise\Promise updatePracticeRunConfigurationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updatePracticeRunConfigurationAsync(array $args = [])
* @method \Aws\Result updateZonalAutoshiftConfiguration(array $args = []) * @method \Aws\Result updateZonalAutoshiftConfiguration(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateZonalAutoshiftConfigurationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateZonalAutoshiftConfigurationAsync(array $args = [])
* @method \Aws\Result updateZonalShift(array $args = []) * @method \Aws\Result updateZonalShift(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateZonalShiftAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateZonalShiftAsync(array $args = [])
*/ */
class ARCZonalShiftClient extends AwsClient {} class ARCZonalShiftClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\ARCZonalShift\Exception; namespace Aws\ARCZonalShift\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AWS ARC - Zonal Shift** service. * Represents an error interacting with the **AWS ARC - Zonal Shift** service.
*/ */
class ARCZonalShiftException extends AwsException {} class ARCZonalShiftException extends AwsException {}

View file

@ -1,157 +1,157 @@
<?php <?php
namespace Aws; namespace Aws;
use GuzzleHttp\Promise; use GuzzleHttp\Promise;
/** /**
* A configuration provider is a function that returns a promise that is * A configuration provider is a function that returns a promise that is
* fulfilled with a configuration object. This class provides base functionality * fulfilled with a configuration object. This class provides base functionality
* usable by specific configuration provider implementations * usable by specific configuration provider implementations
*/ */
abstract class AbstractConfigurationProvider abstract class AbstractConfigurationProvider
{ {
const ENV_PROFILE = 'AWS_PROFILE'; const ENV_PROFILE = 'AWS_PROFILE';
const ENV_CONFIG_FILE = 'AWS_CONFIG_FILE'; const ENV_CONFIG_FILE = 'AWS_CONFIG_FILE';
public static $cacheKey; public static $cacheKey;
protected static $interfaceClass; protected static $interfaceClass;
protected static $exceptionClass; protected static $exceptionClass;
/** /**
* Wraps a config provider and saves provided configuration in an * Wraps a config provider and saves provided configuration in an
* instance of Aws\CacheInterface. Forwards calls when no config found * instance of Aws\CacheInterface. Forwards calls when no config found
* in cache and updates cache with the results. * in cache and updates cache with the results.
* *
* @param callable $provider Configuration provider function to wrap * @param callable $provider Configuration provider function to wrap
* @param CacheInterface $cache Cache to store configuration * @param CacheInterface $cache Cache to store configuration
* @param string|null $cacheKey (optional) Cache key to use * @param string|null $cacheKey (optional) Cache key to use
* *
* @return callable * @return callable
*/ */
public static function cache( public static function cache(
callable $provider, callable $provider,
CacheInterface $cache, CacheInterface $cache,
$cacheKey = null $cacheKey = null
) { ) {
$cacheKey = $cacheKey ?: static::$cacheKey; $cacheKey = $cacheKey ?: static::$cacheKey;
return function () use ($provider, $cache, $cacheKey) { return function () use ($provider, $cache, $cacheKey) {
$found = $cache->get($cacheKey); $found = $cache->get($cacheKey);
if ($found instanceof static::$interfaceClass) { if ($found instanceof static::$interfaceClass) {
return Promise\Create::promiseFor($found); return Promise\Create::promiseFor($found);
} }
return $provider() return $provider()
->then(function ($config) use ( ->then(function ($config) use (
$cache, $cache,
$cacheKey $cacheKey
) { ) {
$cache->set($cacheKey, $config); $cache->set($cacheKey, $config);
return $config; return $config;
}); });
}; };
} }
/** /**
* Creates an aggregate configuration provider that invokes the provided * Creates an aggregate configuration provider that invokes the provided
* variadic providers one after the other until a provider returns * variadic providers one after the other until a provider returns
* configuration. * configuration.
* *
* @return callable * @return callable
*/ */
public static function chain() public static function chain()
{ {
$links = func_get_args(); $links = func_get_args();
if (empty($links)) { if (empty($links)) {
throw new \InvalidArgumentException('No providers in chain'); throw new \InvalidArgumentException('No providers in chain');
} }
return function () use ($links) { return function () use ($links) {
/** @var callable $parent */ /** @var callable $parent */
$parent = array_shift($links); $parent = array_shift($links);
$promise = $parent(); $promise = $parent();
while ($next = array_shift($links)) { while ($next = array_shift($links)) {
$promise = $promise->otherwise($next); $promise = $promise->otherwise($next);
} }
return $promise; return $promise;
}; };
} }
/** /**
* Gets the environment's HOME directory if available. * Gets the environment's HOME directory if available.
* *
* @return null|string * @return null|string
*/ */
protected static function getHomeDir() protected static function getHomeDir()
{ {
// On Linux/Unix-like systems, use the HOME environment variable // On Linux/Unix-like systems, use the HOME environment variable
if ($homeDir = getenv('HOME')) { if ($homeDir = getenv('HOME')) {
return $homeDir; return $homeDir;
} }
// Get the HOMEDRIVE and HOMEPATH values for Windows hosts // Get the HOMEDRIVE and HOMEPATH values for Windows hosts
$homeDrive = getenv('HOMEDRIVE'); $homeDrive = getenv('HOMEDRIVE');
$homePath = getenv('HOMEPATH'); $homePath = getenv('HOMEPATH');
return ($homeDrive && $homePath) ? $homeDrive . $homePath : null; return ($homeDrive && $homePath) ? $homeDrive . $homePath : null;
} }
/** /**
* Gets default config file location from environment, falling back to aws * Gets default config file location from environment, falling back to aws
* default location * default location
* *
* @return string * @return string
*/ */
protected static function getDefaultConfigFilename() protected static function getDefaultConfigFilename()
{ {
if ($filename = getenv(self::ENV_CONFIG_FILE)) { if ($filename = getenv(self::ENV_CONFIG_FILE)) {
return $filename; return $filename;
} }
return self::getHomeDir() . '/.aws/config'; return self::getHomeDir() . '/.aws/config';
} }
/** /**
* Wraps a config provider and caches previously provided configuration. * Wraps a config provider and caches previously provided configuration.
* *
* @param callable $provider Config provider function to wrap. * @param callable $provider Config provider function to wrap.
* *
* @return callable * @return callable
*/ */
public static function memoize(callable $provider) public static function memoize(callable $provider)
{ {
return function () use ($provider) { return function () use ($provider) {
static $result; static $result;
static $isConstant; static $isConstant;
// Constant config will be returned constantly. // Constant config will be returned constantly.
if ($isConstant) { if ($isConstant) {
return $result; return $result;
} }
// Create the initial promise that will be used as the cached value // Create the initial promise that will be used as the cached value
if (null === $result) { if (null === $result) {
$result = $provider(); $result = $provider();
} }
// Return config and set flag that provider is already set // Return config and set flag that provider is already set
return $result return $result
->then(function ($config) use (&$isConstant) { ->then(function ($config) use (&$isConstant) {
$isConstant = true; $isConstant = true;
return $config; return $config;
}); });
}; };
} }
/** /**
* Reject promise with standardized exception. * Reject promise with standardized exception.
* *
* @param $msg * @param $msg
* @return Promise\RejectedPromise * @return Promise\RejectedPromise
*/ */
protected static function reject($msg) protected static function reject($msg)
{ {
$exceptionClass = static::$exceptionClass; $exceptionClass = static::$exceptionClass;
return new Promise\RejectedPromise(new $exceptionClass($msg)); return new Promise\RejectedPromise(new $exceptionClass($msg));
} }
} }

View file

@ -1,83 +1,83 @@
<?php <?php
namespace Aws\AccessAnalyzer; namespace Aws\AccessAnalyzer;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **Access Analyzer** service. * This client is used to interact with the **Access Analyzer** service.
* @method \Aws\Result applyArchiveRule(array $args = []) * @method \Aws\Result applyArchiveRule(array $args = [])
* @method \GuzzleHttp\Promise\Promise applyArchiveRuleAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise applyArchiveRuleAsync(array $args = [])
* @method \Aws\Result cancelPolicyGeneration(array $args = []) * @method \Aws\Result cancelPolicyGeneration(array $args = [])
* @method \GuzzleHttp\Promise\Promise cancelPolicyGenerationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise cancelPolicyGenerationAsync(array $args = [])
* @method \Aws\Result checkAccessNotGranted(array $args = []) * @method \Aws\Result checkAccessNotGranted(array $args = [])
* @method \GuzzleHttp\Promise\Promise checkAccessNotGrantedAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise checkAccessNotGrantedAsync(array $args = [])
* @method \Aws\Result checkNoNewAccess(array $args = []) * @method \Aws\Result checkNoNewAccess(array $args = [])
* @method \GuzzleHttp\Promise\Promise checkNoNewAccessAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise checkNoNewAccessAsync(array $args = [])
* @method \Aws\Result checkNoPublicAccess(array $args = []) * @method \Aws\Result checkNoPublicAccess(array $args = [])
* @method \GuzzleHttp\Promise\Promise checkNoPublicAccessAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise checkNoPublicAccessAsync(array $args = [])
* @method \Aws\Result createAccessPreview(array $args = []) * @method \Aws\Result createAccessPreview(array $args = [])
* @method \GuzzleHttp\Promise\Promise createAccessPreviewAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createAccessPreviewAsync(array $args = [])
* @method \Aws\Result createAnalyzer(array $args = []) * @method \Aws\Result createAnalyzer(array $args = [])
* @method \GuzzleHttp\Promise\Promise createAnalyzerAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createAnalyzerAsync(array $args = [])
* @method \Aws\Result createArchiveRule(array $args = []) * @method \Aws\Result createArchiveRule(array $args = [])
* @method \GuzzleHttp\Promise\Promise createArchiveRuleAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createArchiveRuleAsync(array $args = [])
* @method \Aws\Result deleteAnalyzer(array $args = []) * @method \Aws\Result deleteAnalyzer(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteAnalyzerAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteAnalyzerAsync(array $args = [])
* @method \Aws\Result deleteArchiveRule(array $args = []) * @method \Aws\Result deleteArchiveRule(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteArchiveRuleAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteArchiveRuleAsync(array $args = [])
* @method \Aws\Result generateFindingRecommendation(array $args = []) * @method \Aws\Result generateFindingRecommendation(array $args = [])
* @method \GuzzleHttp\Promise\Promise generateFindingRecommendationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise generateFindingRecommendationAsync(array $args = [])
* @method \Aws\Result getAccessPreview(array $args = []) * @method \Aws\Result getAccessPreview(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAccessPreviewAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAccessPreviewAsync(array $args = [])
* @method \Aws\Result getAnalyzedResource(array $args = []) * @method \Aws\Result getAnalyzedResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAnalyzedResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAnalyzedResourceAsync(array $args = [])
* @method \Aws\Result getAnalyzer(array $args = []) * @method \Aws\Result getAnalyzer(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAnalyzerAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAnalyzerAsync(array $args = [])
* @method \Aws\Result getArchiveRule(array $args = []) * @method \Aws\Result getArchiveRule(array $args = [])
* @method \GuzzleHttp\Promise\Promise getArchiveRuleAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getArchiveRuleAsync(array $args = [])
* @method \Aws\Result getFinding(array $args = []) * @method \Aws\Result getFinding(array $args = [])
* @method \GuzzleHttp\Promise\Promise getFindingAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getFindingAsync(array $args = [])
* @method \Aws\Result getFindingRecommendation(array $args = []) * @method \Aws\Result getFindingRecommendation(array $args = [])
* @method \GuzzleHttp\Promise\Promise getFindingRecommendationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getFindingRecommendationAsync(array $args = [])
* @method \Aws\Result getFindingV2(array $args = []) * @method \Aws\Result getFindingV2(array $args = [])
* @method \GuzzleHttp\Promise\Promise getFindingV2Async(array $args = []) * @method \GuzzleHttp\Promise\Promise getFindingV2Async(array $args = [])
* @method \Aws\Result getFindingsStatistics(array $args = []) * @method \Aws\Result getFindingsStatistics(array $args = [])
* @method \GuzzleHttp\Promise\Promise getFindingsStatisticsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getFindingsStatisticsAsync(array $args = [])
* @method \Aws\Result getGeneratedPolicy(array $args = []) * @method \Aws\Result getGeneratedPolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise getGeneratedPolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getGeneratedPolicyAsync(array $args = [])
* @method \Aws\Result listAccessPreviewFindings(array $args = []) * @method \Aws\Result listAccessPreviewFindings(array $args = [])
* @method \GuzzleHttp\Promise\Promise listAccessPreviewFindingsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listAccessPreviewFindingsAsync(array $args = [])
* @method \Aws\Result listAccessPreviews(array $args = []) * @method \Aws\Result listAccessPreviews(array $args = [])
* @method \GuzzleHttp\Promise\Promise listAccessPreviewsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listAccessPreviewsAsync(array $args = [])
* @method \Aws\Result listAnalyzedResources(array $args = []) * @method \Aws\Result listAnalyzedResources(array $args = [])
* @method \GuzzleHttp\Promise\Promise listAnalyzedResourcesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listAnalyzedResourcesAsync(array $args = [])
* @method \Aws\Result listAnalyzers(array $args = []) * @method \Aws\Result listAnalyzers(array $args = [])
* @method \GuzzleHttp\Promise\Promise listAnalyzersAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listAnalyzersAsync(array $args = [])
* @method \Aws\Result listArchiveRules(array $args = []) * @method \Aws\Result listArchiveRules(array $args = [])
* @method \GuzzleHttp\Promise\Promise listArchiveRulesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listArchiveRulesAsync(array $args = [])
* @method \Aws\Result listFindings(array $args = []) * @method \Aws\Result listFindings(array $args = [])
* @method \GuzzleHttp\Promise\Promise listFindingsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listFindingsAsync(array $args = [])
* @method \Aws\Result listFindingsV2(array $args = []) * @method \Aws\Result listFindingsV2(array $args = [])
* @method \GuzzleHttp\Promise\Promise listFindingsV2Async(array $args = []) * @method \GuzzleHttp\Promise\Promise listFindingsV2Async(array $args = [])
* @method \Aws\Result listPolicyGenerations(array $args = []) * @method \Aws\Result listPolicyGenerations(array $args = [])
* @method \GuzzleHttp\Promise\Promise listPolicyGenerationsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listPolicyGenerationsAsync(array $args = [])
* @method \Aws\Result listTagsForResource(array $args = []) * @method \Aws\Result listTagsForResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
* @method \Aws\Result startPolicyGeneration(array $args = []) * @method \Aws\Result startPolicyGeneration(array $args = [])
* @method \GuzzleHttp\Promise\Promise startPolicyGenerationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startPolicyGenerationAsync(array $args = [])
* @method \Aws\Result startResourceScan(array $args = []) * @method \Aws\Result startResourceScan(array $args = [])
* @method \GuzzleHttp\Promise\Promise startResourceScanAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startResourceScanAsync(array $args = [])
* @method \Aws\Result tagResource(array $args = []) * @method \Aws\Result tagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = [])
* @method \Aws\Result untagResource(array $args = []) * @method \Aws\Result untagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = [])
* @method \Aws\Result updateAnalyzer(array $args = []) * @method \Aws\Result updateAnalyzer(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateAnalyzerAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateAnalyzerAsync(array $args = [])
* @method \Aws\Result updateArchiveRule(array $args = []) * @method \Aws\Result updateArchiveRule(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateArchiveRuleAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateArchiveRuleAsync(array $args = [])
* @method \Aws\Result updateFindings(array $args = []) * @method \Aws\Result updateFindings(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateFindingsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateFindingsAsync(array $args = [])
* @method \Aws\Result validatePolicy(array $args = []) * @method \Aws\Result validatePolicy(array $args = [])
* @method \GuzzleHttp\Promise\Promise validatePolicyAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise validatePolicyAsync(array $args = [])
*/ */
class AccessAnalyzerClient extends AwsClient {} class AccessAnalyzerClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\AccessAnalyzer\Exception; namespace Aws\AccessAnalyzer\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **Access Analyzer** service. * Represents an error interacting with the **Access Analyzer** service.
*/ */
class AccessAnalyzerException extends AwsException {} class AccessAnalyzerException extends AwsException {}

View file

@ -1,37 +1,39 @@
<?php <?php
namespace Aws\Account; namespace Aws\Account;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AWS Account** service. * This client is used to interact with the **AWS Account** service.
* @method \Aws\Result acceptPrimaryEmailUpdate(array $args = []) * @method \Aws\Result acceptPrimaryEmailUpdate(array $args = [])
* @method \GuzzleHttp\Promise\Promise acceptPrimaryEmailUpdateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise acceptPrimaryEmailUpdateAsync(array $args = [])
* @method \Aws\Result deleteAlternateContact(array $args = []) * @method \Aws\Result deleteAlternateContact(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteAlternateContactAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteAlternateContactAsync(array $args = [])
* @method \Aws\Result disableRegion(array $args = []) * @method \Aws\Result disableRegion(array $args = [])
* @method \GuzzleHttp\Promise\Promise disableRegionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise disableRegionAsync(array $args = [])
* @method \Aws\Result enableRegion(array $args = []) * @method \Aws\Result enableRegion(array $args = [])
* @method \GuzzleHttp\Promise\Promise enableRegionAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise enableRegionAsync(array $args = [])
* @method \Aws\Result getAccountInformation(array $args = []) * @method \Aws\Result getAccountInformation(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAccountInformationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAccountInformationAsync(array $args = [])
* @method \Aws\Result getAlternateContact(array $args = []) * @method \Aws\Result getAlternateContact(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAlternateContactAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAlternateContactAsync(array $args = [])
* @method \Aws\Result getContactInformation(array $args = []) * @method \Aws\Result getContactInformation(array $args = [])
* @method \GuzzleHttp\Promise\Promise getContactInformationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getContactInformationAsync(array $args = [])
* @method \Aws\Result getPrimaryEmail(array $args = []) * @method \Aws\Result getGovCloudAccountInformation(array $args = [])
* @method \GuzzleHttp\Promise\Promise getPrimaryEmailAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getGovCloudAccountInformationAsync(array $args = [])
* @method \Aws\Result getRegionOptStatus(array $args = []) * @method \Aws\Result getPrimaryEmail(array $args = [])
* @method \GuzzleHttp\Promise\Promise getRegionOptStatusAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getPrimaryEmailAsync(array $args = [])
* @method \Aws\Result listRegions(array $args = []) * @method \Aws\Result getRegionOptStatus(array $args = [])
* @method \GuzzleHttp\Promise\Promise listRegionsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getRegionOptStatusAsync(array $args = [])
* @method \Aws\Result putAccountName(array $args = []) * @method \Aws\Result listRegions(array $args = [])
* @method \GuzzleHttp\Promise\Promise putAccountNameAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listRegionsAsync(array $args = [])
* @method \Aws\Result putAlternateContact(array $args = []) * @method \Aws\Result putAccountName(array $args = [])
* @method \GuzzleHttp\Promise\Promise putAlternateContactAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise putAccountNameAsync(array $args = [])
* @method \Aws\Result putContactInformation(array $args = []) * @method \Aws\Result putAlternateContact(array $args = [])
* @method \GuzzleHttp\Promise\Promise putContactInformationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise putAlternateContactAsync(array $args = [])
* @method \Aws\Result startPrimaryEmailUpdate(array $args = []) * @method \Aws\Result putContactInformation(array $args = [])
* @method \GuzzleHttp\Promise\Promise startPrimaryEmailUpdateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise putContactInformationAsync(array $args = [])
*/ * @method \Aws\Result startPrimaryEmailUpdate(array $args = [])
class AccountClient extends AwsClient {} * @method \GuzzleHttp\Promise\Promise startPrimaryEmailUpdateAsync(array $args = [])
*/
class AccountClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\Account\Exception; namespace Aws\Account\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AWS Account** service. * Represents an error interacting with the **AWS Account** service.
*/ */
class AccountException extends AwsException {} class AccountException extends AwsException {}

View file

@ -1,42 +1,42 @@
<?php <?php
namespace Aws\Acm; namespace Aws\Acm;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AWS Certificate Manager** service. * This client is used to interact with the **AWS Certificate Manager** service.
* *
* @method \Aws\Result addTagsToCertificate(array $args = []) * @method \Aws\Result addTagsToCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise addTagsToCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise addTagsToCertificateAsync(array $args = [])
* @method \Aws\Result deleteCertificate(array $args = []) * @method \Aws\Result deleteCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteCertificateAsync(array $args = [])
* @method \Aws\Result describeCertificate(array $args = []) * @method \Aws\Result describeCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise describeCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise describeCertificateAsync(array $args = [])
* @method \Aws\Result exportCertificate(array $args = []) * @method \Aws\Result exportCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise exportCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise exportCertificateAsync(array $args = [])
* @method \Aws\Result getAccountConfiguration(array $args = []) * @method \Aws\Result getAccountConfiguration(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAccountConfigurationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAccountConfigurationAsync(array $args = [])
* @method \Aws\Result getCertificate(array $args = []) * @method \Aws\Result getCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise getCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getCertificateAsync(array $args = [])
* @method \Aws\Result importCertificate(array $args = []) * @method \Aws\Result importCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise importCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise importCertificateAsync(array $args = [])
* @method \Aws\Result listCertificates(array $args = []) * @method \Aws\Result listCertificates(array $args = [])
* @method \GuzzleHttp\Promise\Promise listCertificatesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listCertificatesAsync(array $args = [])
* @method \Aws\Result listTagsForCertificate(array $args = []) * @method \Aws\Result listTagsForCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise listTagsForCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listTagsForCertificateAsync(array $args = [])
* @method \Aws\Result putAccountConfiguration(array $args = []) * @method \Aws\Result putAccountConfiguration(array $args = [])
* @method \GuzzleHttp\Promise\Promise putAccountConfigurationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise putAccountConfigurationAsync(array $args = [])
* @method \Aws\Result removeTagsFromCertificate(array $args = []) * @method \Aws\Result removeTagsFromCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise removeTagsFromCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise removeTagsFromCertificateAsync(array $args = [])
* @method \Aws\Result renewCertificate(array $args = []) * @method \Aws\Result renewCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise renewCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise renewCertificateAsync(array $args = [])
* @method \Aws\Result requestCertificate(array $args = []) * @method \Aws\Result requestCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise requestCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise requestCertificateAsync(array $args = [])
* @method \Aws\Result resendValidationEmail(array $args = []) * @method \Aws\Result resendValidationEmail(array $args = [])
* @method \GuzzleHttp\Promise\Promise resendValidationEmailAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise resendValidationEmailAsync(array $args = [])
* @method \Aws\Result revokeCertificate(array $args = []) * @method \Aws\Result revokeCertificate(array $args = [])
* @method \GuzzleHttp\Promise\Promise revokeCertificateAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise revokeCertificateAsync(array $args = [])
* @method \Aws\Result updateCertificateOptions(array $args = []) * @method \Aws\Result updateCertificateOptions(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateCertificateOptionsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateCertificateOptionsAsync(array $args = [])
*/ */
class AcmClient extends AwsClient {} class AcmClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\Acm\Exception; namespace Aws\Acm\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AWS Certificate Manager** service. * Represents an error interacting with the **AWS Certificate Manager** service.
*/ */
class AcmException extends AwsException {} class AcmException extends AwsException {}

View file

@ -1,83 +1,83 @@
<?php <?php
namespace Aws\Amplify; namespace Aws\Amplify;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AWS Amplify** service. * This client is used to interact with the **AWS Amplify** service.
* @method \Aws\Result createApp(array $args = []) * @method \Aws\Result createApp(array $args = [])
* @method \GuzzleHttp\Promise\Promise createAppAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createAppAsync(array $args = [])
* @method \Aws\Result createBackendEnvironment(array $args = []) * @method \Aws\Result createBackendEnvironment(array $args = [])
* @method \GuzzleHttp\Promise\Promise createBackendEnvironmentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createBackendEnvironmentAsync(array $args = [])
* @method \Aws\Result createBranch(array $args = []) * @method \Aws\Result createBranch(array $args = [])
* @method \GuzzleHttp\Promise\Promise createBranchAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createBranchAsync(array $args = [])
* @method \Aws\Result createDeployment(array $args = []) * @method \Aws\Result createDeployment(array $args = [])
* @method \GuzzleHttp\Promise\Promise createDeploymentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createDeploymentAsync(array $args = [])
* @method \Aws\Result createDomainAssociation(array $args = []) * @method \Aws\Result createDomainAssociation(array $args = [])
* @method \GuzzleHttp\Promise\Promise createDomainAssociationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createDomainAssociationAsync(array $args = [])
* @method \Aws\Result createWebhook(array $args = []) * @method \Aws\Result createWebhook(array $args = [])
* @method \GuzzleHttp\Promise\Promise createWebhookAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createWebhookAsync(array $args = [])
* @method \Aws\Result deleteApp(array $args = []) * @method \Aws\Result deleteApp(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteAppAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteAppAsync(array $args = [])
* @method \Aws\Result deleteBackendEnvironment(array $args = []) * @method \Aws\Result deleteBackendEnvironment(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteBackendEnvironmentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteBackendEnvironmentAsync(array $args = [])
* @method \Aws\Result deleteBranch(array $args = []) * @method \Aws\Result deleteBranch(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteBranchAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteBranchAsync(array $args = [])
* @method \Aws\Result deleteDomainAssociation(array $args = []) * @method \Aws\Result deleteDomainAssociation(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteDomainAssociationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteDomainAssociationAsync(array $args = [])
* @method \Aws\Result deleteJob(array $args = []) * @method \Aws\Result deleteJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteJobAsync(array $args = [])
* @method \Aws\Result deleteWebhook(array $args = []) * @method \Aws\Result deleteWebhook(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteWebhookAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteWebhookAsync(array $args = [])
* @method \Aws\Result generateAccessLogs(array $args = []) * @method \Aws\Result generateAccessLogs(array $args = [])
* @method \GuzzleHttp\Promise\Promise generateAccessLogsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise generateAccessLogsAsync(array $args = [])
* @method \Aws\Result getApp(array $args = []) * @method \Aws\Result getApp(array $args = [])
* @method \GuzzleHttp\Promise\Promise getAppAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getAppAsync(array $args = [])
* @method \Aws\Result getArtifactUrl(array $args = []) * @method \Aws\Result getArtifactUrl(array $args = [])
* @method \GuzzleHttp\Promise\Promise getArtifactUrlAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getArtifactUrlAsync(array $args = [])
* @method \Aws\Result getBackendEnvironment(array $args = []) * @method \Aws\Result getBackendEnvironment(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBackendEnvironmentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBackendEnvironmentAsync(array $args = [])
* @method \Aws\Result getBranch(array $args = []) * @method \Aws\Result getBranch(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBranchAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBranchAsync(array $args = [])
* @method \Aws\Result getDomainAssociation(array $args = []) * @method \Aws\Result getDomainAssociation(array $args = [])
* @method \GuzzleHttp\Promise\Promise getDomainAssociationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getDomainAssociationAsync(array $args = [])
* @method \Aws\Result getJob(array $args = []) * @method \Aws\Result getJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise getJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getJobAsync(array $args = [])
* @method \Aws\Result getWebhook(array $args = []) * @method \Aws\Result getWebhook(array $args = [])
* @method \GuzzleHttp\Promise\Promise getWebhookAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getWebhookAsync(array $args = [])
* @method \Aws\Result listApps(array $args = []) * @method \Aws\Result listApps(array $args = [])
* @method \GuzzleHttp\Promise\Promise listAppsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listAppsAsync(array $args = [])
* @method \Aws\Result listArtifacts(array $args = []) * @method \Aws\Result listArtifacts(array $args = [])
* @method \GuzzleHttp\Promise\Promise listArtifactsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listArtifactsAsync(array $args = [])
* @method \Aws\Result listBackendEnvironments(array $args = []) * @method \Aws\Result listBackendEnvironments(array $args = [])
* @method \GuzzleHttp\Promise\Promise listBackendEnvironmentsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listBackendEnvironmentsAsync(array $args = [])
* @method \Aws\Result listBranches(array $args = []) * @method \Aws\Result listBranches(array $args = [])
* @method \GuzzleHttp\Promise\Promise listBranchesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listBranchesAsync(array $args = [])
* @method \Aws\Result listDomainAssociations(array $args = []) * @method \Aws\Result listDomainAssociations(array $args = [])
* @method \GuzzleHttp\Promise\Promise listDomainAssociationsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listDomainAssociationsAsync(array $args = [])
* @method \Aws\Result listJobs(array $args = []) * @method \Aws\Result listJobs(array $args = [])
* @method \GuzzleHttp\Promise\Promise listJobsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listJobsAsync(array $args = [])
* @method \Aws\Result listTagsForResource(array $args = []) * @method \Aws\Result listTagsForResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
* @method \Aws\Result listWebhooks(array $args = []) * @method \Aws\Result listWebhooks(array $args = [])
* @method \GuzzleHttp\Promise\Promise listWebhooksAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listWebhooksAsync(array $args = [])
* @method \Aws\Result startDeployment(array $args = []) * @method \Aws\Result startDeployment(array $args = [])
* @method \GuzzleHttp\Promise\Promise startDeploymentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startDeploymentAsync(array $args = [])
* @method \Aws\Result startJob(array $args = []) * @method \Aws\Result startJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise startJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startJobAsync(array $args = [])
* @method \Aws\Result stopJob(array $args = []) * @method \Aws\Result stopJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise stopJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise stopJobAsync(array $args = [])
* @method \Aws\Result tagResource(array $args = []) * @method \Aws\Result tagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = [])
* @method \Aws\Result untagResource(array $args = []) * @method \Aws\Result untagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = [])
* @method \Aws\Result updateApp(array $args = []) * @method \Aws\Result updateApp(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateAppAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateAppAsync(array $args = [])
* @method \Aws\Result updateBranch(array $args = []) * @method \Aws\Result updateBranch(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateBranchAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateBranchAsync(array $args = [])
* @method \Aws\Result updateDomainAssociation(array $args = []) * @method \Aws\Result updateDomainAssociation(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateDomainAssociationAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateDomainAssociationAsync(array $args = [])
* @method \Aws\Result updateWebhook(array $args = []) * @method \Aws\Result updateWebhook(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateWebhookAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateWebhookAsync(array $args = [])
*/ */
class AmplifyClient extends AwsClient {} class AmplifyClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\Amplify\Exception; namespace Aws\Amplify\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AWS Amplify** service. * Represents an error interacting with the **AWS Amplify** service.
*/ */
class AmplifyException extends AwsException {} class AmplifyException extends AwsException {}

View file

@ -1,71 +1,71 @@
<?php <?php
namespace Aws\AmplifyBackend; namespace Aws\AmplifyBackend;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AmplifyBackend** service. * This client is used to interact with the **AmplifyBackend** service.
* @method \Aws\Result cloneBackend(array $args = []) * @method \Aws\Result cloneBackend(array $args = [])
* @method \GuzzleHttp\Promise\Promise cloneBackendAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise cloneBackendAsync(array $args = [])
* @method \Aws\Result createBackend(array $args = []) * @method \Aws\Result createBackend(array $args = [])
* @method \GuzzleHttp\Promise\Promise createBackendAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createBackendAsync(array $args = [])
* @method \Aws\Result createBackendAPI(array $args = []) * @method \Aws\Result createBackendAPI(array $args = [])
* @method \GuzzleHttp\Promise\Promise createBackendAPIAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createBackendAPIAsync(array $args = [])
* @method \Aws\Result createBackendAuth(array $args = []) * @method \Aws\Result createBackendAuth(array $args = [])
* @method \GuzzleHttp\Promise\Promise createBackendAuthAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createBackendAuthAsync(array $args = [])
* @method \Aws\Result createBackendConfig(array $args = []) * @method \Aws\Result createBackendConfig(array $args = [])
* @method \GuzzleHttp\Promise\Promise createBackendConfigAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createBackendConfigAsync(array $args = [])
* @method \Aws\Result createBackendStorage(array $args = []) * @method \Aws\Result createBackendStorage(array $args = [])
* @method \GuzzleHttp\Promise\Promise createBackendStorageAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createBackendStorageAsync(array $args = [])
* @method \Aws\Result createToken(array $args = []) * @method \Aws\Result createToken(array $args = [])
* @method \GuzzleHttp\Promise\Promise createTokenAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createTokenAsync(array $args = [])
* @method \Aws\Result deleteBackend(array $args = []) * @method \Aws\Result deleteBackend(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteBackendAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteBackendAsync(array $args = [])
* @method \Aws\Result deleteBackendAPI(array $args = []) * @method \Aws\Result deleteBackendAPI(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteBackendAPIAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteBackendAPIAsync(array $args = [])
* @method \Aws\Result deleteBackendAuth(array $args = []) * @method \Aws\Result deleteBackendAuth(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteBackendAuthAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteBackendAuthAsync(array $args = [])
* @method \Aws\Result deleteBackendStorage(array $args = []) * @method \Aws\Result deleteBackendStorage(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteBackendStorageAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteBackendStorageAsync(array $args = [])
* @method \Aws\Result deleteToken(array $args = []) * @method \Aws\Result deleteToken(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteTokenAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteTokenAsync(array $args = [])
* @method \Aws\Result generateBackendAPIModels(array $args = []) * @method \Aws\Result generateBackendAPIModels(array $args = [])
* @method \GuzzleHttp\Promise\Promise generateBackendAPIModelsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise generateBackendAPIModelsAsync(array $args = [])
* @method \Aws\Result getBackend(array $args = []) * @method \Aws\Result getBackend(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBackendAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBackendAsync(array $args = [])
* @method \Aws\Result getBackendAPI(array $args = []) * @method \Aws\Result getBackendAPI(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBackendAPIAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBackendAPIAsync(array $args = [])
* @method \Aws\Result getBackendAPIModels(array $args = []) * @method \Aws\Result getBackendAPIModels(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBackendAPIModelsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBackendAPIModelsAsync(array $args = [])
* @method \Aws\Result getBackendAuth(array $args = []) * @method \Aws\Result getBackendAuth(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBackendAuthAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBackendAuthAsync(array $args = [])
* @method \Aws\Result getBackendJob(array $args = []) * @method \Aws\Result getBackendJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBackendJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBackendJobAsync(array $args = [])
* @method \Aws\Result getBackendStorage(array $args = []) * @method \Aws\Result getBackendStorage(array $args = [])
* @method \GuzzleHttp\Promise\Promise getBackendStorageAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getBackendStorageAsync(array $args = [])
* @method \Aws\Result getToken(array $args = []) * @method \Aws\Result getChallengeToken(array $args = [])
* @method \GuzzleHttp\Promise\Promise getTokenAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getChallengeTokenAsync(array $args = [])
* @method \Aws\Result importBackendAuth(array $args = []) * @method \Aws\Result importBackendAuth(array $args = [])
* @method \GuzzleHttp\Promise\Promise importBackendAuthAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise importBackendAuthAsync(array $args = [])
* @method \Aws\Result importBackendStorage(array $args = []) * @method \Aws\Result importBackendStorage(array $args = [])
* @method \GuzzleHttp\Promise\Promise importBackendStorageAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise importBackendStorageAsync(array $args = [])
* @method \Aws\Result listBackendJobs(array $args = []) * @method \Aws\Result listBackendJobs(array $args = [])
* @method \GuzzleHttp\Promise\Promise listBackendJobsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listBackendJobsAsync(array $args = [])
* @method \Aws\Result listS3Buckets(array $args = []) * @method \Aws\Result listS3Buckets(array $args = [])
* @method \GuzzleHttp\Promise\Promise listS3BucketsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listS3BucketsAsync(array $args = [])
* @method \Aws\Result removeAllBackends(array $args = []) * @method \Aws\Result removeAllBackends(array $args = [])
* @method \GuzzleHttp\Promise\Promise removeAllBackendsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise removeAllBackendsAsync(array $args = [])
* @method \Aws\Result removeBackendConfig(array $args = []) * @method \Aws\Result removeBackendConfig(array $args = [])
* @method \GuzzleHttp\Promise\Promise removeBackendConfigAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise removeBackendConfigAsync(array $args = [])
* @method \Aws\Result updateBackendAPI(array $args = []) * @method \Aws\Result updateBackendAPI(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateBackendAPIAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateBackendAPIAsync(array $args = [])
* @method \Aws\Result updateBackendAuth(array $args = []) * @method \Aws\Result updateBackendAuth(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateBackendAuthAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateBackendAuthAsync(array $args = [])
* @method \Aws\Result updateBackendConfig(array $args = []) * @method \Aws\Result updateBackendConfig(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateBackendConfigAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateBackendConfigAsync(array $args = [])
* @method \Aws\Result updateBackendJob(array $args = []) * @method \Aws\Result updateBackendJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateBackendJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateBackendJobAsync(array $args = [])
* @method \Aws\Result updateBackendStorage(array $args = []) * @method \Aws\Result updateBackendStorage(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateBackendStorageAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateBackendStorageAsync(array $args = [])
*/ */
class AmplifyBackendClient extends AwsClient {} class AmplifyBackendClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\AmplifyBackend\Exception; namespace Aws\AmplifyBackend\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AmplifyBackend** service. * Represents an error interacting with the **AmplifyBackend** service.
*/ */
class AmplifyBackendException extends AwsException {} class AmplifyBackendException extends AwsException {}

View file

@ -1,65 +1,65 @@
<?php <?php
namespace Aws\AmplifyUIBuilder; namespace Aws\AmplifyUIBuilder;
use Aws\AwsClient; use Aws\AwsClient;
/** /**
* This client is used to interact with the **AWS Amplify UI Builder** service. * This client is used to interact with the **AWS Amplify UI Builder** service.
* @method \Aws\Result createComponent(array $args = []) * @method \Aws\Result createComponent(array $args = [])
* @method \GuzzleHttp\Promise\Promise createComponentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createComponentAsync(array $args = [])
* @method \Aws\Result createForm(array $args = []) * @method \Aws\Result createForm(array $args = [])
* @method \GuzzleHttp\Promise\Promise createFormAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createFormAsync(array $args = [])
* @method \Aws\Result createTheme(array $args = []) * @method \Aws\Result createTheme(array $args = [])
* @method \GuzzleHttp\Promise\Promise createThemeAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise createThemeAsync(array $args = [])
* @method \Aws\Result deleteComponent(array $args = []) * @method \Aws\Result deleteComponent(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteComponentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteComponentAsync(array $args = [])
* @method \Aws\Result deleteForm(array $args = []) * @method \Aws\Result deleteForm(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteFormAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteFormAsync(array $args = [])
* @method \Aws\Result deleteTheme(array $args = []) * @method \Aws\Result deleteTheme(array $args = [])
* @method \GuzzleHttp\Promise\Promise deleteThemeAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise deleteThemeAsync(array $args = [])
* @method \Aws\Result exchangeCodeForToken(array $args = []) * @method \Aws\Result exchangeCodeForToken(array $args = [])
* @method \GuzzleHttp\Promise\Promise exchangeCodeForTokenAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise exchangeCodeForTokenAsync(array $args = [])
* @method \Aws\Result exportComponents(array $args = []) * @method \Aws\Result exportComponents(array $args = [])
* @method \GuzzleHttp\Promise\Promise exportComponentsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise exportComponentsAsync(array $args = [])
* @method \Aws\Result exportForms(array $args = []) * @method \Aws\Result exportForms(array $args = [])
* @method \GuzzleHttp\Promise\Promise exportFormsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise exportFormsAsync(array $args = [])
* @method \Aws\Result exportThemes(array $args = []) * @method \Aws\Result exportThemes(array $args = [])
* @method \GuzzleHttp\Promise\Promise exportThemesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise exportThemesAsync(array $args = [])
* @method \Aws\Result getCodegenJob(array $args = []) * @method \Aws\Result getCodegenJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise getCodegenJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getCodegenJobAsync(array $args = [])
* @method \Aws\Result getComponent(array $args = []) * @method \Aws\Result getComponent(array $args = [])
* @method \GuzzleHttp\Promise\Promise getComponentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getComponentAsync(array $args = [])
* @method \Aws\Result getForm(array $args = []) * @method \Aws\Result getForm(array $args = [])
* @method \GuzzleHttp\Promise\Promise getFormAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getFormAsync(array $args = [])
* @method \Aws\Result getMetadata(array $args = []) * @method \Aws\Result getMetadata(array $args = [])
* @method \GuzzleHttp\Promise\Promise getMetadataAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getMetadataAsync(array $args = [])
* @method \Aws\Result getTheme(array $args = []) * @method \Aws\Result getTheme(array $args = [])
* @method \GuzzleHttp\Promise\Promise getThemeAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise getThemeAsync(array $args = [])
* @method \Aws\Result listCodegenJobs(array $args = []) * @method \Aws\Result listCodegenJobs(array $args = [])
* @method \GuzzleHttp\Promise\Promise listCodegenJobsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listCodegenJobsAsync(array $args = [])
* @method \Aws\Result listComponents(array $args = []) * @method \Aws\Result listComponents(array $args = [])
* @method \GuzzleHttp\Promise\Promise listComponentsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listComponentsAsync(array $args = [])
* @method \Aws\Result listForms(array $args = []) * @method \Aws\Result listForms(array $args = [])
* @method \GuzzleHttp\Promise\Promise listFormsAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listFormsAsync(array $args = [])
* @method \Aws\Result listTagsForResource(array $args = []) * @method \Aws\Result listTagsForResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
* @method \Aws\Result listThemes(array $args = []) * @method \Aws\Result listThemes(array $args = [])
* @method \GuzzleHttp\Promise\Promise listThemesAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise listThemesAsync(array $args = [])
* @method \Aws\Result putMetadataFlag(array $args = []) * @method \Aws\Result putMetadataFlag(array $args = [])
* @method \GuzzleHttp\Promise\Promise putMetadataFlagAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise putMetadataFlagAsync(array $args = [])
* @method \Aws\Result refreshToken(array $args = []) * @method \Aws\Result refreshToken(array $args = [])
* @method \GuzzleHttp\Promise\Promise refreshTokenAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise refreshTokenAsync(array $args = [])
* @method \Aws\Result startCodegenJob(array $args = []) * @method \Aws\Result startCodegenJob(array $args = [])
* @method \GuzzleHttp\Promise\Promise startCodegenJobAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise startCodegenJobAsync(array $args = [])
* @method \Aws\Result tagResource(array $args = []) * @method \Aws\Result tagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = [])
* @method \Aws\Result untagResource(array $args = []) * @method \Aws\Result untagResource(array $args = [])
* @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = [])
* @method \Aws\Result updateComponent(array $args = []) * @method \Aws\Result updateComponent(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateComponentAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateComponentAsync(array $args = [])
* @method \Aws\Result updateForm(array $args = []) * @method \Aws\Result updateForm(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateFormAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateFormAsync(array $args = [])
* @method \Aws\Result updateTheme(array $args = []) * @method \Aws\Result updateTheme(array $args = [])
* @method \GuzzleHttp\Promise\Promise updateThemeAsync(array $args = []) * @method \GuzzleHttp\Promise\Promise updateThemeAsync(array $args = [])
*/ */
class AmplifyUIBuilderClient extends AwsClient {} class AmplifyUIBuilderClient extends AwsClient {}

View file

@ -1,9 +1,9 @@
<?php <?php
namespace Aws\AmplifyUIBuilder\Exception; namespace Aws\AmplifyUIBuilder\Exception;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
/** /**
* Represents an error interacting with the **AWS Amplify UI Builder** service. * Represents an error interacting with the **AWS Amplify UI Builder** service.
*/ */
class AmplifyUIBuilderException extends AwsException {} class AmplifyUIBuilderException extends AwsException {}

View file

@ -1,89 +1,89 @@
<?php <?php
namespace Aws\Api; namespace Aws\Api;
/** /**
* Base class that is used by most API shapes * Base class that is used by most API shapes
*/ */
abstract class AbstractModel implements \ArrayAccess abstract class AbstractModel implements \ArrayAccess
{ {
/** @var array */ /** @var array */
protected $definition; protected $definition;
/** @var ShapeMap */ /** @var ShapeMap */
protected $shapeMap; protected $shapeMap;
/** @var array */ /** @var array */
protected $contextParam; protected $contextParam;
/** /**
* @param array $definition Service description * @param array $definition Service description
* @param ShapeMap $shapeMap Shapemap used for creating shapes * @param ShapeMap $shapeMap Shapemap used for creating shapes
*/ */
public function __construct(array $definition, ShapeMap $shapeMap) public function __construct(array $definition, ShapeMap $shapeMap)
{ {
$this->definition = $definition; $this->definition = $definition;
$this->shapeMap = $shapeMap; $this->shapeMap = $shapeMap;
if (isset($definition['contextParam'])) { if (isset($definition['contextParam'])) {
$this->contextParam = $definition['contextParam']; $this->contextParam = $definition['contextParam'];
} }
} }
public function toArray() public function toArray()
{ {
return $this->definition; return $this->definition;
} }
/** /**
* @return mixed|null * @return mixed|null
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetGet($offset) public function offsetGet($offset)
{ {
return isset($this->definition[$offset]) return isset($this->definition[$offset])
? $this->definition[$offset] : null; ? $this->definition[$offset] : null;
} }
/** /**
* @return void * @return void
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetSet($offset, $value) public function offsetSet($offset, $value)
{ {
$this->definition[$offset] = $value; $this->definition[$offset] = $value;
} }
/** /**
* @return bool * @return bool
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetExists($offset) public function offsetExists($offset)
{ {
return isset($this->definition[$offset]); return isset($this->definition[$offset]);
} }
/** /**
* @return void * @return void
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetUnset($offset) public function offsetUnset($offset)
{ {
unset($this->definition[$offset]); unset($this->definition[$offset]);
} }
protected function shapeAt($key) protected function shapeAt($key)
{ {
if (!isset($this->definition[$key])) { if (!isset($this->definition[$key])) {
throw new \InvalidArgumentException('Expected shape definition at ' throw new \InvalidArgumentException('Expected shape definition at '
. $key); . $key);
} }
return $this->shapeFor($this->definition[$key]); return $this->shapeFor($this->definition[$key]);
} }
protected function shapeFor(array $definition) protected function shapeFor(array $definition)
{ {
return isset($definition['shape']) return isset($definition['shape'])
? $this->shapeMap->resolve($definition) ? $this->shapeMap->resolve($definition)
: Shape::create($definition, $this->shapeMap); : Shape::create($definition, $this->shapeMap);
} }
} }

View file

@ -1,244 +1,244 @@
<?php <?php
namespace Aws\Api; namespace Aws\Api;
use Aws\Exception\UnresolvedApiException; use Aws\Exception\UnresolvedApiException;
/** /**
* API providers. * API providers.
* *
* An API provider is a function that accepts a type, service, and version and * An API provider is a function that accepts a type, service, and version and
* returns an array of API data on success or NULL if no API data can be created * returns an array of API data on success or NULL if no API data can be created
* for the provided arguments. * for the provided arguments.
* *
* You can wrap your calls to an API provider with the * You can wrap your calls to an API provider with the
* {@see ApiProvider::resolve} method to ensure that API data is created. If the * {@see ApiProvider::resolve} method to ensure that API data is created. If the
* API data is not created, then the resolve() method will throw a * API data is not created, then the resolve() method will throw a
* {@see Aws\Exception\UnresolvedApiException}. * {@see Aws\Exception\UnresolvedApiException}.
* *
* use Aws\Api\ApiProvider; * use Aws\Api\ApiProvider;
* $provider = ApiProvider::defaultProvider(); * $provider = ApiProvider::defaultProvider();
* // Returns an array or NULL. * // Returns an array or NULL.
* $data = $provider('api', 's3', '2006-03-01'); * $data = $provider('api', 's3', '2006-03-01');
* // Returns an array or throws. * // Returns an array or throws.
* $data = ApiProvider::resolve($provider, 'api', 'elasticfood', '2020-01-01'); * $data = ApiProvider::resolve($provider, 'api', 'elasticfood', '2020-01-01');
* *
* You can compose multiple providers into a single provider using * You can compose multiple providers into a single provider using
* {@see Aws\or_chain}. This method accepts providers as arguments and * {@see Aws\or_chain}. This method accepts providers as arguments and
* returns a new function that will invoke each provider until a non-null value * returns a new function that will invoke each provider until a non-null value
* is returned. * is returned.
* *
* $a = ApiProvider::filesystem(sys_get_temp_dir() . '/aws-beta-models'); * $a = ApiProvider::filesystem(sys_get_temp_dir() . '/aws-beta-models');
* $b = ApiProvider::manifest(); * $b = ApiProvider::manifest();
* *
* $c = \Aws\or_chain($a, $b); * $c = \Aws\or_chain($a, $b);
* $data = $c('api', 'betaservice', '2015-08-08'); // $a handles this. * $data = $c('api', 'betaservice', '2015-08-08'); // $a handles this.
* $data = $c('api', 's3', '2006-03-01'); // $b handles this. * $data = $c('api', 's3', '2006-03-01'); // $b handles this.
* $data = $c('api', 'invalid', '2014-12-15'); // Neither handles this. * $data = $c('api', 'invalid', '2014-12-15'); // Neither handles this.
*/ */
class ApiProvider class ApiProvider
{ {
/** @var array A map of public API type names to their file suffix. */ /** @var array A map of public API type names to their file suffix. */
private static $typeMap = [ private static $typeMap = [
'api' => 'api-2', 'api' => 'api-2',
'paginator' => 'paginators-1', 'paginator' => 'paginators-1',
'waiter' => 'waiters-2', 'waiter' => 'waiters-2',
'docs' => 'docs-2', 'docs' => 'docs-2',
]; ];
/** @var array API manifest */ /** @var array API manifest */
private $manifest; private $manifest;
/** @var string The directory containing service models. */ /** @var string The directory containing service models. */
private $modelsDir; private $modelsDir;
/** /**
* Resolves an API provider and ensures a non-null return value. * Resolves an API provider and ensures a non-null return value.
* *
* @param callable $provider Provider function to invoke. * @param callable $provider Provider function to invoke.
* @param string $type Type of data ('api', 'waiter', 'paginator'). * @param string $type Type of data ('api', 'waiter', 'paginator').
* @param string $service Service name. * @param string $service Service name.
* @param string $version API version. * @param string $version API version.
* *
* @return array * @return array
* @throws UnresolvedApiException * @throws UnresolvedApiException
*/ */
public static function resolve(callable $provider, $type, $service, $version) public static function resolve(callable $provider, $type, $service, $version)
{ {
// Execute the provider and return the result, if there is one. // Execute the provider and return the result, if there is one.
$result = $provider($type, $service, $version); $result = $provider($type, $service, $version);
if (is_array($result)) { if (is_array($result)) {
if (!isset($result['metadata']['serviceIdentifier'])) { if (!isset($result['metadata']['serviceIdentifier'])) {
$result['metadata']['serviceIdentifier'] = $service; $result['metadata']['serviceIdentifier'] = $service;
} }
return $result; return $result;
} }
// Throw an exception with a message depending on the inputs. // Throw an exception with a message depending on the inputs.
if (!isset(self::$typeMap[$type])) { if (!isset(self::$typeMap[$type])) {
$msg = "The type must be one of: " . implode(', ', self::$typeMap); $msg = "The type must be one of: " . implode(', ', self::$typeMap);
} elseif ($service) { } elseif ($service) {
$msg = "The {$service} service does not have version: {$version}."; $msg = "The {$service} service does not have version: {$version}.";
} else { } else {
$msg = "You must specify a service name to retrieve its API data."; $msg = "You must specify a service name to retrieve its API data.";
} }
throw new UnresolvedApiException($msg); throw new UnresolvedApiException($msg);
} }
/** /**
* Default SDK API provider. * Default SDK API provider.
* *
* This provider loads pre-built manifest data from the `data` directory. * This provider loads pre-built manifest data from the `data` directory.
* *
* @return self * @return self
*/ */
public static function defaultProvider() public static function defaultProvider()
{ {
return new self(__DIR__ . '/../data', \Aws\manifest()); return new self(__DIR__ . '/../data', \Aws\manifest());
} }
/** /**
* Loads API data after resolving the version to the latest, compatible, * Loads API data after resolving the version to the latest, compatible,
* available version based on the provided manifest data. * available version based on the provided manifest data.
* *
* Manifest data is essentially an associative array of service names to * Manifest data is essentially an associative array of service names to
* associative arrays of API version aliases. * associative arrays of API version aliases.
* *
* [ * [
* ... * ...
* 'ec2' => [ * 'ec2' => [
* 'latest' => '2014-10-01', * 'latest' => '2014-10-01',
* '2014-10-01' => '2014-10-01', * '2014-10-01' => '2014-10-01',
* '2014-09-01' => '2014-10-01', * '2014-09-01' => '2014-10-01',
* '2014-06-15' => '2014-10-01', * '2014-06-15' => '2014-10-01',
* ... * ...
* ], * ],
* 'ecs' => [...], * 'ecs' => [...],
* 'elasticache' => [...], * 'elasticache' => [...],
* ... * ...
* ] * ]
* *
* @param string $dir Directory containing service models. * @param string $dir Directory containing service models.
* @param array $manifest The API version manifest data. * @param array $manifest The API version manifest data.
* *
* @return self * @return self
*/ */
public static function manifest($dir, array $manifest) public static function manifest($dir, array $manifest)
{ {
return new self($dir, $manifest); return new self($dir, $manifest);
} }
/** /**
* Loads API data from the specified directory. * Loads API data from the specified directory.
* *
* If "latest" is specified as the version, this provider must glob the * If "latest" is specified as the version, this provider must glob the
* directory to find which is the latest available version. * directory to find which is the latest available version.
* *
* @param string $dir Directory containing service models. * @param string $dir Directory containing service models.
* *
* @return self * @return self
* @throws \InvalidArgumentException if the provided `$dir` is invalid. * @throws \InvalidArgumentException if the provided `$dir` is invalid.
*/ */
public static function filesystem($dir) public static function filesystem($dir)
{ {
return new self($dir); return new self($dir);
} }
/** /**
* Retrieves a list of valid versions for the specified service. * Retrieves a list of valid versions for the specified service.
* *
* @param string $service Service name * @param string $service Service name
* *
* @return array * @return array
*/ */
public function getVersions($service) public function getVersions($service)
{ {
if (!isset($this->manifest)) { if (!isset($this->manifest)) {
$this->buildVersionsList($service); $this->buildVersionsList($service);
} }
if (!isset($this->manifest[$service]['versions'])) { if (!isset($this->manifest[$service]['versions'])) {
return []; return [];
} }
return array_values(array_unique($this->manifest[$service]['versions'])); return array_values(array_unique($this->manifest[$service]['versions']));
} }
/** /**
* Execute the provider. * Execute the provider.
* *
* @param string $type Type of data ('api', 'waiter', 'paginator'). * @param string $type Type of data ('api', 'waiter', 'paginator').
* @param string $service Service name. * @param string $service Service name.
* @param string $version API version. * @param string $version API version.
* *
* @return array|null * @return array|null
*/ */
public function __invoke($type, $service, $version) public function __invoke($type, $service, $version)
{ {
// Resolve the type or return null. // Resolve the type or return null.
if (isset(self::$typeMap[$type])) { if (isset(self::$typeMap[$type])) {
$type = self::$typeMap[$type]; $type = self::$typeMap[$type];
} else { } else {
return null; return null;
} }
// Resolve the version or return null. // Resolve the version or return null.
if (!isset($this->manifest)) { if (!isset($this->manifest)) {
$this->buildVersionsList($service); $this->buildVersionsList($service);
} }
if (!isset($this->manifest[$service]['versions'][$version])) { if (!isset($this->manifest[$service]['versions'][$version])) {
return null; return null;
} }
$version = $this->manifest[$service]['versions'][$version]; $version = $this->manifest[$service]['versions'][$version];
$path = "{$this->modelsDir}/{$service}/{$version}/{$type}.json"; $path = "{$this->modelsDir}/{$service}/{$version}/{$type}.json";
try { try {
return \Aws\load_compiled_json($path); return \Aws\load_compiled_json($path);
} catch (\InvalidArgumentException $e) { } catch (\InvalidArgumentException $e) {
return null; return null;
} }
} }
/** /**
* @param string $modelsDir Directory containing service models. * @param string $modelsDir Directory containing service models.
* @param array $manifest The API version manifest data. * @param array $manifest The API version manifest data.
*/ */
private function __construct($modelsDir, ?array $manifest = null) private function __construct($modelsDir, ?array $manifest = null)
{ {
$this->manifest = $manifest; $this->manifest = $manifest;
$this->modelsDir = rtrim($modelsDir, '/'); $this->modelsDir = rtrim($modelsDir, '/');
if (!is_dir($this->modelsDir)) { if (!is_dir($this->modelsDir)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
"The specified models directory, {$modelsDir}, was not found." "The specified models directory, {$modelsDir}, was not found."
); );
} }
} }
/** /**
* Build the versions list for the specified service by globbing the dir. * Build the versions list for the specified service by globbing the dir.
*/ */
private function buildVersionsList($service) private function buildVersionsList($service)
{ {
$dir = "{$this->modelsDir}/{$service}/"; $dir = "{$this->modelsDir}/{$service}/";
if (!is_dir($dir)) { if (!is_dir($dir)) {
return; return;
} }
// Get versions, remove . and .., and sort in descending order. // Get versions, remove . and .., and sort in descending order.
$results = array_diff(scandir($dir, SCANDIR_SORT_DESCENDING), ['..', '.']); $results = array_diff(scandir($dir, SCANDIR_SORT_DESCENDING), ['..', '.']);
if (!$results) { if (!$results) {
$this->manifest[$service] = ['versions' => []]; $this->manifest[$service] = ['versions' => []];
} else { } else {
$this->manifest[$service] = [ $this->manifest[$service] = [
'versions' => [ 'versions' => [
'latest' => $results[0] 'latest' => $results[0]
] ]
]; ];
$this->manifest[$service]['versions'] += array_combine($results, $results); $this->manifest[$service]['versions'] += array_combine($results, $results);
} }
} }
} }

View file

@ -1,134 +1,134 @@
<?php <?php
namespace Aws\Api; namespace Aws\Api;
use Aws\Api\Parser\Exception\ParserException; use Aws\Api\Parser\Exception\ParserException;
use DateTime; use DateTime;
use DateTimeZone; use DateTimeZone;
use Exception; use Exception;
/** /**
* DateTime overrides that make DateTime work more seamlessly as a string, * DateTime overrides that make DateTime work more seamlessly as a string,
* with JSON documents, and with JMESPath. * with JSON documents, and with JMESPath.
*/ */
class DateTimeResult extends \DateTime implements \JsonSerializable class DateTimeResult extends \DateTime implements \JsonSerializable
{ {
private const ISO8601_NANOSECOND_REGEX = '/^(.*\.\d{6})(\d{1,3})(Z|[+-]\d{2}:\d{2})?$/'; private const ISO8601_NANOSECOND_REGEX = '/^(.*\.\d{6})(\d{1,3})(Z|[+-]\d{2}:\d{2})?$/';
/** /**
* Create a new DateTimeResult from a unix timestamp. * Create a new DateTimeResult from a unix timestamp.
* The Unix epoch (or Unix time or POSIX time or Unix * The Unix epoch (or Unix time or POSIX time or Unix
* timestamp) is the number of seconds that have elapsed since * timestamp) is the number of seconds that have elapsed since
* January 1, 1970 (midnight UTC/GMT). * January 1, 1970 (midnight UTC/GMT).
* *
* @return DateTimeResult * @return DateTimeResult
* @throws Exception * @throws Exception
*/ */
public static function fromEpoch($unixTimestamp) public static function fromEpoch($unixTimestamp)
{ {
if (!is_numeric($unixTimestamp)) { if (!is_numeric($unixTimestamp)) {
throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromEpoch'); throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromEpoch');
} }
// PHP 5.5 does not support sub-second precision // PHP 5.5 does not support sub-second precision
if (\PHP_VERSION_ID < 56000) { if (\PHP_VERSION_ID < 56000) {
return new self(gmdate('c', $unixTimestamp)); return new self(gmdate('c', $unixTimestamp));
} }
$decimalSeparator = isset(localeconv()['decimal_point']) ? localeconv()['decimal_point'] : "."; $decimalSeparator = isset(localeconv()['decimal_point']) ? localeconv()['decimal_point'] : ".";
$formatString = "U" . $decimalSeparator . "u"; $formatString = "U" . $decimalSeparator . "u";
$dateTime = DateTime::createFromFormat( $dateTime = DateTime::createFromFormat(
$formatString, $formatString,
sprintf('%0.6f', $unixTimestamp), sprintf('%0.6f', $unixTimestamp),
new DateTimeZone('UTC') new DateTimeZone('UTC')
); );
if (false === $dateTime) { if (false === $dateTime) {
throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromEpoch'); throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromEpoch');
} }
return new self( return new self(
$dateTime->format('Y-m-d H:i:s.u'), $dateTime->format('Y-m-d H:i:s.u'),
new DateTimeZone('UTC') new DateTimeZone('UTC')
); );
} }
/** /**
* @return DateTimeResult * @return DateTimeResult
*/ */
public static function fromISO8601($iso8601Timestamp) public static function fromISO8601($iso8601Timestamp)
{ {
if (is_numeric($iso8601Timestamp) || !is_string($iso8601Timestamp)) { if (is_numeric($iso8601Timestamp) || !is_string($iso8601Timestamp)) {
throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromISO8601'); throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromISO8601');
} }
// Prior to 8.0.10, nanosecond precision is not supported // Prior to 8.0.10, nanosecond precision is not supported
// Reduces to microsecond precision if nanosecond precision is detected // Reduces to microsecond precision if nanosecond precision is detected
if (PHP_VERSION_ID < 80010 if (PHP_VERSION_ID < 80010
&& preg_match(self::ISO8601_NANOSECOND_REGEX, $iso8601Timestamp, $matches) && preg_match(self::ISO8601_NANOSECOND_REGEX, $iso8601Timestamp, $matches)
) { ) {
$iso8601Timestamp = $matches[1] . ($matches[3] ?? ''); $iso8601Timestamp = $matches[1] . ($matches[3] ?? '');
} }
return new DateTimeResult($iso8601Timestamp); return new DateTimeResult($iso8601Timestamp);
} }
/** /**
* Create a new DateTimeResult from an unknown timestamp. * Create a new DateTimeResult from an unknown timestamp.
* *
* @return DateTimeResult * @return DateTimeResult
* @throws Exception * @throws Exception
*/ */
public static function fromTimestamp($timestamp, $expectedFormat = null) public static function fromTimestamp($timestamp, $expectedFormat = null)
{ {
if (empty($timestamp)) { if (empty($timestamp)) {
return self::fromEpoch(0); return self::fromEpoch(0);
} }
if (!(is_string($timestamp) || is_numeric($timestamp))) { if (!(is_string($timestamp) || is_numeric($timestamp))) {
throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromTimestamp'); throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromTimestamp');
} }
try { try {
if ($expectedFormat == 'iso8601') { if ($expectedFormat == 'iso8601') {
try { try {
return self::fromISO8601($timestamp); return self::fromISO8601($timestamp);
} catch (Exception $exception) { } catch (Exception $exception) {
return self::fromEpoch($timestamp); return self::fromEpoch($timestamp);
} }
} else if ($expectedFormat == 'unixTimestamp') { } else if ($expectedFormat == 'unixTimestamp') {
try { try {
return self::fromEpoch($timestamp); return self::fromEpoch($timestamp);
} catch (Exception $exception) { } catch (Exception $exception) {
return self::fromISO8601($timestamp); return self::fromISO8601($timestamp);
} }
} else if (\Aws\is_valid_epoch($timestamp)) { } else if (\Aws\is_valid_epoch($timestamp)) {
return self::fromEpoch($timestamp); return self::fromEpoch($timestamp);
} }
return self::fromISO8601($timestamp); return self::fromISO8601($timestamp);
} catch (Exception $exception) { } catch (Exception $exception) {
throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromTimestamp'); throw new ParserException('Invalid timestamp value passed to DateTimeResult::fromTimestamp');
} }
} }
/** /**
* Serialize the DateTimeResult as an ISO 8601 date string. * Serialize the DateTimeResult as an ISO 8601 date string.
* *
* @return string * @return string
*/ */
public function __toString() public function __toString()
{ {
return $this->format('c'); return $this->format('c');
} }
/** /**
* Serialize the date as an ISO 8601 date when serializing as JSON. * Serialize the date as an ISO 8601 date when serializing as JSON.
* *
* @return string * @return string
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function jsonSerialize() public function jsonSerialize()
{ {
return (string) $this; return (string) $this;
} }
} }

View file

@ -1,139 +1,139 @@
<?php <?php
namespace Aws\Api; namespace Aws\Api;
/** /**
* Encapsulates the documentation strings for a given service-version and * Encapsulates the documentation strings for a given service-version and
* provides methods for extracting the desired parts related to a service, * provides methods for extracting the desired parts related to a service,
* operation, error, or shape (i.e., parameter). * operation, error, or shape (i.e., parameter).
*/ */
class DocModel class DocModel
{ {
/** @var array */ /** @var array */
private $docs; private $docs;
/** /**
* @param array $docs * @param array $docs
* *
* @throws \RuntimeException * @throws \RuntimeException
*/ */
public function __construct(array $docs) public function __construct(array $docs)
{ {
if (!extension_loaded('tidy')) { if (!extension_loaded('tidy')) {
throw new \RuntimeException('The "tidy" PHP extension is required.'); throw new \RuntimeException('The "tidy" PHP extension is required.');
} }
$this->docs = $docs; $this->docs = $docs;
} }
/** /**
* Convert the doc model to an array. * Convert the doc model to an array.
* *
* @return array * @return array
*/ */
public function toArray() public function toArray()
{ {
return $this->docs; return $this->docs;
} }
/** /**
* Retrieves documentation about the service. * Retrieves documentation about the service.
* *
* @return null|string * @return null|string
*/ */
public function getServiceDocs() public function getServiceDocs()
{ {
return isset($this->docs['service']) ? $this->docs['service'] : null; return isset($this->docs['service']) ? $this->docs['service'] : null;
} }
/** /**
* Retrieves documentation about an operation. * Retrieves documentation about an operation.
* *
* @param string $operation Name of the operation * @param string $operation Name of the operation
* *
* @return null|string * @return null|string
*/ */
public function getOperationDocs($operation) public function getOperationDocs($operation)
{ {
return isset($this->docs['operations'][$operation]) return isset($this->docs['operations'][$operation])
? $this->docs['operations'][$operation] ? $this->docs['operations'][$operation]
: null; : null;
} }
/** /**
* Retrieves documentation about an error. * Retrieves documentation about an error.
* *
* @param string $error Name of the error * @param string $error Name of the error
* *
* @return null|string * @return null|string
*/ */
public function getErrorDocs($error) public function getErrorDocs($error)
{ {
return isset($this->docs['shapes'][$error]['base']) return isset($this->docs['shapes'][$error]['base'])
? $this->docs['shapes'][$error]['base'] ? $this->docs['shapes'][$error]['base']
: null; : null;
} }
/** /**
* Retrieves documentation about a shape, specific to the context. * Retrieves documentation about a shape, specific to the context.
* *
* @param string $shapeName Name of the shape. * @param string $shapeName Name of the shape.
* @param string $parentName Name of the parent/context shape. * @param string $parentName Name of the parent/context shape.
* @param string $ref Name used by the context to reference the shape. * @param string $ref Name used by the context to reference the shape.
* *
* @return null|string * @return null|string
*/ */
public function getShapeDocs($shapeName, $parentName, $ref) public function getShapeDocs($shapeName, $parentName, $ref)
{ {
if (!isset($this->docs['shapes'][$shapeName])) { if (!isset($this->docs['shapes'][$shapeName])) {
return ''; return '';
} }
$result = ''; $result = '';
$d = $this->docs['shapes'][$shapeName]; $d = $this->docs['shapes'][$shapeName];
if (isset($d['refs']["{$parentName}\${$ref}"])) { if (isset($d['refs']["{$parentName}\${$ref}"])) {
$result = $d['refs']["{$parentName}\${$ref}"]; $result = $d['refs']["{$parentName}\${$ref}"];
} elseif (isset($d['base'])) { } elseif (isset($d['base'])) {
$result = $d['base']; $result = $d['base'];
} }
if (isset($d['append'])) { if (isset($d['append'])) {
if (!isset($d['excludeAppend']) if (!isset($d['excludeAppend'])
|| !in_array($parentName, $d['excludeAppend']) || !in_array($parentName, $d['excludeAppend'])
) { ) {
$result .= $d['append']; $result .= $d['append'];
} }
} }
if (isset($d['appendOnly']) if (isset($d['appendOnly'])
&& in_array($parentName, $d['appendOnly']['shapes']) && in_array($parentName, $d['appendOnly']['shapes'])
) { ) {
$result .= $d['appendOnly']['message']; $result .= $d['appendOnly']['message'];
} }
return $this->clean($result); return $this->clean($result);
} }
private function clean($content) private function clean($content)
{ {
if (!$content) { if (!$content) {
return ''; return '';
} }
$tidy = new \tidy(); $tidy = new \tidy();
$tidy->parseString($content, [ $tidy->parseString($content, [
'indent' => true, 'indent' => true,
'doctype' => 'omit', 'doctype' => 'omit',
'output-html' => true, 'output-html' => true,
'show-body-only' => true, 'show-body-only' => true,
'drop-empty-paras' => true, 'drop-empty-paras' => true,
'clean' => true, 'clean' => true,
'drop-proprietary-attributes' => true, 'drop-proprietary-attributes' => true,
'hide-comments' => true, 'hide-comments' => true,
'logical-emphasis' => true 'logical-emphasis' => true
]); ]);
$tidy->cleanRepair(); $tidy->cleanRepair();
return (string) $content; return (string) $content;
} }
} }

View file

@ -1,99 +1,99 @@
<?php <?php
namespace Aws\Api\ErrorParser; namespace Aws\Api\ErrorParser;
use Aws\Api\Parser\MetadataParserTrait; use Aws\Api\Parser\MetadataParserTrait;
use Aws\Api\Parser\PayloadParserTrait; use Aws\Api\Parser\PayloadParserTrait;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\CommandInterface; use Aws\CommandInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
abstract class AbstractErrorParser abstract class AbstractErrorParser
{ {
use MetadataParserTrait; use MetadataParserTrait;
use PayloadParserTrait; use PayloadParserTrait;
/** /**
* @var Service * @var Service
*/ */
protected $api; protected $api;
/** /**
* @param Service $api * @param Service $api
*/ */
public function __construct(?Service $api = null) public function __construct(?Service $api = null)
{ {
$this->api = $api; $this->api = $api;
} }
abstract protected function payload( abstract protected function payload(
ResponseInterface $response, ResponseInterface $response,
StructureShape $member StructureShape $member
); );
protected function extractPayload( protected function extractPayload(
StructureShape $member, StructureShape $member,
ResponseInterface $response ResponseInterface $response
) { ) {
if ($member instanceof StructureShape) { if ($member instanceof StructureShape) {
// Structure members parse top-level data into a specific key. // Structure members parse top-level data into a specific key.
return $this->payload($response, $member); return $this->payload($response, $member);
} else { } else {
// Streaming data is just the stream from the response body. // Streaming data is just the stream from the response body.
return $response->getBody(); return $response->getBody();
} }
} }
protected function populateShape( protected function populateShape(
array &$data, array &$data,
ResponseInterface $response, ResponseInterface $response,
?CommandInterface $command = null ?CommandInterface $command = null
) { ) {
$data['body'] = []; $data['body'] = [];
if (!empty($command) && !empty($this->api)) { if (!empty($command) && !empty($this->api)) {
// If modeled error code is indicated, check for known error shape // If modeled error code is indicated, check for known error shape
if (!empty($data['code'])) { if (!empty($data['code'])) {
$errors = $this->api->getOperation($command->getName())->getErrors(); $errors = $this->api->getOperation($command->getName())->getErrors();
foreach ($errors as $key => $error) { foreach ($errors as $key => $error) {
// If error code matches a known error shape, populate the body // If error code matches a known error shape, populate the body
if ($this->errorCodeMatches($data, $error)) { if ($this->errorCodeMatches($data, $error)) {
$modeledError = $error; $modeledError = $error;
$data['body'] = $this->extractPayload( $data['body'] = $this->extractPayload(
$modeledError, $modeledError,
$response $response
); );
$data['error_shape'] = $modeledError; $data['error_shape'] = $modeledError;
foreach ($error->getMembers() as $name => $member) { foreach ($error->getMembers() as $name => $member) {
switch ($member['location']) { switch ($member['location']) {
case 'header': case 'header':
$this->extractHeader($name, $member, $response, $data['body']); $this->extractHeader($name, $member, $response, $data['body']);
break; break;
case 'headers': case 'headers':
$this->extractHeaders($name, $member, $response, $data['body']); $this->extractHeaders($name, $member, $response, $data['body']);
break; break;
case 'statusCode': case 'statusCode':
$this->extractStatus($name, $response, $data['body']); $this->extractStatus($name, $response, $data['body']);
break; break;
} }
} }
break; break;
} }
} }
} }
} }
return $data; return $data;
} }
private function errorCodeMatches(array $data, $error): bool private function errorCodeMatches(array $data, $error): bool
{ {
return $data['code'] == $error['name'] return $data['code'] == $error['name']
|| (isset($error['error']['code']) && $data['code'] === $error['error']['code']); || (isset($error['error']['code']) && $data['code'] === $error['error']['code']);
} }
} }

View file

@ -1,144 +1,144 @@
<?php <?php
namespace Aws\Api\ErrorParser; namespace Aws\Api\ErrorParser;
use Aws\Api\Parser\PayloadParserTrait; use Aws\Api\Parser\PayloadParserTrait;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
/** /**
* Provides basic JSON error parsing functionality. * Provides basic JSON error parsing functionality.
*/ */
trait JsonParserTrait trait JsonParserTrait
{ {
use PayloadParserTrait; use PayloadParserTrait;
private function genericHandler(ResponseInterface $response): array private function genericHandler(ResponseInterface $response): array
{ {
$code = (string) $response->getStatusCode(); $code = (string) $response->getStatusCode();
$error_code = null; $error_code = null;
$error_type = null; $error_type = null;
// Parse error code and type for query compatible services // Parse error code and type for query compatible services
if ($this->api if ($this->api
&& !is_null($this->api->getMetadata('awsQueryCompatible')) && !is_null($this->api->getMetadata('awsQueryCompatible'))
&& $response->hasHeader('x-amzn-query-error') && $response->hasHeader('x-amzn-query-error')
) { ) {
$awsQueryError = $this->parseAwsQueryCompatibleHeader($response); $awsQueryError = $this->parseAwsQueryCompatibleHeader($response);
if ($awsQueryError) { if ($awsQueryError) {
$error_code = $awsQueryError['code']; $error_code = $awsQueryError['code'];
$error_type = $awsQueryError['type']; $error_type = $awsQueryError['type'];
} }
} }
// Parse error code from X-Amzn-Errortype header // Parse error code from X-Amzn-Errortype header
if (!$error_code && $response->hasHeader('X-Amzn-Errortype')) { if (!$error_code && $response->hasHeader('X-Amzn-Errortype')) {
$error_code = $this->extractErrorCode( $error_code = $this->extractErrorCode(
$response->getHeaderLine('X-Amzn-Errortype') $response->getHeaderLine('X-Amzn-Errortype')
); );
} }
$parsedBody = null; $parsedBody = null;
$body = $response->getBody(); $body = $response->getBody();
if (!$body->isSeekable() || $body->getSize()) { if (!$body->isSeekable() || $body->getSize()) {
$parsedBody = $this->parseJson((string) $body, $response); $parsedBody = $this->parseJson((string) $body, $response);
} }
// Parse error code from response body // Parse error code from response body
if (!$error_code && $parsedBody) { if (!$error_code && $parsedBody) {
$error_code = $this->parseErrorFromBody($parsedBody); $error_code = $this->parseErrorFromBody($parsedBody);
} }
if (!isset($error_type)) { if (!isset($error_type)) {
$error_type = $code[0] == '4' ? 'client' : 'server'; $error_type = $code[0] == '4' ? 'client' : 'server';
} }
return [ return [
'request_id' => $response->getHeaderLine('x-amzn-requestid'), 'request_id' => $response->getHeaderLine('x-amzn-requestid'),
'code' => $error_code ?? null, 'code' => $error_code ?? null,
'message' => null, 'message' => null,
'type' => $error_type, 'type' => $error_type,
'parsed' => $parsedBody 'parsed' => $parsedBody
]; ];
} }
/** /**
* Parse AWS Query Compatible error from header * Parse AWS Query Compatible error from header
* *
* @param ResponseInterface $response * @param ResponseInterface $response
* @return array|null Returns ['code' => string, 'type' => string] or null * @return array|null Returns ['code' => string, 'type' => string] or null
*/ */
private function parseAwsQueryCompatibleHeader(ResponseInterface $response): ?array private function parseAwsQueryCompatibleHeader(ResponseInterface $response): ?array
{ {
$queryError = $response->getHeaderLine('x-amzn-query-error'); $queryError = $response->getHeaderLine('x-amzn-query-error');
$parts = explode(';', $queryError); $parts = explode(';', $queryError);
if (count($parts) === 2 && $parts[0] && $parts[1]) { if (count($parts) === 2 && $parts[0] && $parts[1]) {
return [ return [
'code' => $parts[0], 'code' => $parts[0],
'type' => $parts[1] 'type' => $parts[1]
]; ];
} }
return null; return null;
} }
/** /**
* Parse error code from response body * Parse error code from response body
* *
* @param array|null $parsedBody * @param array|null $parsedBody
* @return string|null * @return string|null
*/ */
private function parseErrorFromBody(?array $parsedBody): ?string private function parseErrorFromBody(?array $parsedBody): ?string
{ {
if (!$parsedBody if (!$parsedBody
|| (!isset($parsedBody['code']) && !isset($parsedBody['__type'])) || (!isset($parsedBody['code']) && !isset($parsedBody['__type']))
) { ) {
return null; return null;
} }
$error_code = $parsedBody['code'] ?? $parsedBody['__type']; $error_code = $parsedBody['code'] ?? $parsedBody['__type'];
return $this->extractErrorCode($error_code); return $this->extractErrorCode($error_code);
} }
/** /**
* Extract error code from raw error string containing # and/or : delimiters * Extract error code from raw error string containing # and/or : delimiters
* *
* @param string $rawErrorCode * @param string $rawErrorCode
* @return string * @return string
*/ */
private function extractErrorCode(string $rawErrorCode): string private function extractErrorCode(string $rawErrorCode): string
{ {
// Handle format with both # and uri (e.g., "namespace#http://foo-bar") // Handle format with both # and uri (e.g., "namespace#http://foo-bar")
if (str_contains($rawErrorCode, ':') && str_contains($rawErrorCode, '#')) { if (str_contains($rawErrorCode, ':') && str_contains($rawErrorCode, '#')) {
$start = strpos($rawErrorCode, '#') + 1; $start = strpos($rawErrorCode, '#') + 1;
$end = strpos($rawErrorCode, ':', $start); $end = strpos($rawErrorCode, ':', $start);
return substr($rawErrorCode, $start, $end - $start); return substr($rawErrorCode, $start, $end - $start);
} }
// Handle format with uri only : (e.g., "ErrorCode:http://foo-bar.com/baz") // Handle format with uri only : (e.g., "ErrorCode:http://foo-bar.com/baz")
if (str_contains($rawErrorCode, ':')) { if (str_contains($rawErrorCode, ':')) {
return substr($rawErrorCode, 0, strpos($rawErrorCode, ':')); return substr($rawErrorCode, 0, strpos($rawErrorCode, ':'));
} }
// Handle format with only # (e.g., "namespace#ErrorCode") // Handle format with only # (e.g., "namespace#ErrorCode")
if (str_contains($rawErrorCode, '#')) { if (str_contains($rawErrorCode, '#')) {
return substr($rawErrorCode, strpos($rawErrorCode, '#') + 1); return substr($rawErrorCode, strpos($rawErrorCode, '#') + 1);
} }
return $rawErrorCode; return $rawErrorCode;
} }
protected function payload( protected function payload(
ResponseInterface $response, ResponseInterface $response,
StructureShape $member StructureShape $member
) { ) {
$body = $response->getBody(); $body = $response->getBody();
if (!$body->isSeekable() || $body->getSize()) { if (!$body->isSeekable() || $body->getSize()) {
$jsonBody = $this->parseJson($body, $response); $jsonBody = $this->parseJson($body, $response);
} else { } else {
$jsonBody = (string) $body; $jsonBody = (string) $body;
} }
return $this->parser->parse($member, $jsonBody); return $this->parser->parse($member, $jsonBody);
} }
} }

View file

@ -1,47 +1,47 @@
<?php <?php
namespace Aws\Api\ErrorParser; namespace Aws\Api\ErrorParser;
use Aws\Api\Parser\JsonParser; use Aws\Api\Parser\JsonParser;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\CommandInterface; use Aws\CommandInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
/** /**
* Parsers JSON-RPC errors. * Parsers JSON-RPC errors.
*/ */
class JsonRpcErrorParser extends AbstractErrorParser class JsonRpcErrorParser extends AbstractErrorParser
{ {
use JsonParserTrait; use JsonParserTrait;
private $parser; private $parser;
public function __construct(?Service $api = null, ?JsonParser $parser = null) public function __construct(?Service $api = null, ?JsonParser $parser = null)
{ {
parent::__construct($api); parent::__construct($api);
$this->parser = $parser ?: new JsonParser(); $this->parser = $parser ?: new JsonParser();
} }
public function __invoke( public function __invoke(
ResponseInterface $response, ResponseInterface $response,
?CommandInterface $command = null ?CommandInterface $command = null
) { ) {
$data = $this->genericHandler($response); $data = $this->genericHandler($response);
// Make the casing consistent across services. // Make the casing consistent across services.
if ($data['parsed']) { if ($data['parsed']) {
$data['parsed'] = array_change_key_case($data['parsed']); $data['parsed'] = array_change_key_case($data['parsed']);
} }
if (isset($data['parsed']['__type'])) { if (isset($data['parsed']['__type'])) {
if (!isset($data['code'])) { if (!isset($data['code'])) {
$parts = explode('#', $data['parsed']['__type']); $parts = explode('#', $data['parsed']['__type']);
$data['code'] = isset($parts[1]) ? $parts[1] : $parts[0]; $data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
} }
$data['message'] = $data['parsed']['message'] ?? null; $data['message'] = $data['parsed']['message'] ?? null;
} }
$this->populateShape($data, $response, $command); $this->populateShape($data, $response, $command);
return $data; return $data;
} }
} }

View file

@ -1,49 +1,49 @@
<?php <?php
namespace Aws\Api\ErrorParser; namespace Aws\Api\ErrorParser;
use Aws\Api\Parser\JsonParser; use Aws\Api\Parser\JsonParser;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\CommandInterface; use Aws\CommandInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
/** /**
* Parses JSON-REST errors. * Parses JSON-REST errors.
*/ */
class RestJsonErrorParser extends AbstractErrorParser class RestJsonErrorParser extends AbstractErrorParser
{ {
use JsonParserTrait; use JsonParserTrait;
private $parser; private $parser;
public function __construct(?Service $api = null, ?JsonParser $parser = null) public function __construct(?Service $api = null, ?JsonParser $parser = null)
{ {
parent::__construct($api); parent::__construct($api);
$this->parser = $parser ?: new JsonParser(); $this->parser = $parser ?: new JsonParser();
} }
public function __invoke( public function __invoke(
ResponseInterface $response, ResponseInterface $response,
?CommandInterface $command = null ?CommandInterface $command = null
) { ) {
$data = $this->genericHandler($response); $data = $this->genericHandler($response);
// Merge in error data from the JSON body // Merge in error data from the JSON body
if ($json = $data['parsed']) { if ($json = $data['parsed']) {
$data = array_replace($json, $data); $data = array_replace($json, $data);
} }
// Correct error type from services like Amazon Glacier // Correct error type from services like Amazon Glacier
if (!empty($data['type'])) { if (!empty($data['type'])) {
$data['type'] = strtolower($data['type']); $data['type'] = strtolower($data['type']);
} }
// Retrieve error message directly // Retrieve error message directly
$data['message'] = $data['parsed']['message'] $data['message'] = $data['parsed']['message']
?? ($data['parsed']['Message'] ?? null); ?? ($data['parsed']['Message'] ?? null);
$this->populateShape($data, $response, $command); $this->populateShape($data, $response, $command);
return $data; return $data;
} }
} }

View file

@ -1,111 +1,111 @@
<?php <?php
namespace Aws\Api\ErrorParser; namespace Aws\Api\ErrorParser;
use Aws\Api\Parser\PayloadParserTrait; use Aws\Api\Parser\PayloadParserTrait;
use Aws\Api\Parser\XmlParser; use Aws\Api\Parser\XmlParser;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\CommandInterface; use Aws\CommandInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
/** /**
* Parses XML errors. * Parses XML errors.
*/ */
class XmlErrorParser extends AbstractErrorParser class XmlErrorParser extends AbstractErrorParser
{ {
use PayloadParserTrait; use PayloadParserTrait;
protected $parser; protected $parser;
public function __construct(?Service $api = null, ?XmlParser $parser = null) public function __construct(?Service $api = null, ?XmlParser $parser = null)
{ {
parent::__construct($api); parent::__construct($api);
$this->parser = $parser ?: new XmlParser(); $this->parser = $parser ?: new XmlParser();
} }
public function __invoke( public function __invoke(
ResponseInterface $response, ResponseInterface $response,
?CommandInterface $command = null ?CommandInterface $command = null
) { ) {
$code = (string) $response->getStatusCode(); $code = (string) $response->getStatusCode();
$data = [ $data = [
'type' => $code[0] == '4' ? 'client' : 'server', 'type' => $code[0] == '4' ? 'client' : 'server',
'request_id' => null, 'request_id' => null,
'code' => null, 'code' => null,
'message' => null, 'message' => null,
'parsed' => null 'parsed' => null
]; ];
$body = $response->getBody(); $body = $response->getBody();
if ($body->getSize() > 0) { if ($body->getSize() > 0) {
$this->parseBody($this->parseXml($body, $response), $data); $this->parseBody($this->parseXml($body, $response), $data);
} else { } else {
$this->parseHeaders($response, $data); $this->parseHeaders($response, $data);
} }
$this->populateShape($data, $response, $command); $this->populateShape($data, $response, $command);
return $data; return $data;
} }
private function parseHeaders(ResponseInterface $response, array &$data) private function parseHeaders(ResponseInterface $response, array &$data)
{ {
if ($response->getStatusCode() == '404') { if ($response->getStatusCode() == '404') {
$data['code'] = 'NotFound'; $data['code'] = 'NotFound';
} }
$data['message'] = $response->getStatusCode() . ' ' $data['message'] = $response->getStatusCode() . ' '
. $response->getReasonPhrase(); . $response->getReasonPhrase();
if ($requestId = $response->getHeaderLine('x-amz-request-id')) { if ($requestId = $response->getHeaderLine('x-amz-request-id')) {
$data['request_id'] = $requestId; $data['request_id'] = $requestId;
$data['message'] .= " (Request-ID: $requestId)"; $data['message'] .= " (Request-ID: $requestId)";
} }
} }
private function parseBody(\SimpleXMLElement $body, array &$data) private function parseBody(\SimpleXMLElement $body, array &$data)
{ {
$data['parsed'] = $body; $data['parsed'] = $body;
$prefix = $this->registerNamespacePrefix($body); $prefix = $this->registerNamespacePrefix($body);
if ($tempXml = $body->xpath("//{$prefix}Code[1]")) { if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
$data['code'] = (string) $tempXml[0]; $data['code'] = (string) $tempXml[0];
} }
if ($tempXml = $body->xpath("//{$prefix}Message[1]")) { if ($tempXml = $body->xpath("//{$prefix}Message[1]")) {
$data['message'] = (string) $tempXml[0]; $data['message'] = (string) $tempXml[0];
} }
$tempXml = $body->xpath("//{$prefix}RequestId[1]"); $tempXml = $body->xpath("//{$prefix}RequestId[1]");
if (isset($tempXml[0])) { if (isset($tempXml[0])) {
$data['request_id'] = (string)$tempXml[0]; $data['request_id'] = (string)$tempXml[0];
} }
} }
protected function registerNamespacePrefix(\SimpleXMLElement $element) protected function registerNamespacePrefix(\SimpleXMLElement $element)
{ {
$namespaces = $element->getDocNamespaces(); $namespaces = $element->getDocNamespaces();
if (!isset($namespaces[''])) { if (!isset($namespaces[''])) {
return ''; return '';
} }
// Account for the default namespace being defined and PHP not // Account for the default namespace being defined and PHP not
// being able to handle it :(. // being able to handle it :(.
$element->registerXPathNamespace('ns', $namespaces['']); $element->registerXPathNamespace('ns', $namespaces['']);
return 'ns:'; return 'ns:';
} }
protected function payload( protected function payload(
ResponseInterface $response, ResponseInterface $response,
StructureShape $member StructureShape $member
) { ) {
$xmlBody = $this->parseXml($response->getBody(), $response); $xmlBody = $this->parseXml($response->getBody(), $response);
$prefix = $this->registerNamespacePrefix($xmlBody); $prefix = $this->registerNamespacePrefix($xmlBody);
$errorBody = $xmlBody->xpath("//{$prefix}Error"); $errorBody = $xmlBody->xpath("//{$prefix}Error");
if (is_array($errorBody) && !empty($errorBody[0])) { if (is_array($errorBody) && !empty($errorBody[0])) {
return $this->parser->parse($member, $errorBody[0]); return $this->parser->parse($member, $errorBody[0]);
} }
} }
} }

View file

@ -1,35 +1,35 @@
<?php <?php
namespace Aws\Api; namespace Aws\Api;
/** /**
* Represents a list shape. * Represents a list shape.
*/ */
class ListShape extends Shape class ListShape extends Shape
{ {
private $member; private $member;
public function __construct(array $definition, ShapeMap $shapeMap) public function __construct(array $definition, ShapeMap $shapeMap)
{ {
$definition['type'] = 'list'; $definition['type'] = 'list';
parent::__construct($definition, $shapeMap); parent::__construct($definition, $shapeMap);
} }
/** /**
* @return Shape * @return Shape
* @throws \RuntimeException if no member is specified * @throws \RuntimeException if no member is specified
*/ */
public function getMember() public function getMember()
{ {
if (!$this->member) { if (!$this->member) {
if (!isset($this->definition['member'])) { if (!isset($this->definition['member'])) {
throw new \RuntimeException('No member attribute specified'); throw new \RuntimeException('No member attribute specified');
} }
$this->member = Shape::create( $this->member = Shape::create(
$this->definition['member'], $this->definition['member'],
$this->shapeMap $this->shapeMap
); );
} }
return $this->member; return $this->member;
} }
} }

View file

@ -1,54 +1,54 @@
<?php <?php
namespace Aws\Api; namespace Aws\Api;
/** /**
* Represents a map shape. * Represents a map shape.
*/ */
class MapShape extends Shape class MapShape extends Shape
{ {
/** @var Shape */ /** @var Shape */
private $value; private $value;
/** @var Shape */ /** @var Shape */
private $key; private $key;
public function __construct(array $definition, ShapeMap $shapeMap) public function __construct(array $definition, ShapeMap $shapeMap)
{ {
$definition['type'] = 'map'; $definition['type'] = 'map';
parent::__construct($definition, $shapeMap); parent::__construct($definition, $shapeMap);
} }
/** /**
* @return Shape * @return Shape
* @throws \RuntimeException if no value is specified * @throws \RuntimeException if no value is specified
*/ */
public function getValue() public function getValue()
{ {
if (!$this->value) { if (!$this->value) {
if (!isset($this->definition['value'])) { if (!isset($this->definition['value'])) {
throw new \RuntimeException('No value specified'); throw new \RuntimeException('No value specified');
} }
$this->value = Shape::create( $this->value = Shape::create(
$this->definition['value'], $this->definition['value'],
$this->shapeMap $this->shapeMap
); );
} }
return $this->value; return $this->value;
} }
/** /**
* @return Shape * @return Shape
*/ */
public function getKey() public function getKey()
{ {
if (!$this->key) { if (!$this->key) {
$this->key = isset($this->definition['key']) $this->key = isset($this->definition['key'])
? Shape::create($this->definition['key'], $this->shapeMap) ? Shape::create($this->definition['key'], $this->shapeMap)
: new Shape(['type' => 'string'], $this->shapeMap); : new Shape(['type' => 'string'], $this->shapeMap);
} }
return $this->key; return $this->key;
} }
} }

View file

@ -1,158 +1,158 @@
<?php <?php
namespace Aws\Api; namespace Aws\Api;
/** /**
* Represents an API operation. * Represents an API operation.
*/ */
class Operation extends AbstractModel class Operation extends AbstractModel
{ {
private $input; private $input;
private $output; private $output;
private $errors; private $errors;
private $staticContextParams = []; private $staticContextParams = [];
private $contextParams; private $contextParams;
private $operationContextParams = []; private $operationContextParams = [];
public function __construct(array $definition, ShapeMap $shapeMap) public function __construct(array $definition, ShapeMap $shapeMap)
{ {
$definition['type'] = 'structure'; $definition['type'] = 'structure';
if (!isset($definition['http']['method'])) { if (!isset($definition['http']['method'])) {
$definition['http']['method'] = 'POST'; $definition['http']['method'] = 'POST';
} }
if (!isset($definition['http']['requestUri'])) { if (!isset($definition['http']['requestUri'])) {
$definition['http']['requestUri'] = '/'; $definition['http']['requestUri'] = '/';
} }
if (isset($definition['staticContextParams'])) { if (isset($definition['staticContextParams'])) {
$this->staticContextParams = $definition['staticContextParams']; $this->staticContextParams = $definition['staticContextParams'];
} }
if (isset($definition['operationContextParams'])) { if (isset($definition['operationContextParams'])) {
$this->operationContextParams = $definition['operationContextParams']; $this->operationContextParams = $definition['operationContextParams'];
} }
parent::__construct($definition, $shapeMap); parent::__construct($definition, $shapeMap);
$this->contextParams = $this->setContextParams(); $this->contextParams = $this->setContextParams();
} }
/** /**
* Returns an associative array of the HTTP attribute of the operation: * Returns an associative array of the HTTP attribute of the operation:
* *
* - method: HTTP method of the operation * - method: HTTP method of the operation
* - requestUri: URI of the request (can include URI template placeholders) * - requestUri: URI of the request (can include URI template placeholders)
* *
* @return array * @return array
*/ */
public function getHttp() public function getHttp()
{ {
return $this->definition['http']; return $this->definition['http'];
} }
/** /**
* Get the input shape of the operation. * Get the input shape of the operation.
* *
* @return StructureShape * @return StructureShape
*/ */
public function getInput() public function getInput()
{ {
if (!$this->input) { if (!$this->input) {
if ($input = $this['input']) { if ($input = $this['input']) {
$this->input = $this->shapeFor($input); $this->input = $this->shapeFor($input);
} else { } else {
$this->input = new StructureShape([], $this->shapeMap); $this->input = new StructureShape([], $this->shapeMap);
} }
} }
return $this->input; return $this->input;
} }
/** /**
* Get the output shape of the operation. * Get the output shape of the operation.
* *
* @return StructureShape * @return StructureShape
*/ */
public function getOutput() public function getOutput()
{ {
if (!$this->output) { if (!$this->output) {
if ($output = $this['output']) { if ($output = $this['output']) {
$this->output = $this->shapeFor($output); $this->output = $this->shapeFor($output);
} else { } else {
$this->output = new StructureShape([], $this->shapeMap); $this->output = new StructureShape([], $this->shapeMap);
} }
} }
return $this->output; return $this->output;
} }
/** /**
* Get an array of operation error shapes. * Get an array of operation error shapes.
* *
* @return Shape[] * @return Shape[]
*/ */
public function getErrors() public function getErrors()
{ {
if ($this->errors === null) { if ($this->errors === null) {
if ($errors = $this['errors']) { if ($errors = $this['errors']) {
foreach ($errors as $key => $error) { foreach ($errors as $key => $error) {
$errors[$key] = $this->shapeFor($error); $errors[$key] = $this->shapeFor($error);
} }
$this->errors = $errors; $this->errors = $errors;
} else { } else {
$this->errors = []; $this->errors = [];
} }
} }
return $this->errors; return $this->errors;
} }
/** /**
* Gets static modeled static values used for * Gets static modeled static values used for
* endpoint resolution. * endpoint resolution.
* *
* @return array * @return array
*/ */
public function getStaticContextParams() public function getStaticContextParams()
{ {
return $this->staticContextParams; return $this->staticContextParams;
} }
/** /**
* Gets definition of modeled dynamic values used * Gets definition of modeled dynamic values used
* for endpoint resolution * for endpoint resolution
* *
* @return array * @return array
*/ */
public function getContextParams() public function getContextParams()
{ {
return $this->contextParams; return $this->contextParams;
} }
/** /**
* Gets definition of modeled dynamic values used * Gets definition of modeled dynamic values used
* for endpoint resolution * for endpoint resolution
* *
* @return array * @return array
*/ */
public function getOperationContextParams(): array public function getOperationContextParams(): array
{ {
return $this->operationContextParams; return $this->operationContextParams;
} }
private function setContextParams() private function setContextParams()
{ {
$members = $this->getInput()->getMembers(); $members = $this->getInput()->getMembers();
$contextParams = []; $contextParams = [];
foreach($members as $name => $shape) { foreach($members as $name => $shape) {
if (!empty($contextParam = $shape->getContextParam())) { if (!empty($contextParam = $shape->getContextParam())) {
$contextParams[$contextParam['name']] = [ $contextParams[$contextParam['name']] = [
'shape' => $name, 'shape' => $name,
'type' => $shape->getType() 'type' => $shape->getType()
]; ];
} }
} }
return $contextParams; return $contextParams;
} }
} }

View file

@ -1,46 +1,46 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\CommandInterface; use Aws\CommandInterface;
use Aws\ResultInterface; use Aws\ResultInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
/** /**
* @internal * @internal
*/ */
abstract class AbstractParser abstract class AbstractParser
{ {
/** @var \Aws\Api\Service Representation of the service API*/ /** @var \Aws\Api\Service Representation of the service API*/
protected $api; protected $api;
/** @var callable */ /** @var callable */
protected $parser; protected $parser;
/** /**
* @param Service $api Service description. * @param Service $api Service description.
*/ */
public function __construct(Service $api) public function __construct(Service $api)
{ {
$this->api = $api; $this->api = $api;
} }
/** /**
* @param CommandInterface $command Command that was executed. * @param CommandInterface $command Command that was executed.
* @param ResponseInterface $response Response that was received. * @param ResponseInterface $response Response that was received.
* *
* @return ResultInterface * @return ResultInterface
*/ */
abstract public function __invoke( abstract public function __invoke(
CommandInterface $command, CommandInterface $command,
ResponseInterface $response ResponseInterface $response
); );
abstract public function parseMemberFromStream( abstract public function parseMemberFromStream(
StreamInterface $stream, StreamInterface $stream,
StructureShape $member, StructureShape $member,
$response $response
); );
} }

View file

@ -1,216 +1,216 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\DateTimeResult; use Aws\Api\DateTimeResult;
use Aws\Api\Shape; use Aws\Api\Shape;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\Result; use Aws\Result;
use Aws\CommandInterface; use Aws\CommandInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
/** /**
* @internal * @internal
*/ */
abstract class AbstractRestParser extends AbstractParser abstract class AbstractRestParser extends AbstractParser
{ {
use PayloadParserTrait; use PayloadParserTrait;
/** /**
* Parses a payload from a response. * Parses a payload from a response.
* *
* @param ResponseInterface $response Response to parse. * @param ResponseInterface $response Response to parse.
* @param StructureShape $member Member to parse * @param StructureShape $member Member to parse
* @param array $result Result value * @param array $result Result value
* *
* @return mixed * @return mixed
*/ */
abstract protected function payload( abstract protected function payload(
ResponseInterface $response, ResponseInterface $response,
StructureShape $member, StructureShape $member,
array &$result array &$result
); );
public function __invoke( public function __invoke(
CommandInterface $command, CommandInterface $command,
ResponseInterface $response ResponseInterface $response
) { ) {
$output = $this->api->getOperation($command->getName())->getOutput(); $output = $this->api->getOperation($command->getName())->getOutput();
$result = []; $result = [];
if ($payload = $output['payload']) { if ($payload = $output['payload']) {
$this->extractPayload($payload, $output, $response, $result); $this->extractPayload($payload, $output, $response, $result);
} }
foreach ($output->getMembers() as $name => $member) { foreach ($output->getMembers() as $name => $member) {
switch ($member['location']) { switch ($member['location']) {
case 'header': case 'header':
$this->extractHeader($name, $member, $response, $result); $this->extractHeader($name, $member, $response, $result);
break; break;
case 'headers': case 'headers':
$this->extractHeaders($name, $member, $response, $result); $this->extractHeaders($name, $member, $response, $result);
break; break;
case 'statusCode': case 'statusCode':
$this->extractStatus($name, $response, $result); $this->extractStatus($name, $response, $result);
break; break;
} }
} }
$body = $response->getBody(); $body = $response->getBody();
if (!$payload if (!$payload
&& (!$body->isSeekable() || $body->getSize()) && (!$body->isSeekable() || $body->getSize())
&& count($output->getMembers()) > 0 && count($output->getMembers()) > 0
) { ) {
// if no payload was found, then parse the contents of the body // if no payload was found, then parse the contents of the body
$this->payload($response, $output, $result); $this->payload($response, $output, $result);
} }
return new Result($result); return new Result($result);
} }
private function extractPayload( private function extractPayload(
$payload, $payload,
StructureShape $output, StructureShape $output,
ResponseInterface $response, ResponseInterface $response,
array &$result array &$result
) { ) {
$member = $output->getMember($payload); $member = $output->getMember($payload);
$body = $response->getBody(); $body = $response->getBody();
if (!empty($member['eventstream'])) { if (!empty($member['eventstream'])) {
$result[$payload] = new EventParsingIterator( $result[$payload] = new EventParsingIterator(
$body, $body,
$member, $member,
$this $this
); );
} elseif ($member instanceof StructureShape) { } elseif ($member instanceof StructureShape) {
//Unions must have at least one member set to a non-null value //Unions must have at least one member set to a non-null value
// If the body is empty, we can assume it is unset // If the body is empty, we can assume it is unset
if (!empty($member['union']) && ($body->isSeekable() && !$body->getSize())) { if (!empty($member['union']) && ($body->isSeekable() && !$body->getSize())) {
return; return;
} }
$result[$payload] = []; $result[$payload] = [];
$this->payload($response, $member, $result[$payload]); $this->payload($response, $member, $result[$payload]);
} else { } else {
// Always set the payload to the body stream, regardless of content // Always set the payload to the body stream, regardless of content
$result[$payload] = $body; $result[$payload] = $body;
} }
} }
/** /**
* Extract a single header from the response into the result. * Extract a single header from the response into the result.
*/ */
private function extractHeader( private function extractHeader(
$name, $name,
Shape $shape, Shape $shape,
ResponseInterface $response, ResponseInterface $response,
&$result &$result
) { ) {
$value = $response->getHeaderLine($shape['locationName'] ?: $name); $value = $response->getHeaderLine($shape['locationName'] ?: $name);
// Empty headers should not be deserialized // Empty headers should not be deserialized
if ($value === null || $value === '') { if ($value === null || $value === '') {
return; return;
} }
switch ($shape->getType()) { switch ($shape->getType()) {
case 'float': case 'float':
case 'double': case 'double':
$value = match ($value) { $value = match ($value) {
'NaN', 'Infinity', '-Infinity' => $value, 'NaN', 'Infinity', '-Infinity' => $value,
default => (float) $value default => (float) $value
}; };
break; break;
case 'long': case 'long':
case 'integer': case 'integer':
$value = (int) $value; $value = (int) $value;
break; break;
case 'boolean': case 'boolean':
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN); $value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
break; break;
case 'blob': case 'blob':
$value = base64_decode($value); $value = base64_decode($value);
break; break;
case 'timestamp': case 'timestamp':
try { try {
$value = DateTimeResult::fromTimestamp( $value = DateTimeResult::fromTimestamp(
$value, $value,
!empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null !empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null
); );
break; break;
} catch (\Exception $e) { } catch (\Exception $e) {
// If the value cannot be parsed, then do not add it to the // If the value cannot be parsed, then do not add it to the
// output structure. // output structure.
return; return;
} }
case 'string': case 'string':
try { try {
if ($shape['jsonvalue']) { if ($shape['jsonvalue']) {
$value = $this->parseJson(base64_decode($value), $response); $value = $this->parseJson(base64_decode($value), $response);
} }
// If value is not set, do not add to output structure. // If value is not set, do not add to output structure.
if (!isset($value)) { if (!isset($value)) {
return; return;
} }
break; break;
} catch (\Exception $e) { } catch (\Exception $e) {
//If the value cannot be parsed, then do not add it to the //If the value cannot be parsed, then do not add it to the
//output structure. //output structure.
return; return;
} }
case 'list': case 'list':
$listMember = $shape->getMember(); $listMember = $shape->getMember();
$type = $listMember->getType(); $type = $listMember->getType();
// Only boolean lists require special handling // Only boolean lists require special handling
// other types can be returned as-is // other types can be returned as-is
if ($type !== 'boolean') { if ($type !== 'boolean') {
break; break;
} }
$items = array_map('trim', explode(',', $value)); $items = array_map('trim', explode(',', $value));
$value = array_map( $value = array_map(
static fn($item) => filter_var($item, FILTER_VALIDATE_BOOLEAN), static fn($item) => filter_var($item, FILTER_VALIDATE_BOOLEAN),
$items $items
); );
break; break;
} }
$result[$name] = $value; $result[$name] = $value;
} }
/** /**
* Extract a map of headers with an optional prefix from the response. * Extract a map of headers with an optional prefix from the response.
*/ */
private function extractHeaders( private function extractHeaders(
$name, $name,
Shape $shape, Shape $shape,
ResponseInterface $response, ResponseInterface $response,
&$result &$result
) { ) {
// Check if the headers are prefixed by a location name // Check if the headers are prefixed by a location name
$result[$name] = []; $result[$name] = [];
$prefix = $shape['locationName']; $prefix = $shape['locationName'];
$prefixLen = $prefix !== null ? strlen($prefix) : 0; $prefixLen = $prefix !== null ? strlen($prefix) : 0;
foreach ($response->getHeaders() as $k => $values) { foreach ($response->getHeaders() as $k => $values) {
if (!$prefixLen) { if (!$prefixLen) {
$result[$name][$k] = implode(', ', $values); $result[$name][$k] = implode(', ', $values);
} elseif (stripos($k, $prefix) === 0) { } elseif (stripos($k, $prefix) === 0) {
$result[$name][substr($k, $prefixLen)] = implode(', ', $values); $result[$name][substr($k, $prefixLen)] = implode(', ', $values);
} }
} }
} }
/** /**
* Places the status code of the response into the result array. * Places the status code of the response into the result array.
*/ */
private function extractStatus( private function extractStatus(
$name, $name,
ResponseInterface $response, ResponseInterface $response,
array &$result array &$result
) { ) {
$result[$name] = (int) $response->getStatusCode(); $result[$name] = (int) $response->getStatusCode();
} }
} }

View file

@ -1,54 +1,54 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\CommandInterface; use Aws\CommandInterface;
use Aws\Exception\AwsException; use Aws\Exception\AwsException;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
/** /**
* @internal Decorates a parser and validates the x-amz-crc32 header. * @internal Decorates a parser and validates the x-amz-crc32 header.
*/ */
class Crc32ValidatingParser extends AbstractParser class Crc32ValidatingParser extends AbstractParser
{ {
/** /**
* @param callable $parser Parser to wrap. * @param callable $parser Parser to wrap.
*/ */
public function __construct(callable $parser) public function __construct(callable $parser)
{ {
$this->parser = $parser; $this->parser = $parser;
} }
public function __invoke( public function __invoke(
CommandInterface $command, CommandInterface $command,
ResponseInterface $response ResponseInterface $response
) { ) {
if ($expected = $response->getHeaderLine('x-amz-crc32')) { if ($expected = $response->getHeaderLine('x-amz-crc32')) {
$hash = hexdec(Psr7\Utils::hash($response->getBody(), 'crc32b')); $hash = hexdec(Psr7\Utils::hash($response->getBody(), 'crc32b'));
if ($expected != $hash) { if ($expected != $hash) {
throw new AwsException( throw new AwsException(
"crc32 mismatch. Expected {$expected}, found {$hash}.", "crc32 mismatch. Expected {$expected}, found {$hash}.",
$command, $command,
[ [
'code' => 'ClientChecksumMismatch', 'code' => 'ClientChecksumMismatch',
'connection_error' => true, 'connection_error' => true,
'response' => $response 'response' => $response
] ]
); );
} }
} }
$fn = $this->parser; $fn = $this->parser;
return $fn($command, $response); return $fn($command, $response);
} }
public function parseMemberFromStream( public function parseMemberFromStream(
StreamInterface $stream, StreamInterface $stream,
StructureShape $member, StructureShape $member,
$response $response
) { ) {
return $this->parser->parseMemberFromStream($stream, $member, $response); return $this->parser->parseMemberFromStream($stream, $member, $response);
} }
} }

View file

@ -1,347 +1,347 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use \Iterator; use \Iterator;
use Aws\Api\DateTimeResult; use Aws\Api\DateTimeResult;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
use Aws\Api\Parser\Exception\ParserException; use Aws\Api\Parser\Exception\ParserException;
/** /**
* @internal Implements a decoder for a binary encoded event stream that will * @internal Implements a decoder for a binary encoded event stream that will
* decode, validate, and provide individual events from the stream. * decode, validate, and provide individual events from the stream.
*/ */
class DecodingEventStreamIterator implements Iterator class DecodingEventStreamIterator implements Iterator
{ {
const HEADERS = 'headers'; const HEADERS = 'headers';
const PAYLOAD = 'payload'; const PAYLOAD = 'payload';
const LENGTH_TOTAL = 'total_length'; const LENGTH_TOTAL = 'total_length';
const LENGTH_HEADERS = 'headers_length'; const LENGTH_HEADERS = 'headers_length';
const CRC_PRELUDE = 'prelude_crc'; const CRC_PRELUDE = 'prelude_crc';
const BYTES_PRELUDE = 12; const BYTES_PRELUDE = 12;
const BYTES_TRAILING = 4; const BYTES_TRAILING = 4;
private static $preludeFormat = [ private static $preludeFormat = [
self::LENGTH_TOTAL => 'decodeUint32', self::LENGTH_TOTAL => 'decodeUint32',
self::LENGTH_HEADERS => 'decodeUint32', self::LENGTH_HEADERS => 'decodeUint32',
self::CRC_PRELUDE => 'decodeUint32', self::CRC_PRELUDE => 'decodeUint32',
]; ];
private static $lengthFormatMap = [ private static $lengthFormatMap = [
1 => 'decodeUint8', 1 => 'decodeUint8',
2 => 'decodeUint16', 2 => 'decodeUint16',
4 => 'decodeUint32', 4 => 'decodeUint32',
8 => 'decodeUint64', 8 => 'decodeUint64',
]; ];
private static $headerTypeMap = [ private static $headerTypeMap = [
0 => 'decodeBooleanTrue', 0 => 'decodeBooleanTrue',
1 => 'decodeBooleanFalse', 1 => 'decodeBooleanFalse',
2 => 'decodeInt8', 2 => 'decodeInt8',
3 => 'decodeInt16', 3 => 'decodeInt16',
4 => 'decodeInt32', 4 => 'decodeInt32',
5 => 'decodeInt64', 5 => 'decodeInt64',
6 => 'decodeBytes', 6 => 'decodeBytes',
7 => 'decodeString', 7 => 'decodeString',
8 => 'decodeTimestamp', 8 => 'decodeTimestamp',
9 => 'decodeUuid', 9 => 'decodeUuid',
]; ];
/** @var StreamInterface Stream of eventstream shape to parse. */ /** @var StreamInterface Stream of eventstream shape to parse. */
protected $stream; protected $stream;
/** @var array Currently parsed event. */ /** @var array Currently parsed event. */
protected $currentEvent; protected $currentEvent;
/** @var int Current in-order event key. */ /** @var int Current in-order event key. */
protected $key; protected $key;
/** @var resource|\HashContext CRC32 hash context for event validation */ /** @var resource|\HashContext CRC32 hash context for event validation */
protected $hashContext; protected $hashContext;
/** @var int $currentPosition */ /** @var int $currentPosition */
protected $currentPosition; protected $currentPosition;
/** /**
* DecodingEventStreamIterator constructor. * DecodingEventStreamIterator constructor.
* *
* @param StreamInterface $stream * @param StreamInterface $stream
*/ */
public function __construct(StreamInterface $stream) public function __construct(StreamInterface $stream)
{ {
$this->stream = $stream; $this->stream = $stream;
$this->rewind(); $this->rewind();
} }
protected function parseHeaders($headerBytes) protected function parseHeaders($headerBytes)
{ {
$headers = []; $headers = [];
$bytesRead = 0; $bytesRead = 0;
while ($bytesRead < $headerBytes) { while ($bytesRead < $headerBytes) {
list($key, $numBytes) = $this->decodeString(1); list($key, $numBytes) = $this->decodeString(1);
$bytesRead += $numBytes; $bytesRead += $numBytes;
list($type, $numBytes) = $this->decodeUint8(); list($type, $numBytes) = $this->decodeUint8();
$bytesRead += $numBytes; $bytesRead += $numBytes;
$f = self::$headerTypeMap[$type]; $f = self::$headerTypeMap[$type];
list($value, $numBytes) = $this->{$f}(); list($value, $numBytes) = $this->{$f}();
$bytesRead += $numBytes; $bytesRead += $numBytes;
if (isset($headers[$key])) { if (isset($headers[$key])) {
throw new ParserException('Duplicate key in event headers.'); throw new ParserException('Duplicate key in event headers.');
} }
$headers[$key] = $value; $headers[$key] = $value;
} }
return [$headers, $bytesRead]; return [$headers, $bytesRead];
} }
protected function parsePrelude() protected function parsePrelude()
{ {
$prelude = []; $prelude = [];
$bytesRead = 0; $bytesRead = 0;
$calculatedCrc = null; $calculatedCrc = null;
foreach (self::$preludeFormat as $key => $decodeFunction) { foreach (self::$preludeFormat as $key => $decodeFunction) {
if ($key === self::CRC_PRELUDE) { if ($key === self::CRC_PRELUDE) {
$hashCopy = hash_copy($this->hashContext); $hashCopy = hash_copy($this->hashContext);
$calculatedCrc = hash_final($this->hashContext, true); $calculatedCrc = hash_final($this->hashContext, true);
$this->hashContext = $hashCopy; $this->hashContext = $hashCopy;
} }
list($value, $numBytes) = $this->{$decodeFunction}(); list($value, $numBytes) = $this->{$decodeFunction}();
$bytesRead += $numBytes; $bytesRead += $numBytes;
$prelude[$key] = $value; $prelude[$key] = $value;
} }
if (unpack('N', $calculatedCrc)[1] !== $prelude[self::CRC_PRELUDE]) { if (unpack('N', $calculatedCrc)[1] !== $prelude[self::CRC_PRELUDE]) {
throw new ParserException('Prelude checksum mismatch.'); throw new ParserException('Prelude checksum mismatch.');
} }
return [$prelude, $bytesRead]; return [$prelude, $bytesRead];
} }
/** /**
* This method decodes an event from the stream. * This method decodes an event from the stream.
* *
* @return array * @return array
*/ */
protected function parseEvent() protected function parseEvent()
{ {
$event = []; $event = [];
if ($this->stream->tell() < $this->stream->getSize()) { if ($this->stream->tell() < $this->stream->getSize()) {
$this->hashContext = hash_init('crc32b'); $this->hashContext = hash_init('crc32b');
$bytesLeft = $this->stream->getSize() - $this->stream->tell(); $bytesLeft = $this->stream->getSize() - $this->stream->tell();
list($prelude, $numBytes) = $this->parsePrelude(); list($prelude, $numBytes) = $this->parsePrelude();
if ($prelude[self::LENGTH_TOTAL] > $bytesLeft) { if ($prelude[self::LENGTH_TOTAL] > $bytesLeft) {
throw new ParserException('Message length too long.'); throw new ParserException('Message length too long.');
} }
$bytesLeft -= $numBytes; $bytesLeft -= $numBytes;
if ($prelude[self::LENGTH_HEADERS] > $bytesLeft) { if ($prelude[self::LENGTH_HEADERS] > $bytesLeft) {
throw new ParserException('Headers length too long.'); throw new ParserException('Headers length too long.');
} }
list( list(
$event[self::HEADERS], $event[self::HEADERS],
$numBytes $numBytes
) = $this->parseHeaders($prelude[self::LENGTH_HEADERS]); ) = $this->parseHeaders($prelude[self::LENGTH_HEADERS]);
$event[self::PAYLOAD] = Psr7\Utils::streamFor( $event[self::PAYLOAD] = Psr7\Utils::streamFor(
$this->readAndHashBytes( $this->readAndHashBytes(
$prelude[self::LENGTH_TOTAL] - self::BYTES_PRELUDE $prelude[self::LENGTH_TOTAL] - self::BYTES_PRELUDE
- $numBytes - self::BYTES_TRAILING - $numBytes - self::BYTES_TRAILING
) )
); );
$calculatedCrc = hash_final($this->hashContext, true); $calculatedCrc = hash_final($this->hashContext, true);
$messageCrc = $this->stream->read(4); $messageCrc = $this->stream->read(4);
if ($calculatedCrc !== $messageCrc) { if ($calculatedCrc !== $messageCrc) {
throw new ParserException('Message checksum mismatch.'); throw new ParserException('Message checksum mismatch.');
} }
} }
return $event; return $event;
} }
// Iterator Functionality // Iterator Functionality
/** /**
* @return array * @return array
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function current() public function current()
{ {
return $this->currentEvent; return $this->currentEvent;
} }
/** /**
* @return int * @return int
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function key() public function key()
{ {
return $this->key; return $this->key;
} }
/** /**
* @return void * @return void
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function next() public function next()
{ {
$this->currentPosition = $this->stream->tell(); $this->currentPosition = $this->stream->tell();
if ($this->valid()) { if ($this->valid()) {
$this->key++; $this->key++;
$this->currentEvent = $this->parseEvent(); $this->currentEvent = $this->parseEvent();
} }
} }
/** /**
* @return void * @return void
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function rewind() public function rewind()
{ {
$this->stream->rewind(); $this->stream->rewind();
$this->key = 0; $this->key = 0;
$this->currentPosition = 0; $this->currentPosition = 0;
$this->currentEvent = $this->parseEvent(); $this->currentEvent = $this->parseEvent();
} }
/** /**
* @return bool * @return bool
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function valid() public function valid()
{ {
return $this->currentPosition < $this->stream->getSize(); return $this->currentPosition < $this->stream->getSize();
} }
// Decoding Utilities // Decoding Utilities
protected function readAndHashBytes($num) protected function readAndHashBytes($num)
{ {
$bytes = $this->stream->read($num); $bytes = $this->stream->read($num);
hash_update($this->hashContext, $bytes); hash_update($this->hashContext, $bytes);
return $bytes; return $bytes;
} }
private function decodeBooleanTrue() private function decodeBooleanTrue()
{ {
return [true, 0]; return [true, 0];
} }
private function decodeBooleanFalse() private function decodeBooleanFalse()
{ {
return [false, 0]; return [false, 0];
} }
private function uintToInt($val, $size) private function uintToInt($val, $size)
{ {
$signedCap = pow(2, $size - 1); $signedCap = pow(2, $size - 1);
if ($val > $signedCap) { if ($val > $signedCap) {
$val -= (2 * $signedCap); $val -= (2 * $signedCap);
} }
return $val; return $val;
} }
private function decodeInt8() private function decodeInt8()
{ {
$val = (int)unpack('C', $this->readAndHashBytes(1))[1]; $val = (int)unpack('C', $this->readAndHashBytes(1))[1];
return [$this->uintToInt($val, 8), 1]; return [$this->uintToInt($val, 8), 1];
} }
private function decodeUint8() private function decodeUint8()
{ {
return [unpack('C', $this->readAndHashBytes(1))[1], 1]; return [unpack('C', $this->readAndHashBytes(1))[1], 1];
} }
private function decodeInt16() private function decodeInt16()
{ {
$val = (int)unpack('n', $this->readAndHashBytes(2))[1]; $val = (int)unpack('n', $this->readAndHashBytes(2))[1];
return [$this->uintToInt($val, 16), 2]; return [$this->uintToInt($val, 16), 2];
} }
private function decodeUint16() private function decodeUint16()
{ {
return [unpack('n', $this->readAndHashBytes(2))[1], 2]; return [unpack('n', $this->readAndHashBytes(2))[1], 2];
} }
private function decodeInt32() private function decodeInt32()
{ {
$val = (int)unpack('N', $this->readAndHashBytes(4))[1]; $val = (int)unpack('N', $this->readAndHashBytes(4))[1];
return [$this->uintToInt($val, 32), 4]; return [$this->uintToInt($val, 32), 4];
} }
private function decodeUint32() private function decodeUint32()
{ {
return [unpack('N', $this->readAndHashBytes(4))[1], 4]; return [unpack('N', $this->readAndHashBytes(4))[1], 4];
} }
private function decodeInt64() private function decodeInt64()
{ {
$val = $this->unpackInt64($this->readAndHashBytes(8))[1]; $val = $this->unpackInt64($this->readAndHashBytes(8))[1];
return [$this->uintToInt($val, 64), 8]; return [$this->uintToInt($val, 64), 8];
} }
private function decodeUint64() private function decodeUint64()
{ {
return [$this->unpackInt64($this->readAndHashBytes(8))[1], 8]; return [$this->unpackInt64($this->readAndHashBytes(8))[1], 8];
} }
private function unpackInt64($bytes) private function unpackInt64($bytes)
{ {
return unpack('J', $bytes); return unpack('J', $bytes);
} }
private function decodeBytes($lengthBytes=2) private function decodeBytes($lengthBytes=2)
{ {
if (!isset(self::$lengthFormatMap[$lengthBytes])) { if (!isset(self::$lengthFormatMap[$lengthBytes])) {
throw new ParserException('Undefined variable length format.'); throw new ParserException('Undefined variable length format.');
} }
$f = self::$lengthFormatMap[$lengthBytes]; $f = self::$lengthFormatMap[$lengthBytes];
list($len, $bytes) = $this->{$f}(); list($len, $bytes) = $this->{$f}();
return [$this->readAndHashBytes($len), $len + $bytes]; return [$this->readAndHashBytes($len), $len + $bytes];
} }
private function decodeString($lengthBytes=2) private function decodeString($lengthBytes=2)
{ {
if (!isset(self::$lengthFormatMap[$lengthBytes])) { if (!isset(self::$lengthFormatMap[$lengthBytes])) {
throw new ParserException('Undefined variable length format.'); throw new ParserException('Undefined variable length format.');
} }
$f = self::$lengthFormatMap[$lengthBytes]; $f = self::$lengthFormatMap[$lengthBytes];
list($len, $bytes) = $this->{$f}(); list($len, $bytes) = $this->{$f}();
return [$this->readAndHashBytes($len), $len + $bytes]; return [$this->readAndHashBytes($len), $len + $bytes];
} }
private function decodeTimestamp() private function decodeTimestamp()
{ {
list($val, $bytes) = $this->decodeInt64(); list($val, $bytes) = $this->decodeInt64();
return [ return [
DateTimeResult::createFromFormat('U.u', $val / 1000), DateTimeResult::createFromFormat('U.u', $val / 1000),
$bytes $bytes
]; ];
} }
private function decodeUuid() private function decodeUuid()
{ {
$val = unpack('H32', $this->readAndHashBytes(16))[1]; $val = unpack('H32', $this->readAndHashBytes(16))[1];
return [ return [
substr($val, 0, 8) . '-' substr($val, 0, 8) . '-'
. substr($val, 8, 4) . '-' . substr($val, 8, 4) . '-'
. substr($val, 12, 4) . '-' . substr($val, 12, 4) . '-'
. substr($val, 16, 4) . '-' . substr($val, 16, 4) . '-'
. substr($val, 20, 12), . substr($val, 20, 12),
16 16
]; ];
} }
} }

View file

@ -1,211 +1,211 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use \Iterator; use \Iterator;
use Aws\Exception\EventStreamDataException; use Aws\Exception\EventStreamDataException;
use Aws\Api\Parser\Exception\ParserException; use Aws\Api\Parser\Exception\ParserException;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
/** /**
* @internal Implements a decoder for a binary encoded event stream that will * @internal Implements a decoder for a binary encoded event stream that will
* decode, validate, and provide individual events from the stream. * decode, validate, and provide individual events from the stream.
*/ */
class EventParsingIterator implements Iterator class EventParsingIterator implements Iterator
{ {
/** @var StreamInterface */ /** @var StreamInterface */
private $decodingIterator; private $decodingIterator;
/** @var StructureShape */ /** @var StructureShape */
private $shape; private $shape;
/** @var AbstractParser */ /** @var AbstractParser */
private $parser; private $parser;
public function __construct( public function __construct(
StreamInterface $stream, StreamInterface $stream,
StructureShape $shape, StructureShape $shape,
AbstractParser $parser AbstractParser $parser
) { ) {
$this->decodingIterator = $this->chooseDecodingIterator($stream); $this->decodingIterator = $this->chooseDecodingIterator($stream);
$this->shape = $shape; $this->shape = $shape;
$this->parser = $parser; $this->parser = $parser;
} }
/** /**
* This method choose a decoding iterator implementation based on if the stream * This method choose a decoding iterator implementation based on if the stream
* is seekable or not. * is seekable or not.
* *
* @param $stream * @param $stream
* *
* @return Iterator * @return Iterator
*/ */
private function chooseDecodingIterator($stream) private function chooseDecodingIterator($stream)
{ {
if ($stream->isSeekable()) { if ($stream->isSeekable()) {
return new DecodingEventStreamIterator($stream); return new DecodingEventStreamIterator($stream);
} else { } else {
return new NonSeekableStreamDecodingEventStreamIterator($stream); return new NonSeekableStreamDecodingEventStreamIterator($stream);
} }
} }
/** /**
* @return mixed * @return mixed
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function current() public function current()
{ {
return $this->parseEvent($this->decodingIterator->current()); return $this->parseEvent($this->decodingIterator->current());
} }
/** /**
* @return mixed * @return mixed
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function key() public function key()
{ {
return $this->decodingIterator->key(); return $this->decodingIterator->key();
} }
/** /**
* @return void * @return void
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function next() public function next()
{ {
$this->decodingIterator->next(); $this->decodingIterator->next();
} }
/** /**
* @return void * @return void
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function rewind() public function rewind()
{ {
$this->decodingIterator->rewind(); $this->decodingIterator->rewind();
} }
/** /**
* @return bool * @return bool
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function valid() public function valid()
{ {
return $this->decodingIterator->valid(); return $this->decodingIterator->valid();
} }
private function parseEvent(array $event) private function parseEvent(array $event)
{ {
if (!empty($event['headers'][':message-type'])) { if (!empty($event['headers'][':message-type'])) {
if ($event['headers'][':message-type'] === 'error') { if ($event['headers'][':message-type'] === 'error') {
return $this->parseError($event); return $this->parseError($event);
} }
if ($event['headers'][':message-type'] === 'exception') { if ($event['headers'][':message-type'] === 'exception') {
return $this->parseException($event); return $this->parseException($event);
} }
if ($event['headers'][':message-type'] !== 'event') { if ($event['headers'][':message-type'] !== 'event') {
throw new ParserException('Failed to parse unknown message type.'); throw new ParserException('Failed to parse unknown message type.');
} }
} }
$eventType = $event['headers'][':event-type'] ?? null; $eventType = $event['headers'][':event-type'] ?? null;
if (empty($eventType)) { if (empty($eventType)) {
throw new ParserException('Failed to parse without event type.'); throw new ParserException('Failed to parse without event type.');
} }
$eventPayload = $event['payload']; $eventPayload = $event['payload'];
if ($eventType === 'initial-response') { if ($eventType === 'initial-response') {
return $this->parseInitialResponseEvent($eventPayload); return $this->parseInitialResponseEvent($eventPayload);
} }
$eventShape = $this->shape->getMember($eventType); $eventShape = $this->shape->getMember($eventType);
return [ return [
$eventType => array_merge( $eventType => array_merge(
$this->parseEventHeaders($event['headers'], $eventShape), $this->parseEventHeaders($event['headers'], $eventShape),
$this->parseEventPayload($eventPayload, $eventShape) $this->parseEventPayload($eventPayload, $eventShape)
) )
]; ];
} }
/** /**
* @param $headers * @param $headers
* @param $eventShape * @param $eventShape
* *
* @return array * @return array
*/ */
private function parseEventHeaders($headers, $eventShape): array private function parseEventHeaders($headers, $eventShape): array
{ {
$parsedHeaders = []; $parsedHeaders = [];
foreach ($eventShape->getMembers() as $memberName => $memberProps) { foreach ($eventShape->getMembers() as $memberName => $memberProps) {
if (isset($memberProps['eventheader'])) { if (isset($memberProps['eventheader'])) {
$parsedHeaders[$memberName] = $headers[$memberName]; $parsedHeaders[$memberName] = $headers[$memberName];
} }
} }
return $parsedHeaders; return $parsedHeaders;
} }
/** /**
* @param $payload * @param $payload
* @param $eventShape * @param $eventShape
* *
* @return array * @return array
*/ */
private function parseEventPayload($payload, $eventShape): array private function parseEventPayload($payload, $eventShape): array
{ {
$parsedPayload = []; $parsedPayload = [];
foreach ($eventShape->getMembers() as $memberName => $memberProps) { foreach ($eventShape->getMembers() as $memberName => $memberProps) {
$memberShape = $eventShape->getMember($memberName); $memberShape = $eventShape->getMember($memberName);
if (isset($memberProps['eventpayload'])) { if (isset($memberProps['eventpayload'])) {
if ($memberShape->getType() === 'blob') { if ($memberShape->getType() === 'blob') {
$parsedPayload[$memberName] = $payload; $parsedPayload[$memberName] = $payload;
} else { } else {
$parsedPayload[$memberName] = $this->parser->parseMemberFromStream( $parsedPayload[$memberName] = $this->parser->parseMemberFromStream(
$payload, $payload,
$memberShape, $memberShape,
null null
); );
} }
break; break;
} }
} }
if (empty($parsedPayload) && !empty($payload->getContents())) { if (empty($parsedPayload) && !empty($payload->getContents())) {
/** /**
* If we did not find a member with an eventpayload trait, then we should deserialize the payload * If we did not find a member with an eventpayload trait, then we should deserialize the payload
* using the event's shape. * using the event's shape.
*/ */
$parsedPayload = $this->parser->parseMemberFromStream($payload, $eventShape, null); $parsedPayload = $this->parser->parseMemberFromStream($payload, $eventShape, null);
} }
return $parsedPayload; return $parsedPayload;
} }
private function parseError(array $event) private function parseError(array $event)
{ {
throw new EventStreamDataException( throw new EventStreamDataException(
$event['headers'][':error-code'], $event['headers'][':error-code'],
$event['headers'][':error-message'] $event['headers'][':error-message']
); );
} }
private function parseException(array $event) { private function parseException(array $event) {
$payload = $event['payload']?->getContents(); $payload = $event['payload']?->getContents();
$parsedPayload = json_decode($payload, true); $parsedPayload = json_decode($payload, true);
throw new EventStreamDataException( throw new EventStreamDataException(
$event['headers'][':exception-type'] ?? 'Unknown', $event['headers'][':exception-type'] ?? 'Unknown',
$parsedPayload['message'] ?? $payload, $parsedPayload['message'] ?? $payload,
); );
} }
private function parseInitialResponseEvent($payload): array private function parseInitialResponseEvent($payload): array
{ {
return ['initial-response' => json_decode($payload, true)]; return ['initial-response' => json_decode($payload, true)];
} }
} }

View file

@ -1,56 +1,56 @@
<?php <?php
namespace Aws\Api\Parser\Exception; namespace Aws\Api\Parser\Exception;
use Aws\HasMonitoringEventsTrait; use Aws\HasMonitoringEventsTrait;
use Aws\MonitoringEventsInterface; use Aws\MonitoringEventsInterface;
use Aws\ResponseContainerInterface; use Aws\ResponseContainerInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
class ParserException extends \RuntimeException implements class ParserException extends \RuntimeException implements
MonitoringEventsInterface, MonitoringEventsInterface,
ResponseContainerInterface ResponseContainerInterface
{ {
use HasMonitoringEventsTrait; use HasMonitoringEventsTrait;
private $errorCode; private $errorCode;
private $requestId; private $requestId;
private $response; private $response;
public function __construct($message = '', $code = 0, $previous = null, array $context = []) public function __construct($message = '', $code = 0, $previous = null, array $context = [])
{ {
$this->errorCode = isset($context['error_code']) ? $context['error_code'] : null; $this->errorCode = isset($context['error_code']) ? $context['error_code'] : null;
$this->requestId = isset($context['request_id']) ? $context['request_id'] : null; $this->requestId = isset($context['request_id']) ? $context['request_id'] : null;
$this->response = isset($context['response']) ? $context['response'] : null; $this->response = isset($context['response']) ? $context['response'] : null;
parent::__construct($message, $code, $previous); parent::__construct($message, $code, $previous);
} }
/** /**
* Get the error code, if any. * Get the error code, if any.
* *
* @return string|null * @return string|null
*/ */
public function getErrorCode() public function getErrorCode()
{ {
return $this->errorCode; return $this->errorCode;
} }
/** /**
* Get the request ID, if any. * Get the request ID, if any.
* *
* @return string|null * @return string|null
*/ */
public function getRequestId() public function getRequestId()
{ {
return $this->requestId; return $this->requestId;
} }
/** /**
* Get the received HTTP response if any. * Get the received HTTP response if any.
* *
* @return ResponseInterface|null * @return ResponseInterface|null
*/ */
public function getResponse() public function getResponse()
{ {
return $this->response; return $this->response;
} }
} }

View file

@ -1,74 +1,74 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\DateTimeResult; use Aws\Api\DateTimeResult;
use Aws\Api\Shape; use Aws\Api\Shape;
/** /**
* @internal Implements standard JSON parsing. * @internal Implements standard JSON parsing.
*/ */
class JsonParser class JsonParser
{ {
public function parse(Shape $shape, $value) public function parse(Shape $shape, $value)
{ {
if ($value === null) { if ($value === null) {
return $value; return $value;
} }
switch ($shape['type']) { switch ($shape['type']) {
case 'structure': case 'structure':
if (isset($shape['document']) && $shape['document']) { if (isset($shape['document']) && $shape['document']) {
return $value; return $value;
} }
$target = []; $target = [];
foreach ($shape->getMembers() as $name => $member) { foreach ($shape->getMembers() as $name => $member) {
$locationName = $member['locationName'] ?: $name; $locationName = $member['locationName'] ?: $name;
if (isset($value[$locationName])) { if (isset($value[$locationName])) {
$target[$name] = $this->parse($member, $value[$locationName]); $target[$name] = $this->parse($member, $value[$locationName]);
} }
} }
if (isset($shape['union']) if (isset($shape['union'])
&& $shape['union'] && $shape['union']
&& is_array($value) && is_array($value)
&& empty($target) && empty($target)
) { ) {
foreach ($value as $key => $val) { foreach ($value as $key => $val) {
$target['Unknown'][$key] = $val; $target['Unknown'][$key] = $val;
} }
} }
return $target; return $target;
case 'list': case 'list':
$member = $shape->getMember(); $member = $shape->getMember();
$target = []; $target = [];
foreach ($value as $v) { foreach ($value as $v) {
$target[] = $this->parse($member, $v); $target[] = $this->parse($member, $v);
} }
return $target; return $target;
case 'map': case 'map':
$values = $shape->getValue(); $values = $shape->getValue();
$target = []; $target = [];
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
// null map values should not be deserialized // null map values should not be deserialized
if (!is_null($v)) { if (!is_null($v)) {
$target[$k] = $this->parse($values, $v); $target[$k] = $this->parse($values, $v);
} }
} }
return $target; return $target;
case 'timestamp': case 'timestamp':
return DateTimeResult::fromTimestamp( return DateTimeResult::fromTimestamp(
$value, $value,
!empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null !empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null
); );
case 'blob': case 'blob':
return base64_decode($value); return base64_decode($value);
default: default:
return $value; return $value;
} }
} }
} }

View file

@ -1,82 +1,82 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\Operation; use Aws\Api\Operation;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\Result; use Aws\Result;
use Aws\CommandInterface; use Aws\CommandInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
/** /**
* @internal Implements JSON-RPC parsing (e.g., DynamoDB) * @internal Implements JSON-RPC parsing (e.g., DynamoDB)
*/ */
class JsonRpcParser extends AbstractParser class JsonRpcParser extends AbstractParser
{ {
use PayloadParserTrait; use PayloadParserTrait;
/** /**
* @param Service $api Service description * @param Service $api Service description
* @param JsonParser $parser JSON body builder * @param JsonParser $parser JSON body builder
*/ */
public function __construct(Service $api, ?JsonParser $parser = null) public function __construct(Service $api, ?JsonParser $parser = null)
{ {
parent::__construct($api); parent::__construct($api);
$this->parser = $parser ?: new JsonParser(); $this->parser = $parser ?: new JsonParser();
} }
public function __invoke( public function __invoke(
CommandInterface $command, CommandInterface $command,
ResponseInterface $response ResponseInterface $response
) { ) {
$operation = $this->api->getOperation($command->getName()); $operation = $this->api->getOperation($command->getName());
return $this->parseResponse($response, $operation); return $this->parseResponse($response, $operation);
} }
/** /**
* This method parses a response based on JSON RPC protocol. * This method parses a response based on JSON RPC protocol.
* *
* @param ResponseInterface $response the response to parse. * @param ResponseInterface $response the response to parse.
* @param Operation $operation the operation which holds information for * @param Operation $operation the operation which holds information for
* parsing the response. * parsing the response.
* *
* @return Result * @return Result
*/ */
private function parseResponse(ResponseInterface $response, Operation $operation) private function parseResponse(ResponseInterface $response, Operation $operation)
{ {
if (null === $operation['output']) { if (null === $operation['output']) {
return new Result([]); return new Result([]);
} }
$outputShape = $operation->getOutput(); $outputShape = $operation->getOutput();
foreach ($outputShape->getMembers() as $memberName => $memberProps) { foreach ($outputShape->getMembers() as $memberName => $memberProps) {
if (!empty($memberProps['eventstream'])) { if (!empty($memberProps['eventstream'])) {
return new Result([ return new Result([
$memberName => new EventParsingIterator( $memberName => new EventParsingIterator(
$response->getBody(), $response->getBody(),
$outputShape->getMember($memberName), $outputShape->getMember($memberName),
$this $this
) )
]); ]);
} }
} }
$result = $this->parseMemberFromStream( $result = $this->parseMemberFromStream(
$response->getBody(), $response->getBody(),
$operation->getOutput(), $operation->getOutput(),
$response $response
); );
return new Result(is_null($result) ? [] : $result); return new Result(is_null($result) ? [] : $result);
} }
public function parseMemberFromStream( public function parseMemberFromStream(
StreamInterface $stream, StreamInterface $stream,
StructureShape $member, StructureShape $member,
$response $response
) { ) {
return $this->parser->parse($member, $this->parseJson($stream, $response)); return $this->parser->parse($member, $this->parseJson($stream, $response));
} }
} }

View file

@ -1,95 +1,95 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\DateTimeResult; use Aws\Api\DateTimeResult;
use Aws\Api\Shape; use Aws\Api\Shape;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
trait MetadataParserTrait trait MetadataParserTrait
{ {
/** /**
* Extract a single header from the response into the result. * Extract a single header from the response into the result.
*/ */
protected function extractHeader( protected function extractHeader(
$name, $name,
Shape $shape, Shape $shape,
ResponseInterface $response, ResponseInterface $response,
&$result &$result
) { ) {
$value = $response->getHeaderLine($shape['locationName'] ?: $name); $value = $response->getHeaderLine($shape['locationName'] ?: $name);
// Empty values should not be deserialized // Empty values should not be deserialized
if ($value === null || $value === '') { if ($value === null || $value === '') {
return; return;
} }
switch ($shape->getType()) { switch ($shape->getType()) {
case 'float': case 'float':
case 'double': case 'double':
$value = (float) $value; $value = (float) $value;
break; break;
case 'long': case 'long':
case 'integer': case 'integer':
$value = (int) $value; $value = (int) $value;
break; break;
case 'boolean': case 'boolean':
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN); $value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
break; break;
case 'blob': case 'blob':
$value = base64_decode($value); $value = base64_decode($value);
break; break;
case 'timestamp': case 'timestamp':
try { try {
$value = DateTimeResult::fromTimestamp( $value = DateTimeResult::fromTimestamp(
$value, $value,
!empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null !empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null
); );
break; break;
} catch (\Exception $e) { } catch (\Exception $e) {
// If the value cannot be parsed, then do not add it to the // If the value cannot be parsed, then do not add it to the
// output structure. // output structure.
return; return;
} }
case 'string': case 'string':
if ($shape['jsonvalue']) { if ($shape['jsonvalue']) {
$value = $this->parseJson(base64_decode($value), $response); $value = $this->parseJson(base64_decode($value), $response);
} }
break; break;
} }
$result[$name] = $value; $result[$name] = $value;
} }
/** /**
* Extract a map of headers with an optional prefix from the response. * Extract a map of headers with an optional prefix from the response.
*/ */
protected function extractHeaders( protected function extractHeaders(
$name, $name,
Shape $shape, Shape $shape,
ResponseInterface $response, ResponseInterface $response,
&$result &$result
) { ) {
// Check if the headers are prefixed by a location name // Check if the headers are prefixed by a location name
$result[$name] = []; $result[$name] = [];
$prefix = $shape['locationName']; $prefix = $shape['locationName'];
$prefixLen = strlen($prefix); $prefixLen = strlen($prefix);
foreach ($response->getHeaders() as $k => $values) { foreach ($response->getHeaders() as $k => $values) {
if (!$prefixLen) { if (!$prefixLen) {
$result[$name][$k] = implode(', ', $values); $result[$name][$k] = implode(', ', $values);
} elseif (stripos($k, $prefix) === 0) { } elseif (stripos($k, $prefix) === 0) {
$result[$name][substr($k, $prefixLen)] = implode(', ', $values); $result[$name][substr($k, $prefixLen)] = implode(', ', $values);
} }
} }
} }
/** /**
* Places the status code of the response into the result array. * Places the status code of the response into the result array.
*/ */
protected function extractStatus( protected function extractStatus(
$name, $name,
ResponseInterface $response, ResponseInterface $response,
array &$result array &$result
) { ) {
$result[$name] = (int) $response->getStatusCode(); $result[$name] = (int) $response->getStatusCode();
} }
} }

View file

@ -1,101 +1,112 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
use Aws\Api\Parser\Exception\ParserException; use Aws\Api\Parser\Exception\ParserException;
/** /**
* @inheritDoc * @inheritDoc
*/ */
class NonSeekableStreamDecodingEventStreamIterator extends DecodingEventStreamIterator class NonSeekableStreamDecodingEventStreamIterator extends DecodingEventStreamIterator
{ {
/** @var array $tempBuffer */ /** @var array $tempBuffer */
private $tempBuffer; private $tempBuffer;
/** /**
* NonSeekableStreamDecodingEventStreamIterator constructor. * NonSeekableStreamDecodingEventStreamIterator constructor.
* *
* @param StreamInterface $stream * @param StreamInterface $stream
*/ */
public function __construct(StreamInterface $stream) public function __construct(StreamInterface $stream)
{ {
$this->stream = $stream; $this->stream = $stream;
if ($this->stream->isSeekable()) { if ($this->stream->isSeekable()) {
throw new \InvalidArgumentException('The stream provided must be not seekable.'); throw new \InvalidArgumentException('The stream provided must be not seekable.');
} }
$this->tempBuffer = []; $this->tempBuffer = [];
} }
/** /**
* @inheritDoc * @inheritDoc
* *
* @return array * @return array
*/ */
protected function parseEvent(): array protected function parseEvent(): array
{ {
$event = []; $event = [];
$this->hashContext = hash_init('crc32b'); $this->hashContext = hash_init('crc32b');
$prelude = $this->parsePrelude()[0]; $prelude = $this->parsePrelude()[0];
list( list(
$event[self::HEADERS], $event[self::HEADERS],
$numBytes $numBytes
) = $this->parseHeaders($prelude[self::LENGTH_HEADERS]); ) = $this->parseHeaders($prelude[self::LENGTH_HEADERS]);
$event[self::PAYLOAD] = Psr7\Utils::streamFor( $event[self::PAYLOAD] = Psr7\Utils::streamFor(
$this->readAndHashBytes( $this->readAndHashBytes(
$prelude[self::LENGTH_TOTAL] - self::BYTES_PRELUDE $prelude[self::LENGTH_TOTAL] - self::BYTES_PRELUDE
- $numBytes - self::BYTES_TRAILING - $numBytes - self::BYTES_TRAILING
) )
); );
$calculatedCrc = hash_final($this->hashContext, true); $calculatedCrc = hash_final($this->hashContext, true);
$messageCrc = $this->stream->read(4); $messageCrc = $this->stream->read(4);
if ($calculatedCrc !== $messageCrc) { if ($calculatedCrc !== $messageCrc) {
throw new ParserException('Message checksum mismatch.'); throw new ParserException('Message checksum mismatch.');
} }
return $event; return $event;
} }
protected function readAndHashBytes($num): string protected function readAndHashBytes($num): string
{ {
$bytes = ''; $bytes = '';
while (!empty($this->tempBuffer) && $num > 0) { while (!empty($this->tempBuffer) && $num > 0) {
$byte = array_shift($this->tempBuffer); $byte = array_shift($this->tempBuffer);
$bytes .= $byte; $bytes .= $byte;
$num = $num - 1; $num -= 1;
} }
$bytes = $bytes . $this->stream->read($num); // Loop until we've read the expected number of bytes
hash_update($this->hashContext, $bytes); while ($num > 0 && !$this->stream->eof()) {
$chunk = $this->stream->read($num);
return $bytes; $chunkLen = strlen($chunk);
} $bytes .= $chunk;
$num -= $chunkLen;
// Iterator Functionality
if ($chunkLen === 0) {
#[\ReturnTypeWillChange] break; // Prevent infinite loop on unexpected EOF
public function rewind() }
{ }
$this->currentEvent = $this->parseEvent();
} hash_update($this->hashContext, $bytes);
public function next() return $bytes;
{ }
$this->tempBuffer[] = $this->stream->read(1);
if ($this->valid()) { // Iterator Functionality
$this->key++;
$this->currentEvent = $this->parseEvent(); #[\ReturnTypeWillChange]
} public function rewind()
} {
$this->currentEvent = $this->parseEvent();
/** }
* @return bool
*/ public function next()
#[\ReturnTypeWillChange] {
public function valid() $this->tempBuffer[] = $this->stream->read(1);
{ if ($this->valid()) {
return !$this->stream->eof(); $this->key++;
} $this->currentEvent = $this->parseEvent();
} }
}
/**
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
{
return !$this->stream->eof();
}
}

View file

@ -1,61 +1,61 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\Parser\Exception\ParserException; use Aws\Api\Parser\Exception\ParserException;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
trait PayloadParserTrait trait PayloadParserTrait
{ {
/** /**
* @param string $json * @param string $json
* *
* @throws ParserException * @throws ParserException
* *
* @return array * @return array
*/ */
private function parseJson($json, $response) private function parseJson($json, $response)
{ {
$jsonPayload = json_decode($json, true); $jsonPayload = json_decode($json, true);
if (JSON_ERROR_NONE !== json_last_error()) { if (JSON_ERROR_NONE !== json_last_error()) {
throw new ParserException( throw new ParserException(
'Error parsing JSON: ' . json_last_error_msg(), 'Error parsing JSON: ' . json_last_error_msg(),
0, 0,
null, null,
['response' => $response] ['response' => $response]
); );
} }
return $jsonPayload; return $jsonPayload;
} }
/** /**
* @param string $xml * @param string $xml
* *
* @throws ParserException * @throws ParserException
* *
* @return \SimpleXMLElement * @return \SimpleXMLElement
*/ */
protected function parseXml($xml, $response) protected function parseXml($xml, $response)
{ {
$priorSetting = libxml_use_internal_errors(true); $priorSetting = libxml_use_internal_errors(true);
try { try {
libxml_clear_errors(); libxml_clear_errors();
$xmlPayload = new \SimpleXMLElement($xml); $xmlPayload = new \SimpleXMLElement($xml);
if ($error = libxml_get_last_error()) { if ($error = libxml_get_last_error()) {
throw new \RuntimeException($error->message); throw new \RuntimeException($error->message);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
throw new ParserException( throw new ParserException(
"Error parsing XML: {$e->getMessage()}", "Error parsing XML: {$e->getMessage()}",
0, 0,
$e, $e,
['response' => $response] ['response' => $response]
); );
} finally { } finally {
libxml_use_internal_errors($priorSetting); libxml_use_internal_errors($priorSetting);
} }
return $xmlPayload; return $xmlPayload;
} }
} }

View file

@ -1,68 +1,68 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\Result; use Aws\Result;
use Aws\CommandInterface; use Aws\CommandInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
/** /**
* @internal Parses query (XML) responses (e.g., EC2, SQS, and many others) * @internal Parses query (XML) responses (e.g., EC2, SQS, and many others)
*/ */
class QueryParser extends AbstractParser class QueryParser extends AbstractParser
{ {
use PayloadParserTrait; use PayloadParserTrait;
/** @var bool */ /** @var bool */
private $honorResultWrapper; private $honorResultWrapper;
/** /**
* @param Service $api Service description * @param Service $api Service description
* @param XmlParser $xmlParser Optional XML parser * @param XmlParser $xmlParser Optional XML parser
* @param bool $honorResultWrapper Set to false to disable the peeling * @param bool $honorResultWrapper Set to false to disable the peeling
* back of result wrappers from the * back of result wrappers from the
* output structure. * output structure.
*/ */
public function __construct( public function __construct(
Service $api, Service $api,
?XmlParser $xmlParser = null, ?XmlParser $xmlParser = null,
$honorResultWrapper = true $honorResultWrapper = true
) { ) {
parent::__construct($api); parent::__construct($api);
$this->parser = $xmlParser ?: new XmlParser(); $this->parser = $xmlParser ?: new XmlParser();
$this->honorResultWrapper = $honorResultWrapper; $this->honorResultWrapper = $honorResultWrapper;
} }
public function __invoke( public function __invoke(
CommandInterface $command, CommandInterface $command,
ResponseInterface $response ResponseInterface $response
) { ) {
$output = $this->api->getOperation($command->getName())->getOutput(); $output = $this->api->getOperation($command->getName())->getOutput();
$body = $response->getBody(); $body = $response->getBody();
$xml = !$body->isSeekable() || $body->getSize() $xml = !$body->isSeekable() || $body->getSize()
? $this->parseXml($body, $response) ? $this->parseXml($body, $response)
: null; : null;
// Empty request bodies should not be deserialized. // Empty request bodies should not be deserialized.
if (is_null($xml)) { if (is_null($xml)) {
return new Result(); return new Result();
} }
if ($this->honorResultWrapper && $output['resultWrapper']) { if ($this->honorResultWrapper && $output['resultWrapper']) {
$xml = $xml->{$output['resultWrapper']}; $xml = $xml->{$output['resultWrapper']};
} }
return new Result($this->parser->parse($output, $xml)); return new Result($this->parser->parse($output, $xml));
} }
public function parseMemberFromStream( public function parseMemberFromStream(
StreamInterface $stream, StreamInterface $stream,
StructureShape $member, StructureShape $member,
$response $response
) { ) {
$xml = $this->parseXml($stream, $response); $xml = $this->parseXml($stream, $response);
return $this->parser->parse($member, $xml); return $this->parser->parse($member, $xml);
} }
} }

View file

@ -1,64 +1,64 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\Service; use Aws\Api\Service;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
/** /**
* @internal Implements REST-JSON parsing (e.g., Glacier, Elastic Transcoder) * @internal Implements REST-JSON parsing (e.g., Glacier, Elastic Transcoder)
*/ */
class RestJsonParser extends AbstractRestParser class RestJsonParser extends AbstractRestParser
{ {
use PayloadParserTrait; use PayloadParserTrait;
/** /**
* @param Service $api Service description * @param Service $api Service description
* @param JsonParser $parser JSON body builder * @param JsonParser $parser JSON body builder
*/ */
public function __construct(Service $api, ?JsonParser $parser = null) public function __construct(Service $api, ?JsonParser $parser = null)
{ {
parent::__construct($api); parent::__construct($api);
$this->parser = $parser ?: new JsonParser(); $this->parser = $parser ?: new JsonParser();
} }
protected function payload( protected function payload(
ResponseInterface $response, ResponseInterface $response,
StructureShape $member, StructureShape $member,
array &$result array &$result
) { ) {
$responseBody = (string) $response->getBody(); $responseBody = (string) $response->getBody();
// Parse JSON if we have content // Parse JSON if we have content
$parsedJson = null; $parsedJson = null;
if (!empty($responseBody)) { if (!empty($responseBody)) {
$parsedJson = $this->parseJson($responseBody, $response); $parsedJson = $this->parseJson($responseBody, $response);
} else { } else {
// An empty response body should be deserialized as null // An empty response body should be deserialized as null
$result = $parsedJson; $result = $parsedJson;
return; return;
} }
$parsedBody = $this->parser->parse($member, $parsedJson); $parsedBody = $this->parser->parse($member, $parsedJson);
if (is_string($parsedBody) && $member['document']) { if (is_string($parsedBody) && $member['document']) {
// Document types can be strings: replace entire result // Document types can be strings: replace entire result
$result = $parsedBody; $result = $parsedBody;
} else { } else {
// Merge array/object results into existing result // Merge array/object results into existing result
$result = array_merge($result, (array) $parsedBody); $result = array_merge($result, (array) $parsedBody);
} }
} }
public function parseMemberFromStream( public function parseMemberFromStream(
StreamInterface $stream, StreamInterface $stream,
StructureShape $member, StructureShape $member,
$response $response
) { ) {
$jsonBody = $this->parseJson($stream, $response); $jsonBody = $this->parseJson($stream, $response);
if ($jsonBody) { if ($jsonBody) {
return $this->parser->parse($member, $jsonBody); return $this->parser->parse($member, $jsonBody);
} }
return []; return [];
} }
} }

View file

@ -1,42 +1,42 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
use Aws\Api\Service; use Aws\Api\Service;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
/** /**
* @internal Implements REST-XML parsing (e.g., S3, CloudFront, etc...) * @internal Implements REST-XML parsing (e.g., S3, CloudFront, etc...)
*/ */
class RestXmlParser extends AbstractRestParser class RestXmlParser extends AbstractRestParser
{ {
use PayloadParserTrait; use PayloadParserTrait;
/** /**
* @param Service $api Service description * @param Service $api Service description
* @param XmlParser $parser XML body parser * @param XmlParser $parser XML body parser
*/ */
public function __construct(Service $api, ?XmlParser $parser = null) public function __construct(Service $api, ?XmlParser $parser = null)
{ {
parent::__construct($api); parent::__construct($api);
$this->parser = $parser ?: new XmlParser(); $this->parser = $parser ?: new XmlParser();
} }
protected function payload( protected function payload(
ResponseInterface $response, ResponseInterface $response,
StructureShape $member, StructureShape $member,
array &$result array &$result
) { ) {
$result += $this->parseMemberFromStream($response->getBody(), $member, $response); $result += $this->parseMemberFromStream($response->getBody(), $member, $response);
} }
public function parseMemberFromStream( public function parseMemberFromStream(
StreamInterface $stream, StreamInterface $stream,
StructureShape $member, StructureShape $member,
$response $response
) { ) {
$xml = $this->parseXml($stream, $response); $xml = $this->parseXml($stream, $response);
return $this->parser->parse($member, $xml); return $this->parser->parse($member, $xml);
} }
} }

View file

@ -1,183 +1,183 @@
<?php <?php
namespace Aws\Api\Parser; namespace Aws\Api\Parser;
use Aws\Api\DateTimeResult; use Aws\Api\DateTimeResult;
use Aws\Api\ListShape; use Aws\Api\ListShape;
use Aws\Api\MapShape; use Aws\Api\MapShape;
use Aws\Api\Parser\Exception\ParserException; use Aws\Api\Parser\Exception\ParserException;
use Aws\Api\Shape; use Aws\Api\Shape;
use Aws\Api\StructureShape; use Aws\Api\StructureShape;
/** /**
* @internal Implements standard XML parsing for REST-XML and Query protocols. * @internal Implements standard XML parsing for REST-XML and Query protocols.
*/ */
class XmlParser class XmlParser
{ {
public function parse(StructureShape $shape, \SimpleXMLElement $value) public function parse(StructureShape $shape, \SimpleXMLElement $value)
{ {
return $this->dispatch($shape, $value); return $this->dispatch($shape, $value);
} }
private function dispatch($shape, \SimpleXMLElement $value) private function dispatch($shape, \SimpleXMLElement $value)
{ {
static $methods = [ static $methods = [
'structure' => 'parse_structure', 'structure' => 'parse_structure',
'list' => 'parse_list', 'list' => 'parse_list',
'map' => 'parse_map', 'map' => 'parse_map',
'blob' => 'parse_blob', 'blob' => 'parse_blob',
'boolean' => 'parse_boolean', 'boolean' => 'parse_boolean',
'integer' => 'parse_integer', 'integer' => 'parse_integer',
'float' => 'parse_float', 'float' => 'parse_float',
'double' => 'parse_float', 'double' => 'parse_float',
'timestamp' => 'parse_timestamp', 'timestamp' => 'parse_timestamp',
]; ];
$type = $shape['type']; $type = $shape['type'];
if (isset($methods[$type])) { if (isset($methods[$type])) {
return $this->{$methods[$type]}($shape, $value); return $this->{$methods[$type]}($shape, $value);
} }
return (string) $value; return (string) $value;
} }
private function parse_structure( private function parse_structure(
StructureShape $shape, StructureShape $shape,
\SimpleXMLElement $value \SimpleXMLElement $value
) { ) {
$target = []; $target = [];
foreach ($shape->getMembers() as $name => $member) { foreach ($shape->getMembers() as $name => $member) {
// Extract the name of the XML node // Extract the name of the XML node
$node = $this->memberKey($member, $name); $node = $this->memberKey($member, $name);
if (isset($value->{$node})) { if (isset($value->{$node})) {
$target[$name] = $this->dispatch($member, $value->{$node}); $target[$name] = $this->dispatch($member, $value->{$node});
} else { } else {
$memberShape = $shape->getMember($name); $memberShape = $shape->getMember($name);
if (!empty($memberShape['xmlAttribute'])) { if (!empty($memberShape['xmlAttribute'])) {
$target[$name] = $this->parse_xml_attribute( $target[$name] = $this->parse_xml_attribute(
$shape, $shape,
$memberShape, $memberShape,
$value $value
); );
} }
} }
} }
if (isset($shape['union']) if (isset($shape['union'])
&& $shape['union'] && $shape['union']
&& empty($target) && empty($target)
) { ) {
foreach ($value as $key => $val) { foreach ($value as $key => $val) {
$name = $val->children()->getName(); $name = $val->children()->getName();
$target['Unknown'][$name] = $val->$name; $target['Unknown'][$name] = $val->$name;
} }
} }
return $target; return $target;
} }
private function memberKey(Shape $shape, $name) private function memberKey(Shape $shape, $name)
{ {
// Check if locationName came from shape definition // Check if locationName came from shape definition
if ($shape instanceof StructureShape && isset($shape['locationName'])) { if ($shape instanceof StructureShape && isset($shape['locationName'])) {
$originalDef = $shape->getOriginalDefinition($shape->getName()); $originalDef = $shape->getOriginalDefinition($shape->getName());
if ($originalDef && isset($originalDef['locationName']) if ($originalDef && isset($originalDef['locationName'])
&& $originalDef['locationName'] === $shape['locationName'] && $originalDef['locationName'] === $shape['locationName']
) { ) {
return $name; return $name;
} }
} }
return $shape['locationName'] ?? $name; return $shape['locationName'] ?? $name;
} }
private function parse_list(ListShape $shape, \SimpleXMLElement $value) private function parse_list(ListShape $shape, \SimpleXMLElement $value)
{ {
$target = []; $target = [];
$member = $shape->getMember(); $member = $shape->getMember();
if (!$shape['flattened']) { if (!$shape['flattened']) {
$value = $value->{$member['locationName'] ?: 'member'}; $value = $value->{$member['locationName'] ?: 'member'};
} }
foreach ($value as $v) { foreach ($value as $v) {
$target[] = $this->dispatch($member, $v); $target[] = $this->dispatch($member, $v);
} }
return $target; return $target;
} }
private function parse_map(MapShape $shape, \SimpleXMLElement $value) private function parse_map(MapShape $shape, \SimpleXMLElement $value)
{ {
$target = []; $target = [];
if (!$shape['flattened']) { if (!$shape['flattened']) {
$value = $value->entry; $value = $value->entry;
} }
$mapKey = $shape->getKey(); $mapKey = $shape->getKey();
$mapValue = $shape->getValue(); $mapValue = $shape->getValue();
$keyName = $shape->getKey()['locationName'] ?: 'key'; $keyName = $shape->getKey()['locationName'] ?: 'key';
$valueName = $shape->getValue()['locationName'] ?: 'value'; $valueName = $shape->getValue()['locationName'] ?: 'value';
foreach ($value as $node) { foreach ($value as $node) {
$key = $this->dispatch($mapKey, $node->{$keyName}); $key = $this->dispatch($mapKey, $node->{$keyName});
$value = $this->dispatch($mapValue, $node->{$valueName}); $value = $this->dispatch($mapValue, $node->{$valueName});
$target[$key] = $value; $target[$key] = $value;
} }
return $target; return $target;
} }
private function parse_blob(Shape $shape, $value) private function parse_blob(Shape $shape, $value)
{ {
return base64_decode((string) $value); return base64_decode((string) $value);
} }
private function parse_float(Shape $shape, $value) private function parse_float(Shape $shape, $value)
{ {
$value = (string) $value; $value = (string) $value;
return match ($value) { return match ($value) {
'NaN', 'Infinity', '-Infinity' => $value, 'NaN', 'Infinity', '-Infinity' => $value,
default => (float) $value default => (float) $value
}; };
} }
private function parse_integer(Shape $shape, $value) private function parse_integer(Shape $shape, $value)
{ {
return (int) (string) $value; return (int) (string) $value;
} }
private function parse_boolean(Shape $shape, $value) private function parse_boolean(Shape $shape, $value)
{ {
return $value == 'true'; return $value == 'true';
} }
private function parse_timestamp(Shape $shape, $value) private function parse_timestamp(Shape $shape, $value)
{ {
if (is_string($value) if (is_string($value)
|| is_int($value) || is_int($value)
|| (is_object($value) || (is_object($value)
&& method_exists($value, '__toString')) && method_exists($value, '__toString'))
) { ) {
return DateTimeResult::fromTimestamp( return DateTimeResult::fromTimestamp(
(string) $value, (string) $value,
!empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null !empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null
); );
} }
throw new ParserException('Invalid timestamp value passed to XmlParser::parse_timestamp'); throw new ParserException('Invalid timestamp value passed to XmlParser::parse_timestamp');
} }
private function parse_xml_attribute(Shape $shape, Shape $memberShape, $value) private function parse_xml_attribute(Shape $shape, Shape $memberShape, $value)
{ {
$namespace = $shape['xmlNamespace']['uri'] ?? ''; $namespace = $shape['xmlNamespace']['uri'] ?? '';
$prefix = $shape['xmlNamespace']['prefix'] ?? ''; $prefix = $shape['xmlNamespace']['prefix'] ?? '';
if (!empty($prefix)) { if (!empty($prefix)) {
$prefix .= ':'; $prefix .= ':';
} }
$key = str_replace($prefix, '', $memberShape['locationName']); $key = str_replace($prefix, '', $memberShape['locationName']);
$attributes = $value->attributes($namespace); $attributes = $value->attributes($namespace);
return isset($attributes[$key]) ? (string) $attributes[$key] : null; return isset($attributes[$key]) ? (string) $attributes[$key] : null;
} }
} }

View file

@ -1,38 +1,38 @@
<?php <?php
namespace Aws\Api\Serializer; namespace Aws\Api\Serializer;
use Aws\Api\Shape; use Aws\Api\Shape;
use Aws\Api\ListShape; use Aws\Api\ListShape;
/** /**
* @internal * @internal
*/ */
class Ec2ParamBuilder extends QueryParamBuilder class Ec2ParamBuilder extends QueryParamBuilder
{ {
protected function queryName(Shape $shape, $default = null) protected function queryName(Shape $shape, $default = null)
{ {
return ($shape['queryName'] return ($shape['queryName']
?: ucfirst(@$shape['locationName'] ?: "")) ?: ucfirst(@$shape['locationName'] ?: ""))
?: $default; ?: $default;
} }
protected function isFlat(Shape $shape) protected function isFlat(Shape $shape)
{ {
return false; return false;
} }
protected function format_list( protected function format_list(
ListShape $shape, ListShape $shape,
array $value, array $value,
$prefix, $prefix,
&$query &$query
) { ) {
// Handle empty list serialization // Handle empty list serialization
if (!empty($value)) { if (!empty($value)) {
$items = $shape->getMember(); $items = $shape->getMember();
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
$this->format($items, $v, $prefix . '.' . ($k + 1), $query); $this->format($items, $v, $prefix . '.' . ($k + 1), $query);
} }
} }
} }
} }

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