Generated by Yoast SEO, this is an XML Sitemap, meant for consumption by search engines.
You can find more information about XML sitemaps on sitemaps.org.
This XML Sitemap Index file contains sitemaps.
Sitemap
Last Modified
This XML Sitemap contains URLs.
URL
Images
Last Mod.
wpml-config.xml 0000644 00000004123 14720660247 0007520 0 ustar 00 _yoast_wpseo_title_yoast_wpseo_bctitle_yoast_wpseo_metadesc_yoast_wpseo_focuskw_yoast_wpseo_meta-robots-noindex_yoast_wpseo_meta-robots-nofollow_yoast_wpseo_meta-robots-adv_yoast_wpseo_canonical_yoast_wpseo_redirect_yoast_wpseo_opengraph-description
index.php 0000644 00000000046 14720660247 0006374 0 ustar 00 ABSPATH . 'wp-admin/includes/class-wp-list-table.php',
'walker_category' => ABSPATH . 'wp-includes/category-template.php',
];
}
$cn = strtolower( $class_name );
if ( ! class_exists( $class_name ) && isset( $classes[ $cn ] ) ) {
require_once $classes[ $cn ];
}
}
$yoast_autoload_file = WPSEO_PATH . 'vendor/autoload.php';
if ( is_readable( $yoast_autoload_file ) ) {
$yoast_autoloader = require $yoast_autoload_file;
}
elseif ( ! class_exists( 'WPSEO_Options' ) ) { // Still checking since might be site-level autoload R.
add_action( 'admin_init', 'yoast_wpseo_missing_autoload', 1 );
return;
}
/**
* Include the file from the `symfony/deprecation-contracts` dependency instead of autoloading it via composer.
*
* We need to do that because autoloading via composer prevents the vendor-prefixing of the dependency itself.
* Note that we don't expect the function to be ever called since the OAuth2 library should not provide invalid input.
*/
$deprecation_contracts_file = WPSEO_PATH . 'vendor_prefixed/symfony/deprecation-contracts/functions.php';
if ( is_readable( $deprecation_contracts_file ) ) {
include $deprecation_contracts_file;
}
if ( function_exists( 'spl_autoload_register' ) ) {
spl_autoload_register( 'wpseo_auto_load' );
}
require_once WPSEO_PATH . 'src/functions.php';
/* ********************* DEFINES DEPENDING ON AUTOLOADED CODE ********************* */
/**
* Defaults to production, for safety.
*/
if ( ! defined( 'YOAST_ENVIRONMENT' ) ) {
define( 'YOAST_ENVIRONMENT', 'production' );
}
if ( YOAST_ENVIRONMENT === 'development' && isset( $yoast_autoloader ) ) {
add_action(
'plugins_loaded',
/**
* Reregisters the autoloader so that Yoast SEO is at the front.
* This prevents conflicts with the development versions of our addons.
* An anonymous function is used so we can use the autoloader variable.
* As this is only loaded in development removing this action is not a concern.
*
* @return void
*/
static function () use ( $yoast_autoloader ) {
$yoast_autoloader->unregister();
$yoast_autoloader->register( true );
},
1
);
}
/**
* Only use minified assets when we are in a production environment.
*/
if ( ! defined( 'WPSEO_CSSJS_SUFFIX' ) ) {
define( 'WPSEO_CSSJS_SUFFIX', ( YOAST_ENVIRONMENT !== 'development' ) ? '.min' : '' );
}
/* ***************************** PLUGIN (DE-)ACTIVATION *************************** */
/**
* Run single site / network-wide activation of the plugin.
*
* @param bool $networkwide Whether the plugin is being activated network-wide.
*
* @return void
*/
function wpseo_activate( $networkwide = false ) {
if ( ! is_multisite() || ! $networkwide ) {
_wpseo_activate();
}
else {
/* Multi-site network activation - activate the plugin for all blogs. */
wpseo_network_activate_deactivate( true );
}
// This is done so that the 'uninstall_{$file}' is triggered.
register_uninstall_hook( WPSEO_FILE, '__return_false' );
}
/**
* Run single site / network-wide de-activation of the plugin.
*
* @param bool $networkwide Whether the plugin is being de-activated network-wide.
*
* @return void
*/
function wpseo_deactivate( $networkwide = false ) {
if ( ! is_multisite() || ! $networkwide ) {
_wpseo_deactivate();
}
else {
/* Multi-site network activation - de-activate the plugin for all blogs. */
wpseo_network_activate_deactivate( false );
}
}
/**
* Run network-wide (de-)activation of the plugin.
*
* @param bool $activate True for plugin activation, false for de-activation.
*
* @return void
*/
function wpseo_network_activate_deactivate( $activate = true ) {
global $wpdb;
$network_blogs = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE site_id = %d", $wpdb->siteid ) );
if ( is_array( $network_blogs ) && $network_blogs !== [] ) {
foreach ( $network_blogs as $blog_id ) {
switch_to_blog( $blog_id );
if ( $activate === true ) {
_wpseo_activate();
}
else {
_wpseo_deactivate();
}
restore_current_blog();
}
}
}
/**
* Runs on activation of the plugin.
*
* @return void
*/
function _wpseo_activate() {
require_once WPSEO_PATH . 'inc/wpseo-functions.php';
require_once WPSEO_PATH . 'inc/class-wpseo-installation.php';
wpseo_load_textdomain(); // Make sure we have our translations available for the defaults.
new WPSEO_Installation();
WPSEO_Options::get_instance();
if ( ! is_multisite() ) {
WPSEO_Options::initialize();
}
else {
WPSEO_Options::maybe_set_multisite_defaults( true );
}
WPSEO_Options::ensure_options_exist();
if ( ! is_multisite() || ! ms_is_switched() ) {
// Constructor has side effects so this registers all hooks.
$GLOBALS['wpseo_rewrite'] = new WPSEO_Rewrite();
}
add_action( 'shutdown', [ 'WPSEO_Utils', 'clear_rewrites' ] );
WPSEO_Options::set( 'indexing_reason', 'first_install' );
WPSEO_Options::set( 'first_time_install', true );
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
WPSEO_Options::set( 'should_redirect_after_install_free', true );
}
else {
WPSEO_Options::set( 'activation_redirect_timestamp_free', time() );
}
// Reset tracking to be disabled by default.
if ( ! YoastSEO()->helpers->product->is_premium() && WPSEO_Options::get( 'toggled_tracking' ) !== true ) {
WPSEO_Options::set( 'tracking', false );
}
do_action( 'wpseo_register_roles' );
WPSEO_Role_Manager_Factory::get()->add();
do_action( 'wpseo_register_capabilities' );
WPSEO_Capability_Manager_Factory::get()->add();
// Clear cache so the changes are obvious.
WPSEO_Utils::clear_cache();
do_action( 'wpseo_activate' );
}
/**
* On deactivation, flush the rewrite rules so XML sitemaps stop working.
*
* @return void
*/
function _wpseo_deactivate() {
require_once WPSEO_PATH . 'inc/wpseo-functions.php';
add_action( 'shutdown', [ 'WPSEO_Utils', 'clear_rewrites' ] );
// Register capabilities, to make sure they are cleaned up.
do_action( 'wpseo_register_roles' );
do_action( 'wpseo_register_capabilities' );
// Clean up capabilities.
WPSEO_Role_Manager_Factory::get()->remove();
WPSEO_Capability_Manager_Factory::get()->remove();
// Clear cache so the changes are obvious.
WPSEO_Utils::clear_cache();
do_action( 'wpseo_deactivate' );
}
/**
* Run wpseo activation routine on creation / activation of a multisite blog if WPSEO is activated
* network-wide.
*
* Will only be called by multisite actions.
*
* {@internal Unfortunately will fail if the plugin is in the must-use directory.
* {@link https://core.trac.wordpress.org/ticket/24205} }}
*
* @param int|WP_Site $blog_id Blog ID.
*
* @return void
*/
function wpseo_on_activate_blog( $blog_id ) {
if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( $blog_id instanceof WP_Site ) {
$blog_id = (int) $blog_id->blog_id;
}
if ( is_plugin_active_for_network( WPSEO_BASENAME ) ) {
switch_to_blog( $blog_id );
wpseo_activate( false );
restore_current_blog();
}
}
/* ***************************** PLUGIN LOADING *************************** */
/**
* Load translations.
*
* @return void
*/
function wpseo_load_textdomain() {
$wpseo_path = str_replace( '\\', '/', WPSEO_PATH );
$mu_path = str_replace( '\\', '/', WPMU_PLUGIN_DIR );
if ( stripos( $wpseo_path, $mu_path ) !== false ) {
load_muplugin_textdomain( 'wordpress-seo', dirname( WPSEO_BASENAME ) . '/languages/' );
}
else {
load_plugin_textdomain( 'wordpress-seo', false, dirname( WPSEO_BASENAME ) . '/languages/' );
}
}
add_action( 'plugins_loaded', 'wpseo_load_textdomain' );
/**
* On plugins_loaded: load the minimum amount of essential files for this plugin.
*
* @return void
*/
function wpseo_init() {
require_once WPSEO_PATH . 'inc/wpseo-functions.php';
require_once WPSEO_PATH . 'inc/wpseo-functions-deprecated.php';
// Make sure our option and meta value validation routines and default values are always registered and available.
WPSEO_Options::get_instance();
WPSEO_Meta::init();
if ( version_compare( WPSEO_Options::get( 'version', 1, [ 'wpseo' ] ), WPSEO_VERSION, '<' ) ) {
if ( function_exists( 'opcache_reset' ) ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Prevent notices when opcache.restrict_api is set.
@opcache_reset();
}
new WPSEO_Upgrade();
// Get a cleaned up version of the $options.
}
$GLOBALS['wpseo_rewrite'] = new WPSEO_Rewrite();
if ( WPSEO_Options::get( 'enable_xml_sitemap', null, [ 'wpseo' ] ) === true ) {
$GLOBALS['wpseo_sitemaps'] = new WPSEO_Sitemaps();
}
if ( ! wp_doing_ajax() ) {
require_once WPSEO_PATH . 'inc/wpseo-non-ajax-functions.php';
}
$integrations = [];
$integrations[] = new WPSEO_Slug_Change_Watcher();
foreach ( $integrations as $integration ) {
$integration->register_hooks();
}
}
/**
* Loads the rest api endpoints.
*
* @return void
*/
function wpseo_init_rest_api() {
// We can't do anything when requirements are not met.
if ( ! WPSEO_Utils::is_api_available() ) {
return;
}
// Boot up REST API.
$statistics_service = new WPSEO_Statistics_Service( new WPSEO_Statistics() );
$endpoints = [];
$endpoints[] = new WPSEO_Endpoint_File_Size( new WPSEO_File_Size_Service() );
$endpoints[] = new WPSEO_Endpoint_Statistics( $statistics_service );
foreach ( $endpoints as $endpoint ) {
$endpoint->register();
}
}
/**
* Used to load the required files on the plugins_loaded hook, instead of immediately.
*
* @return void
*/
function wpseo_admin_init() {
new WPSEO_Admin_Init();
}
/* ***************************** BOOTSTRAP / HOOK INTO WP *************************** */
$spl_autoload_exists = function_exists( 'spl_autoload_register' );
if ( ! $spl_autoload_exists ) {
add_action( 'admin_init', 'yoast_wpseo_missing_spl', 1 );
}
if ( ! wp_installing() && ( $spl_autoload_exists ) ) {
add_action( 'plugins_loaded', 'wpseo_init', 14 );
add_action( 'setup_theme', [ 'Yoast_Dynamic_Rewrites', 'instance' ], 1 );
add_action( 'rest_api_init', 'wpseo_init_rest_api' );
if ( is_admin() ) {
new Yoast_Notifications();
$yoast_addon_manager = new WPSEO_Addon_Manager();
$yoast_addon_manager->register_hooks();
if ( wp_doing_ajax() ) {
require_once WPSEO_PATH . 'admin/ajax.php';
// Plugin conflict ajax hooks.
new Yoast_Plugin_Conflict_Ajax();
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: We are not processing form information but only loading the admin init class.
if ( isset( $_POST['action'] ) && is_string( $_POST['action'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information but only loading the admin init class, We are strictly comparing only.
if ( wp_unslash( $_POST['action'] ) === 'inline-save' ) {
add_action( 'plugins_loaded', 'wpseo_admin_init', 15 );
}
}
}
else {
add_action( 'plugins_loaded', 'wpseo_admin_init', 15 );
}
}
add_action( 'plugins_loaded', 'load_yoast_notifications' );
add_action( 'init', [ 'WPSEO_Replace_Vars', 'setup_statics_once' ] );
// Initializes the Yoast indexables for the first time.
YoastSEO();
/**
* Action called when the Yoast SEO plugin file has loaded.
*/
do_action( 'wpseo_loaded' );
}
// Activation and deactivation hook.
register_activation_hook( WPSEO_FILE, 'wpseo_activate' );
register_deactivation_hook( WPSEO_FILE, 'wpseo_deactivate' );
add_action( 'wp_initialize_site', 'wpseo_on_activate_blog', 99 );
add_action( 'activate_blog', 'wpseo_on_activate_blog' );
// Registers SEO capabilities.
$wpseo_register_capabilities = new WPSEO_Register_Capabilities();
$wpseo_register_capabilities->register_hooks();
// Registers SEO roles.
$wpseo_register_capabilities = new WPSEO_Register_Roles();
$wpseo_register_capabilities->register_hooks();
/**
* Wraps for notifications center class.
*
* @return void
*/
function load_yoast_notifications() {
// Init Yoast_Notification_Center class.
Yoast_Notification_Center::get();
}
/**
* Throw an error if the PHP SPL extension is disabled (prevent white screens) and self-deactivate plugin.
*
* @since 1.5.4
*
* @return void
*/
function yoast_wpseo_missing_spl() {
if ( is_admin() ) {
add_action( 'admin_notices', 'yoast_wpseo_missing_spl_notice' );
yoast_wpseo_self_deactivate();
}
}
/**
* Returns the notice in case of missing spl extension.
*
* @return void
*/
function yoast_wpseo_missing_spl_notice() {
$message = esc_html__( 'The Standard PHP Library (SPL) extension seem to be unavailable. Please ask your web host to enable it.', 'wordpress-seo' );
yoast_wpseo_activation_failed_notice( $message );
}
/**
* Throw an error if the Composer autoload is missing and self-deactivate plugin.
*
* @return void
*/
function yoast_wpseo_missing_autoload() {
if ( is_admin() ) {
add_action( 'admin_notices', 'yoast_wpseo_missing_autoload_notice' );
yoast_wpseo_self_deactivate();
}
}
/**
* Returns the notice in case of missing Composer autoload.
*
* @return void
*/
function yoast_wpseo_missing_autoload_notice() {
/* translators: %1$s expands to Yoast SEO, %2$s / %3$s: links to the installation manual in the Readme for the Yoast SEO code repository on GitHub */
$message = esc_html__( 'The %1$s plugin installation is incomplete. Please refer to %2$sinstallation instructions%3$s.', 'wordpress-seo' );
$message = sprintf( $message, 'Yoast SEO', '', '' );
yoast_wpseo_activation_failed_notice( $message );
}
/**
* Throw an error if the filter extension is disabled (prevent white screens) and self-deactivate plugin.
*
* @since 2.0
* @deprecated 23.3
* @codeCoverageIgnore
*
* @return void
*/
function yoast_wpseo_missing_filter() {
_deprecated_function( __FUNCTION__, 'Yoast SEO 23.3' );
}
/**
* Returns the notice in case of missing filter extension.
*
* @deprecated 23.3
* @codeCoverageIgnore
*
* @return void
*/
function yoast_wpseo_missing_filter_notice() {
_deprecated_function( __FUNCTION__, 'Yoast SEO 23.3' );
}
/**
* Echo's the Activation failed notice with any given message.
*
* @param string $message Message string.
*
* @return void
*/
function yoast_wpseo_activation_failed_notice( $message ) {
$title = sprintf(
/* translators: %s: Yoast SEO. */
esc_html__( '%s activation failed', 'wordpress-seo' ),
'Yoast SEO'
);
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This function is only called in 3 places that are safe.
echo '
';
}
/**
* The method will deactivate the plugin, but only once, done by the static $is_deactivated.
*
* @return void
*/
function yoast_wpseo_self_deactivate() {
static $is_deactivated;
if ( $is_deactivated === null ) {
$is_deactivated = true;
deactivate_plugins( WPSEO_BASENAME );
if ( isset( $_GET['activate'] ) ) {
unset( $_GET['activate'] );
}
}
}
/**
* Aliasses added in order to keep compatibility with Yoast SEO: Local.
*/
class_alias( '\Yoast\WP\SEO\Initializers\Initializer_Interface', '\Yoast\WP\SEO\WordPress\Initializer' );
class_alias( '\Yoast\WP\SEO\Loadable_Interface', '\Yoast\WP\SEO\WordPress\Loadable' );
class_alias( '\Yoast\WP\SEO\Integrations\Integration_Interface', '\Yoast\WP\SEO\WordPress\Integration' );
license.txt 0000644 00000101047 14720660247 0006742 0 ustar 00 GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
18. Additional terms
In the light of Article 7 of the GPL license, the following additional
terms apply:
a) You are prohibited to make misrepresentations of the origin of that
material, or to require that modified versions of such material be marked
in reasonable ways as different from the original version;
b) You are limited in the use for publicity purposes of names of
licensors or authors of the material;
c) You are declined any grant of rights under trademark law for use of
the trade names, trademarks, or service marks of YOAST B.V.;
d) You are required to indemnify 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.
END OF TERMS AND CONDITIONS
wp-seo.php 0000644 00000003174 14720660247 0006504 0 ustar 00 .
*/
if ( ! function_exists( 'add_filter' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
if ( ! defined( 'WPSEO_FILE' ) ) {
define( 'WPSEO_FILE', __FILE__ );
}
// Load the Yoast SEO plugin.
require_once dirname( WPSEO_FILE ) . '/wp-seo-main.php';
vendor_prefixed/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php 0000644 00000001613 14720660247 0024747 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider;
/**
* Interface for access token options provider
*/
interface OptionProviderInterface
{
/**
* Builds request options used for requesting an access token.
*
* @param string $method
* @param array $params
* @return array
*/
public function getAccessTokenOptions($method, array $params);
}
vendor_prefixed/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php 0000644 00000002752 14720660247 0025557 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider;
use InvalidArgumentException;
/**
* Add http basic auth into access token request options
* @link https://tools.ietf.org/html/rfc6749#section-2.3.1
*/
class HttpBasicAuthOptionProvider extends \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider
{
/**
* @inheritdoc
*/
public function getAccessTokenOptions($method, array $params)
{
if (empty($params['client_id']) || empty($params['client_secret'])) {
throw new \InvalidArgumentException('clientId and clientSecret are required for http basic auth');
}
$encodedCredentials = \base64_encode(\sprintf('%s:%s', $params['client_id'], $params['client_secret']));
unset($params['client_id'], $params['client_secret']);
$options = parent::getAccessTokenOptions($method, $params);
$options['headers']['Authorization'] = 'Basic ' . $encodedCredentials;
return $options;
}
}
vendor_prefixed/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php 0000644 00000003041 14720660247 0024613 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider;
use YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider;
use YoastSEO_Vendor\League\OAuth2\Client\Tool\QueryBuilderTrait;
/**
* Provide options for access token
*/
class PostAuthOptionProvider implements \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface
{
use QueryBuilderTrait;
/**
* @inheritdoc
*/
public function getAccessTokenOptions($method, array $params)
{
$options = ['headers' => ['content-type' => 'application/x-www-form-urlencoded']];
if ($method === \YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider::METHOD_POST) {
$options['body'] = $this->getAccessTokenBody($params);
}
return $options;
}
/**
* Returns the request body for requesting an access token.
*
* @param array $params
* @return string
*/
protected function getAccessTokenBody(array $params)
{
return $this->buildQueryString($params);
}
}
vendor_prefixed/league/oauth2-client/src/Provider/AbstractProvider.php 0000644 00000064351 14720660247 0022240 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Provider;
use YoastSEO_Vendor\GuzzleHttp\Client as HttpClient;
use YoastSEO_Vendor\GuzzleHttp\ClientInterface as HttpClientInterface;
use YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException;
use InvalidArgumentException;
use YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant;
use YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory;
use YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface;
use YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider;
use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken;
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface;
use YoastSEO_Vendor\League\OAuth2\Client\Tool\ArrayAccessorTrait;
use YoastSEO_Vendor\League\OAuth2\Client\Tool\GuardedPropertyTrait;
use YoastSEO_Vendor\League\OAuth2\Client\Tool\QueryBuilderTrait;
use YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory;
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
use UnexpectedValueException;
/**
* Represents a service provider (authorization server).
*
* @link http://tools.ietf.org/html/rfc6749#section-1.1 Roles (RFC 6749, §1.1)
*/
abstract class AbstractProvider
{
use ArrayAccessorTrait;
use GuardedPropertyTrait;
use QueryBuilderTrait;
/**
* @var string|null Key used in a token response to identify the resource owner.
*/
const ACCESS_TOKEN_RESOURCE_OWNER_ID = null;
/**
* @var string HTTP method used to fetch access tokens.
*/
const METHOD_GET = 'GET';
/**
* @var string HTTP method used to fetch access tokens.
*/
const METHOD_POST = 'POST';
/**
* @var string PKCE method used to fetch authorization token.
* The PKCE code challenge will be hashed with sha256 (recommended).
*/
const PKCE_METHOD_S256 = 'S256';
/**
* @var string PKCE method used to fetch authorization token.
* The PKCE code challenge will be sent as plain text, this is NOT recommended.
* Only use `plain` if no other option is possible.
*/
const PKCE_METHOD_PLAIN = 'plain';
/**
* @var string
*/
protected $clientId;
/**
* @var string
*/
protected $clientSecret;
/**
* @var string
*/
protected $redirectUri;
/**
* @var string
*/
protected $state;
/**
* @var string|null
*/
protected $pkceCode = null;
/**
* @var GrantFactory
*/
protected $grantFactory;
/**
* @var RequestFactory
*/
protected $requestFactory;
/**
* @var HttpClientInterface
*/
protected $httpClient;
/**
* @var OptionProviderInterface
*/
protected $optionProvider;
/**
* Constructs an OAuth 2.0 service provider.
*
* @param array $options An array of options to set on this provider.
* Options include `clientId`, `clientSecret`, `redirectUri`, and `state`.
* Individual providers may introduce more options, as needed.
* @param array $collaborators An array of collaborators that may be used to
* override this provider's default behavior. Collaborators include
* `grantFactory`, `requestFactory`, and `httpClient`.
* Individual providers may introduce more collaborators, as needed.
*/
public function __construct(array $options = [], array $collaborators = [])
{
// We'll let the GuardedPropertyTrait handle mass assignment of incoming
// options, skipping any blacklisted properties defined in the provider
$this->fillProperties($options);
if (empty($collaborators['grantFactory'])) {
$collaborators['grantFactory'] = new \YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory();
}
$this->setGrantFactory($collaborators['grantFactory']);
if (empty($collaborators['requestFactory'])) {
$collaborators['requestFactory'] = new \YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory();
}
$this->setRequestFactory($collaborators['requestFactory']);
if (empty($collaborators['httpClient'])) {
$client_options = $this->getAllowedClientOptions($options);
$collaborators['httpClient'] = new \YoastSEO_Vendor\GuzzleHttp\Client(\array_intersect_key($options, \array_flip($client_options)));
}
$this->setHttpClient($collaborators['httpClient']);
if (empty($collaborators['optionProvider'])) {
$collaborators['optionProvider'] = new \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider();
}
$this->setOptionProvider($collaborators['optionProvider']);
}
/**
* Returns the list of options that can be passed to the HttpClient
*
* @param array $options An array of options to set on this provider.
* Options include `clientId`, `clientSecret`, `redirectUri`, and `state`.
* Individual providers may introduce more options, as needed.
* @return array The options to pass to the HttpClient constructor
*/
protected function getAllowedClientOptions(array $options)
{
$client_options = ['timeout', 'proxy'];
// Only allow turning off ssl verification if it's for a proxy
if (!empty($options['proxy'])) {
$client_options[] = 'verify';
}
return $client_options;
}
/**
* Sets the grant factory instance.
*
* @param GrantFactory $factory
* @return self
*/
public function setGrantFactory(\YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory $factory)
{
$this->grantFactory = $factory;
return $this;
}
/**
* Returns the current grant factory instance.
*
* @return GrantFactory
*/
public function getGrantFactory()
{
return $this->grantFactory;
}
/**
* Sets the request factory instance.
*
* @param RequestFactory $factory
* @return self
*/
public function setRequestFactory(\YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory $factory)
{
$this->requestFactory = $factory;
return $this;
}
/**
* Returns the request factory instance.
*
* @return RequestFactory
*/
public function getRequestFactory()
{
return $this->requestFactory;
}
/**
* Sets the HTTP client instance.
*
* @param HttpClientInterface $client
* @return self
*/
public function setHttpClient(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client)
{
$this->httpClient = $client;
return $this;
}
/**
* Returns the HTTP client instance.
*
* @return HttpClientInterface
*/
public function getHttpClient()
{
return $this->httpClient;
}
/**
* Sets the option provider instance.
*
* @param OptionProviderInterface $provider
* @return self
*/
public function setOptionProvider(\YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface $provider)
{
$this->optionProvider = $provider;
return $this;
}
/**
* Returns the option provider instance.
*
* @return OptionProviderInterface
*/
public function getOptionProvider()
{
return $this->optionProvider;
}
/**
* Returns the current value of the state parameter.
*
* This can be accessed by the redirect handler during authorization.
*
* @return string
*/
public function getState()
{
return $this->state;
}
/**
* Set the value of the pkceCode parameter.
*
* When using PKCE this should be set before requesting an access token.
*
* @param string $pkceCode
* @return self
*/
public function setPkceCode($pkceCode)
{
$this->pkceCode = $pkceCode;
return $this;
}
/**
* Returns the current value of the pkceCode parameter.
*
* This can be accessed by the redirect handler during authorization.
*
* @return string|null
*/
public function getPkceCode()
{
return $this->pkceCode;
}
/**
* Returns the base URL for authorizing a client.
*
* Eg. https://oauth.service.com/authorize
*
* @return string
*/
public abstract function getBaseAuthorizationUrl();
/**
* Returns the base URL for requesting an access token.
*
* Eg. https://oauth.service.com/token
*
* @param array $params
* @return string
*/
public abstract function getBaseAccessTokenUrl(array $params);
/**
* Returns the URL for requesting the resource owner's details.
*
* @param AccessToken $token
* @return string
*/
public abstract function getResourceOwnerDetailsUrl(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token);
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
* @return string
*/
protected function getRandomState($length = 32)
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
return \bin2hex(\random_bytes($length / 2));
}
/**
* Returns a new random string to use as PKCE code_verifier and
* hashed as code_challenge parameters in an authorization flow.
* Must be between 43 and 128 characters long.
*
* @param int $length Length of the random string to be generated.
* @return string
*/
protected function getRandomPkceCode($length = 64)
{
return \substr(\strtr(\base64_encode(\random_bytes($length)), '+/', '-_'), 0, $length);
}
/**
* Returns the default scopes used by this provider.
*
* This should only be the scopes that are required to request the details
* of the resource owner, rather than all the available scopes.
*
* @return array
*/
protected abstract function getDefaultScopes();
/**
* Returns the string that should be used to separate scopes when building
* the URL for requesting an access token.
*
* @return string Scope separator, defaults to ','
*/
protected function getScopeSeparator()
{
return ',';
}
/**
* @return string|null
*/
protected function getPkceMethod()
{
return null;
}
/**
* Returns authorization parameters based on provided options.
*
* @param array $options
* @return array Authorization parameters
*/
protected function getAuthorizationParameters(array $options)
{
if (empty($options['state'])) {
$options['state'] = $this->getRandomState();
}
if (empty($options['scope'])) {
$options['scope'] = $this->getDefaultScopes();
}
$options += ['response_type' => 'code', 'approval_prompt' => 'auto'];
if (\is_array($options['scope'])) {
$separator = $this->getScopeSeparator();
$options['scope'] = \implode($separator, $options['scope']);
}
// Store the state as it may need to be accessed later on.
$this->state = $options['state'];
$pkceMethod = $this->getPkceMethod();
if (!empty($pkceMethod)) {
$this->pkceCode = $this->getRandomPkceCode();
if ($pkceMethod === static::PKCE_METHOD_S256) {
$options['code_challenge'] = \trim(\strtr(\base64_encode(\hash('sha256', $this->pkceCode, \true)), '+/', '-_'), '=');
} elseif ($pkceMethod === static::PKCE_METHOD_PLAIN) {
$options['code_challenge'] = $this->pkceCode;
} else {
throw new \InvalidArgumentException('Unknown PKCE method "' . $pkceMethod . '".');
}
$options['code_challenge_method'] = $pkceMethod;
}
// Business code layer might set a different redirect_uri parameter
// depending on the context, leave it as-is
if (!isset($options['redirect_uri'])) {
$options['redirect_uri'] = $this->redirectUri;
}
$options['client_id'] = $this->clientId;
return $options;
}
/**
* Builds the authorization URL's query string.
*
* @param array $params Query parameters
* @return string Query string
*/
protected function getAuthorizationQuery(array $params)
{
return $this->buildQueryString($params);
}
/**
* Builds the authorization URL.
*
* @param array $options
* @return string Authorization URL
*/
public function getAuthorizationUrl(array $options = [])
{
$base = $this->getBaseAuthorizationUrl();
$params = $this->getAuthorizationParameters($options);
$query = $this->getAuthorizationQuery($params);
return $this->appendQuery($base, $query);
}
/**
* Redirects the client for authorization.
*
* @param array $options
* @param callable|null $redirectHandler
* @return mixed
*/
public function authorize(array $options = [], callable $redirectHandler = null)
{
$url = $this->getAuthorizationUrl($options);
if ($redirectHandler) {
return $redirectHandler($url, $this);
}
// @codeCoverageIgnoreStart
\header('Location: ' . $url);
exit;
// @codeCoverageIgnoreEnd
}
/**
* Appends a query string to a URL.
*
* @param string $url The URL to append the query to
* @param string $query The HTTP query string
* @return string The resulting URL
*/
protected function appendQuery($url, $query)
{
$query = \trim($query, '?&');
if ($query) {
$glue = \strstr($url, '?') === \false ? '?' : '&';
return $url . $glue . $query;
}
return $url;
}
/**
* Returns the method to use when requesting an access token.
*
* @return string HTTP method
*/
protected function getAccessTokenMethod()
{
return self::METHOD_POST;
}
/**
* Returns the key used in the access token response to identify the resource owner.
*
* @return string|null Resource owner identifier key
*/
protected function getAccessTokenResourceOwnerId()
{
return static::ACCESS_TOKEN_RESOURCE_OWNER_ID;
}
/**
* Builds the access token URL's query string.
*
* @param array $params Query parameters
* @return string Query string
*/
protected function getAccessTokenQuery(array $params)
{
return $this->buildQueryString($params);
}
/**
* Checks that a provided grant is valid, or attempts to produce one if the
* provided grant is a string.
*
* @param AbstractGrant|string $grant
* @return AbstractGrant
*/
protected function verifyGrant($grant)
{
if (\is_string($grant)) {
return $this->grantFactory->getGrant($grant);
}
$this->grantFactory->checkGrant($grant);
return $grant;
}
/**
* Returns the full URL to use when requesting an access token.
*
* @param array $params Query parameters
* @return string
*/
protected function getAccessTokenUrl(array $params)
{
$url = $this->getBaseAccessTokenUrl($params);
if ($this->getAccessTokenMethod() === self::METHOD_GET) {
$query = $this->getAccessTokenQuery($params);
return $this->appendQuery($url, $query);
}
return $url;
}
/**
* Returns a prepared request for requesting an access token.
*
* @param array $params Query string parameters
* @return RequestInterface
*/
protected function getAccessTokenRequest(array $params)
{
$method = $this->getAccessTokenMethod();
$url = $this->getAccessTokenUrl($params);
$options = $this->optionProvider->getAccessTokenOptions($this->getAccessTokenMethod(), $params);
return $this->getRequest($method, $url, $options);
}
/**
* Requests an access token using a specified grant and option set.
*
* @param mixed $grant
* @param array $options
* @throws IdentityProviderException
* @return AccessTokenInterface
*/
public function getAccessToken($grant, array $options = [])
{
$grant = $this->verifyGrant($grant);
$params = ['client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'redirect_uri' => $this->redirectUri];
if (!empty($this->pkceCode)) {
$params['code_verifier'] = $this->pkceCode;
}
$params = $grant->prepareRequestParameters($params, $options);
$request = $this->getAccessTokenRequest($params);
$response = $this->getParsedResponse($request);
if (\false === \is_array($response)) {
throw new \UnexpectedValueException('Invalid response received from Authorization Server. Expected JSON.');
}
$prepared = $this->prepareAccessTokenResponse($response);
$token = $this->createAccessToken($prepared, $grant);
return $token;
}
/**
* Returns a PSR-7 request instance that is not authenticated.
*
* @param string $method
* @param string $url
* @param array $options
* @return RequestInterface
*/
public function getRequest($method, $url, array $options = [])
{
return $this->createRequest($method, $url, null, $options);
}
/**
* Returns an authenticated PSR-7 request instance.
*
* @param string $method
* @param string $url
* @param AccessTokenInterface|string|null $token
* @param array $options Any of "headers", "body", and "protocolVersion".
* @return RequestInterface
*/
public function getAuthenticatedRequest($method, $url, $token, array $options = [])
{
return $this->createRequest($method, $url, $token, $options);
}
/**
* Creates a PSR-7 request instance.
*
* @param string $method
* @param string $url
* @param AccessTokenInterface|string|null $token
* @param array $options
* @return RequestInterface
*/
protected function createRequest($method, $url, $token, array $options)
{
$defaults = ['headers' => $this->getHeaders($token)];
$options = \array_merge_recursive($defaults, $options);
$factory = $this->getRequestFactory();
return $factory->getRequestWithOptions($method, $url, $options);
}
/**
* Sends a request instance and returns a response instance.
*
* WARNING: This method does not attempt to catch exceptions caused by HTTP
* errors! It is recommended to wrap this method in a try/catch block.
*
* @param RequestInterface $request
* @return ResponseInterface
*/
public function getResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request)
{
return $this->getHttpClient()->send($request);
}
/**
* Sends a request and returns the parsed response.
*
* @param RequestInterface $request
* @throws IdentityProviderException
* @return mixed
*/
public function getParsedResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request)
{
try {
$response = $this->getResponse($request);
} catch (\YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException $e) {
$response = $e->getResponse();
}
$parsed = $this->parseResponse($response);
$this->checkResponse($response, $parsed);
return $parsed;
}
/**
* Attempts to parse a JSON response.
*
* @param string $content JSON content from response body
* @return array Parsed JSON data
* @throws UnexpectedValueException if the content could not be parsed
*/
protected function parseJson($content)
{
$content = \json_decode($content, \true);
if (\json_last_error() !== \JSON_ERROR_NONE) {
throw new \UnexpectedValueException(\sprintf("Failed to parse JSON response: %s", \json_last_error_msg()));
}
return $content;
}
/**
* Returns the content type header of a response.
*
* @param ResponseInterface $response
* @return string Semi-colon separated join of content-type headers.
*/
protected function getContentType(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
{
return \join(';', (array) $response->getHeader('content-type'));
}
/**
* Parses the response according to its content-type header.
*
* @throws UnexpectedValueException
* @param ResponseInterface $response
* @return array
*/
protected function parseResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
{
$content = (string) $response->getBody();
$type = $this->getContentType($response);
if (\strpos($type, 'urlencoded') !== \false) {
\parse_str($content, $parsed);
return $parsed;
}
// Attempt to parse the string as JSON regardless of content type,
// since some providers use non-standard content types. Only throw an
// exception if the JSON could not be parsed when it was expected to.
try {
return $this->parseJson($content);
} catch (\UnexpectedValueException $e) {
if (\strpos($type, 'json') !== \false) {
throw $e;
}
if ($response->getStatusCode() == 500) {
throw new \UnexpectedValueException('An OAuth server error was encountered that did not contain a JSON body', 0, $e);
}
return $content;
}
}
/**
* Checks a provider response for errors.
*
* @throws IdentityProviderException
* @param ResponseInterface $response
* @param array|string $data Parsed response data
* @return void
*/
protected abstract function checkResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, $data);
/**
* Prepares an parsed access token response for a grant.
*
* Custom mapping of expiration, etc should be done here. Always call the
* parent method when overloading this method.
*
* @param mixed $result
* @return array
*/
protected function prepareAccessTokenResponse(array $result)
{
if ($this->getAccessTokenResourceOwnerId() !== null) {
$result['resource_owner_id'] = $this->getValueByKey($result, $this->getAccessTokenResourceOwnerId());
}
return $result;
}
/**
* Creates an access token from a response.
*
* The grant that was used to fetch the response can be used to provide
* additional context.
*
* @param array $response
* @param AbstractGrant $grant
* @return AccessTokenInterface
*/
protected function createAccessToken(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant $grant)
{
return new \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken($response);
}
/**
* Generates a resource owner object from a successful resource owner
* details request.
*
* @param array $response
* @param AccessToken $token
* @return ResourceOwnerInterface
*/
protected abstract function createResourceOwner(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token);
/**
* Requests and returns the resource owner of given access token.
*
* @param AccessToken $token
* @return ResourceOwnerInterface
*/
public function getResourceOwner(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token)
{
$response = $this->fetchResourceOwnerDetails($token);
return $this->createResourceOwner($response, $token);
}
/**
* Requests resource owner details.
*
* @param AccessToken $token
* @return mixed
*/
protected function fetchResourceOwnerDetails(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token)
{
$url = $this->getResourceOwnerDetailsUrl($token);
$request = $this->getAuthenticatedRequest(self::METHOD_GET, $url, $token);
$response = $this->getParsedResponse($request);
if (\false === \is_array($response)) {
throw new \UnexpectedValueException('Invalid response received from Authorization Server. Expected JSON.');
}
return $response;
}
/**
* Returns the default headers used by this provider.
*
* Typically this is used to set 'Accept' or 'Content-Type' headers.
*
* @return array
*/
protected function getDefaultHeaders()
{
return [];
}
/**
* Returns the authorization headers used by this provider.
*
* Typically this is "Bearer" or "MAC". For more information see:
* http://tools.ietf.org/html/rfc6749#section-7.1
*
* No default is provided, providers must overload this method to activate
* authorization headers.
*
* @param mixed|null $token Either a string or an access token instance
* @return array
*/
protected function getAuthorizationHeaders($token = null)
{
return [];
}
/**
* Returns all headers used by this provider for a request.
*
* The request will be authenticated if an access token is provided.
*
* @param mixed|null $token object or string
* @return array
*/
public function getHeaders($token = null)
{
if ($token) {
return \array_merge($this->getDefaultHeaders(), $this->getAuthorizationHeaders($token));
}
return $this->getDefaultHeaders();
}
}
vendor_prefixed/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php 0000644 00000002273 14720660247 0026076 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception;
/**
* Exception thrown if the provider response contains errors.
*/
class IdentityProviderException extends \Exception
{
/**
* @var mixed
*/
protected $response;
/**
* @param string $message
* @param int $code
* @param mixed $response The response body
*/
public function __construct($message, $code, $response)
{
$this->response = $response;
parent::__construct($message, $code);
}
/**
* Returns the exception's response body.
*
* @return mixed
*/
public function getResponseBody()
{
return $this->response;
}
}
vendor_prefixed/league/oauth2-client/src/Provider/GenericResourceOwner.php 0000644 00000002750 14720660247 0023054 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Provider;
/**
* Represents a generic resource owner for use with the GenericProvider.
*/
class GenericResourceOwner implements \YoastSEO_Vendor\League\OAuth2\Client\Provider\ResourceOwnerInterface
{
/**
* @var array
*/
protected $response;
/**
* @var string
*/
protected $resourceOwnerId;
/**
* @param array $response
* @param string $resourceOwnerId
*/
public function __construct(array $response, $resourceOwnerId)
{
$this->response = $response;
$this->resourceOwnerId = $resourceOwnerId;
}
/**
* Returns the identifier of the authorized resource owner.
*
* @return mixed
*/
public function getId()
{
return $this->response[$this->resourceOwnerId];
}
/**
* Returns the raw resource owner response.
*
* @return array
*/
public function toArray()
{
return $this->response;
}
}
vendor_prefixed/league/oauth2-client/src/Provider/ResourceOwnerInterface.php 0000644 00000002002 14720660247 0023366 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Provider;
/**
* Classes implementing `ResourceOwnerInterface` may be used to represent
* the resource owner authenticated with a service provider.
*/
interface ResourceOwnerInterface
{
/**
* Returns the identifier of the authorized resource owner.
*
* @return mixed
*/
public function getId();
/**
* Return all of the owner details available as an array.
*
* @return array
*/
public function toArray();
}
vendor_prefixed/league/oauth2-client/src/Provider/GenericProvider.php 0000644 00000013404 14720660247 0022042 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Provider;
use InvalidArgumentException;
use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken;
use YoastSEO_Vendor\League\OAuth2\Client\Tool\BearerAuthorizationTrait;
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
/**
* Represents a generic service provider that may be used to interact with any
* OAuth 2.0 service provider, using Bearer token authentication.
*/
class GenericProvider extends \YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider
{
use BearerAuthorizationTrait;
/**
* @var string
*/
private $urlAuthorize;
/**
* @var string
*/
private $urlAccessToken;
/**
* @var string
*/
private $urlResourceOwnerDetails;
/**
* @var string
*/
private $accessTokenMethod;
/**
* @var string
*/
private $accessTokenResourceOwnerId;
/**
* @var array|null
*/
private $scopes = null;
/**
* @var string
*/
private $scopeSeparator;
/**
* @var string
*/
private $responseError = 'error';
/**
* @var string
*/
private $responseCode;
/**
* @var string
*/
private $responseResourceOwnerId = 'id';
/**
* @var string|null
*/
private $pkceMethod = null;
/**
* @param array $options
* @param array $collaborators
*/
public function __construct(array $options = [], array $collaborators = [])
{
$this->assertRequiredOptions($options);
$possible = $this->getConfigurableOptions();
$configured = \array_intersect_key($options, \array_flip($possible));
foreach ($configured as $key => $value) {
$this->{$key} = $value;
}
// Remove all options that are only used locally
$options = \array_diff_key($options, $configured);
parent::__construct($options, $collaborators);
}
/**
* Returns all options that can be configured.
*
* @return array
*/
protected function getConfigurableOptions()
{
return \array_merge($this->getRequiredOptions(), ['accessTokenMethod', 'accessTokenResourceOwnerId', 'scopeSeparator', 'responseError', 'responseCode', 'responseResourceOwnerId', 'scopes', 'pkceMethod']);
}
/**
* Returns all options that are required.
*
* @return array
*/
protected function getRequiredOptions()
{
return ['urlAuthorize', 'urlAccessToken', 'urlResourceOwnerDetails'];
}
/**
* Verifies that all required options have been passed.
*
* @param array $options
* @return void
* @throws InvalidArgumentException
*/
private function assertRequiredOptions(array $options)
{
$missing = \array_diff_key(\array_flip($this->getRequiredOptions()), $options);
if (!empty($missing)) {
throw new \InvalidArgumentException('Required options not defined: ' . \implode(', ', \array_keys($missing)));
}
}
/**
* @inheritdoc
*/
public function getBaseAuthorizationUrl()
{
return $this->urlAuthorize;
}
/**
* @inheritdoc
*/
public function getBaseAccessTokenUrl(array $params)
{
return $this->urlAccessToken;
}
/**
* @inheritdoc
*/
public function getResourceOwnerDetailsUrl(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token)
{
return $this->urlResourceOwnerDetails;
}
/**
* @inheritdoc
*/
public function getDefaultScopes()
{
return $this->scopes;
}
/**
* @inheritdoc
*/
protected function getAccessTokenMethod()
{
return $this->accessTokenMethod ?: parent::getAccessTokenMethod();
}
/**
* @inheritdoc
*/
protected function getAccessTokenResourceOwnerId()
{
return $this->accessTokenResourceOwnerId ?: parent::getAccessTokenResourceOwnerId();
}
/**
* @inheritdoc
*/
protected function getScopeSeparator()
{
return $this->scopeSeparator ?: parent::getScopeSeparator();
}
/**
* @inheritdoc
*/
protected function getPkceMethod()
{
return $this->pkceMethod ?: parent::getPkceMethod();
}
/**
* @inheritdoc
*/
protected function checkResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, $data)
{
if (!empty($data[$this->responseError])) {
$error = $data[$this->responseError];
if (!\is_string($error)) {
$error = \var_export($error, \true);
}
$code = $this->responseCode && !empty($data[$this->responseCode]) ? $data[$this->responseCode] : 0;
if (!\is_int($code)) {
$code = \intval($code);
}
throw new \YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException($error, $code, $data);
}
}
/**
* @inheritdoc
*/
protected function createResourceOwner(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token)
{
return new \YoastSEO_Vendor\League\OAuth2\Client\Provider\GenericResourceOwner($response, $this->responseResourceOwnerId);
}
}
vendor_prefixed/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php 0000644 00000001444 14720660247 0024434 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception;
use InvalidArgumentException;
/**
* Exception thrown if the grant does not extend from AbstractGrant.
*
* @see League\OAuth2\Client\Grant\AbstractGrant
*/
class InvalidGrantException extends \InvalidArgumentException
{
}
vendor_prefixed/league/oauth2-client/src/Grant/Password.php 0000644 00000002077 14720660247 0020042 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Grant;
/**
* Represents a resource owner password credentials grant.
*
* @link http://tools.ietf.org/html/rfc6749#section-1.3.3 Resource Owner Password Credentials (RFC 6749, §1.3.3)
*/
class Password extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant
{
/**
* @inheritdoc
*/
protected function getName()
{
return 'password';
}
/**
* @inheritdoc
*/
protected function getRequiredRequestParameters()
{
return ['username', 'password'];
}
}
vendor_prefixed/league/oauth2-client/src/Grant/AbstractGrant.php 0000644 00000004676 14720660247 0021006 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Grant;
use YoastSEO_Vendor\League\OAuth2\Client\Tool\RequiredParameterTrait;
/**
* Represents a type of authorization grant.
*
* An authorization grant is a credential representing the resource
* owner's authorization (to access its protected resources) used by the
* client to obtain an access token. OAuth 2.0 defines four
* grant types -- authorization code, implicit, resource owner password
* credentials, and client credentials -- as well as an extensibility
* mechanism for defining additional types.
*
* @link http://tools.ietf.org/html/rfc6749#section-1.3 Authorization Grant (RFC 6749, §1.3)
*/
abstract class AbstractGrant
{
use RequiredParameterTrait;
/**
* Returns the name of this grant, eg. 'grant_name', which is used as the
* grant type when encoding URL query parameters.
*
* @return string
*/
protected abstract function getName();
/**
* Returns a list of all required request parameters.
*
* @return array
*/
protected abstract function getRequiredRequestParameters();
/**
* Returns this grant's name as its string representation. This allows for
* string interpolation when building URL query parameters.
*
* @return string
*/
public function __toString()
{
return $this->getName();
}
/**
* Prepares an access token request's parameters by checking that all
* required parameters are set, then merging with any given defaults.
*
* @param array $defaults
* @param array $options
* @return array
*/
public function prepareRequestParameters(array $defaults, array $options)
{
$defaults['grant_type'] = $this->getName();
$required = $this->getRequiredRequestParameters();
$provided = \array_merge($defaults, $options);
$this->checkRequiredParameters($required, $provided);
return $provided;
}
}
vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php 0000644 00000002041 14720660247 0021662 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Grant;
/**
* Represents an authorization code grant.
*
* @link http://tools.ietf.org/html/rfc6749#section-1.3.1 Authorization Code (RFC 6749, §1.3.1)
*/
class AuthorizationCode extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant
{
/**
* @inheritdoc
*/
protected function getName()
{
return 'authorization_code';
}
/**
* @inheritdoc
*/
protected function getRequiredRequestParameters()
{
return ['code'];
}
}
vendor_prefixed/league/oauth2-client/src/Grant/GrantFactory.php 0000644 00000005364 14720660247 0020645 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Grant;
use YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception\InvalidGrantException;
/**
* Represents a factory used when retrieving an authorization grant type.
*/
class GrantFactory
{
/**
* @var array
*/
protected $registry = [];
/**
* Defines a grant singleton in the registry.
*
* @param string $name
* @param AbstractGrant $grant
* @return self
*/
public function setGrant($name, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant $grant)
{
$this->registry[$name] = $grant;
return $this;
}
/**
* Returns a grant singleton by name.
*
* If the grant has not be registered, a default grant will be loaded.
*
* @param string $name
* @return AbstractGrant
*/
public function getGrant($name)
{
if (empty($this->registry[$name])) {
$this->registerDefaultGrant($name);
}
return $this->registry[$name];
}
/**
* Registers a default grant singleton by name.
*
* @param string $name
* @return self
*/
protected function registerDefaultGrant($name)
{
// PascalCase the grant. E.g: 'authorization_code' becomes 'AuthorizationCode'
$class = \str_replace(' ', '', \ucwords(\str_replace(['-', '_'], ' ', $name)));
$class = 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\' . $class;
$this->checkGrant($class);
return $this->setGrant($name, new $class());
}
/**
* Determines if a variable is a valid grant.
*
* @param mixed $class
* @return boolean
*/
public function isGrant($class)
{
return \is_subclass_of($class, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant::class);
}
/**
* Checks if a variable is a valid grant.
*
* @throws InvalidGrantException
* @param mixed $class
* @return void
*/
public function checkGrant($class)
{
if (!$this->isGrant($class)) {
throw new \YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception\InvalidGrantException(\sprintf('Grant "%s" must extend AbstractGrant', \is_object($class) ? \get_class($class) : $class));
}
}
}
vendor_prefixed/league/oauth2-client/src/Grant/RefreshToken.php 0000644 00000002032 14720660247 0020626 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Grant;
/**
* Represents a refresh token grant.
*
* @link http://tools.ietf.org/html/rfc6749#section-6 Refreshing an Access Token (RFC 6749, §6)
*/
class RefreshToken extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant
{
/**
* @inheritdoc
*/
protected function getName()
{
return 'refresh_token';
}
/**
* @inheritdoc
*/
protected function getRequiredRequestParameters()
{
return ['refresh_token'];
}
}
vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php 0000644 00000002032 14720660247 0021623 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Grant;
/**
* Represents a client credentials grant.
*
* @link http://tools.ietf.org/html/rfc6749#section-1.3.4 Client Credentials (RFC 6749, §1.3.4)
*/
class ClientCredentials extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant
{
/**
* @inheritdoc
*/
protected function getName()
{
return 'client_credentials';
}
/**
* @inheritdoc
*/
protected function getRequiredRequestParameters()
{
return [];
}
}
vendor_prefixed/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php 0000644 00000001510 14720660247 0025002 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Token;
interface ResourceOwnerAccessTokenInterface extends \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface
{
/**
* Returns the resource owner identifier, if defined.
*
* @return string|null
*/
public function getResourceOwnerId();
}
vendor_prefixed/league/oauth2-client/src/Token/AccessToken.php 0000644 00000013576 14720660247 0020455 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Token;
use InvalidArgumentException;
use RuntimeException;
/**
* Represents an access token.
*
* @link http://tools.ietf.org/html/rfc6749#section-1.4 Access Token (RFC 6749, §1.4)
*/
class AccessToken implements \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface, \YoastSEO_Vendor\League\OAuth2\Client\Token\ResourceOwnerAccessTokenInterface
{
/**
* @var string
*/
protected $accessToken;
/**
* @var int
*/
protected $expires;
/**
* @var string
*/
protected $refreshToken;
/**
* @var string
*/
protected $resourceOwnerId;
/**
* @var array
*/
protected $values = [];
/**
* @var int
*/
private static $timeNow;
/**
* Set the time now. This should only be used for testing purposes.
*
* @param int $timeNow the time in seconds since epoch
* @return void
*/
public static function setTimeNow($timeNow)
{
self::$timeNow = $timeNow;
}
/**
* Reset the time now if it was set for test purposes.
*
* @return void
*/
public static function resetTimeNow()
{
self::$timeNow = null;
}
/**
* @return int
*/
public function getTimeNow()
{
return self::$timeNow ? self::$timeNow : \time();
}
/**
* Constructs an access token.
*
* @param array $options An array of options returned by the service provider
* in the access token request. The `access_token` option is required.
* @throws InvalidArgumentException if `access_token` is not provided in `$options`.
*/
public function __construct(array $options = [])
{
if (empty($options['access_token'])) {
throw new \InvalidArgumentException('Required option not passed: "access_token"');
}
$this->accessToken = $options['access_token'];
if (!empty($options['resource_owner_id'])) {
$this->resourceOwnerId = $options['resource_owner_id'];
}
if (!empty($options['refresh_token'])) {
$this->refreshToken = $options['refresh_token'];
}
// We need to know when the token expires. Show preference to
// 'expires_in' since it is defined in RFC6749 Section 5.1.
// Defer to 'expires' if it is provided instead.
if (isset($options['expires_in'])) {
if (!\is_numeric($options['expires_in'])) {
throw new \InvalidArgumentException('expires_in value must be an integer');
}
$this->expires = $options['expires_in'] != 0 ? $this->getTimeNow() + $options['expires_in'] : 0;
} elseif (!empty($options['expires'])) {
// Some providers supply the seconds until expiration rather than
// the exact timestamp. Take a best guess at which we received.
$expires = $options['expires'];
if (!$this->isExpirationTimestamp($expires)) {
$expires += $this->getTimeNow();
}
$this->expires = $expires;
}
// Capture any additional values that might exist in the token but are
// not part of the standard response. Vendors will sometimes pass
// additional user data this way.
$this->values = \array_diff_key($options, \array_flip(['access_token', 'resource_owner_id', 'refresh_token', 'expires_in', 'expires']));
}
/**
* Check if a value is an expiration timestamp or second value.
*
* @param integer $value
* @return bool
*/
protected function isExpirationTimestamp($value)
{
// If the given value is larger than the original OAuth 2 draft date,
// assume that it is meant to be a (possible expired) timestamp.
$oauth2InceptionDate = 1349067600;
// 2012-10-01
return $value > $oauth2InceptionDate;
}
/**
* @inheritdoc
*/
public function getToken()
{
return $this->accessToken;
}
/**
* @inheritdoc
*/
public function getRefreshToken()
{
return $this->refreshToken;
}
/**
* @inheritdoc
*/
public function getExpires()
{
return $this->expires;
}
/**
* @inheritdoc
*/
public function getResourceOwnerId()
{
return $this->resourceOwnerId;
}
/**
* @inheritdoc
*/
public function hasExpired()
{
$expires = $this->getExpires();
if (empty($expires)) {
throw new \RuntimeException('"expires" is not set on the token');
}
return $expires < \time();
}
/**
* @inheritdoc
*/
public function getValues()
{
return $this->values;
}
/**
* @inheritdoc
*/
public function __toString()
{
return (string) $this->getToken();
}
/**
* @inheritdoc
*/
public function jsonSerialize()
{
$parameters = $this->values;
if ($this->accessToken) {
$parameters['access_token'] = $this->accessToken;
}
if ($this->refreshToken) {
$parameters['refresh_token'] = $this->refreshToken;
}
if ($this->expires) {
$parameters['expires'] = $this->expires;
}
if ($this->resourceOwnerId) {
$parameters['resource_owner_id'] = $this->resourceOwnerId;
}
return $parameters;
}
}
vendor_prefixed/league/oauth2-client/src/Token/AccessTokenInterface.php 0000644 00000003464 14720660247 0022271 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Token;
use JsonSerializable;
use ReturnTypeWillChange;
use RuntimeException;
interface AccessTokenInterface extends \JsonSerializable
{
/**
* Returns the access token string of this instance.
*
* @return string
*/
public function getToken();
/**
* Returns the refresh token, if defined.
*
* @return string|null
*/
public function getRefreshToken();
/**
* Returns the expiration timestamp in seconds, if defined.
*
* @return integer|null
*/
public function getExpires();
/**
* Checks if this token has expired.
*
* @return boolean true if the token has expired, false otherwise.
* @throws RuntimeException if 'expires' is not set on the token.
*/
public function hasExpired();
/**
* Returns additional vendor values stored in the token.
*
* @return array
*/
public function getValues();
/**
* Returns a string representation of the access token
*
* @return string
*/
public function __toString();
/**
* Returns an array of parameters to serialize when this is serialized with
* json_encode().
*
* @return array
*/
#[ReturnTypeWillChange]
public function jsonSerialize();
}
vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php 0000644 00000002740 14720660247 0022524 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Tool;
use BadMethodCallException;
/**
* Provides functionality to check for required parameters.
*/
trait RequiredParameterTrait
{
/**
* Checks for a required parameter in a hash.
*
* @throws BadMethodCallException
* @param string $name
* @param array $params
* @return void
*/
private function checkRequiredParameter($name, array $params)
{
if (!isset($params[$name])) {
throw new \BadMethodCallException(\sprintf('Required parameter not passed: "%s"', $name));
}
}
/**
* Checks for multiple required parameters in a hash.
*
* @throws InvalidArgumentException
* @param array $names
* @param array $params
* @return void
*/
private function checkRequiredParameters(array $names, array $params)
{
foreach ($names as $name) {
$this->checkRequiredParameter($name, $params);
}
}
}
vendor_prefixed/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php 0000644 00000002173 14720660247 0023064 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Tool;
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface;
/**
* Enables `Bearer` header authorization for providers.
*
* @link http://tools.ietf.org/html/rfc6750 Bearer Token Usage (RFC 6750)
*/
trait BearerAuthorizationTrait
{
/**
* Returns authorization headers for the 'bearer' grant.
*
* @param AccessTokenInterface|string|null $token Either a string or an access token instance
* @return array
*/
protected function getAuthorizationHeaders($token = null)
{
return ['Authorization' => 'Bearer ' . $token];
}
}
vendor_prefixed/league/oauth2-client/src/Tool/ArrayAccessorTrait.php 0000644 00000002662 14720660247 0021647 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Tool;
/**
* Provides generic array navigation tools.
*/
trait ArrayAccessorTrait
{
/**
* Returns a value by key using dot notation.
*
* @param array $data
* @param string $key
* @param mixed|null $default
* @return mixed
*/
private function getValueByKey(array $data, $key, $default = null)
{
if (!\is_string($key) || empty($key) || !\count($data)) {
return $default;
}
if (\strpos($key, '.') !== \false) {
$keys = \explode('.', $key);
foreach ($keys as $innerKey) {
if (!\is_array($data) || !\array_key_exists($innerKey, $data)) {
return $default;
}
$data = $data[$innerKey];
}
return $data;
}
return \array_key_exists($key, $data) ? $data[$key] : $default;
}
}
vendor_prefixed/league/oauth2-client/src/Tool/ProviderRedirectTrait.php 0000644 00000006472 14720660247 0022365 0 ustar 00 redirectLimit) {
$attempts++;
$response = $this->getHttpClient()->send($request, ['allow_redirects' => \false]);
if ($this->isRedirect($response)) {
$redirectUrl = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($response->getHeader('Location')[0]);
$request = $request->withUri($redirectUrl);
} else {
break;
}
}
return $response;
}
/**
* Returns the HTTP client instance.
*
* @return GuzzleHttp\ClientInterface
*/
public abstract function getHttpClient();
/**
* Retrieves current redirect limit.
*
* @return integer
*/
public function getRedirectLimit()
{
return $this->redirectLimit;
}
/**
* Determines if a given response is a redirect.
*
* @param ResponseInterface $response
*
* @return boolean
*/
protected function isRedirect(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
{
$statusCode = $response->getStatusCode();
return $statusCode > 300 && $statusCode < 400 && $response->hasHeader('Location');
}
/**
* Sends a request instance and returns a response instance.
*
* WARNING: This method does not attempt to catch exceptions caused by HTTP
* errors! It is recommended to wrap this method in a try/catch block.
*
* @param RequestInterface $request
* @return ResponseInterface
*/
public function getResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request)
{
try {
$response = $this->followRequestRedirects($request);
} catch (\YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException $e) {
$response = $e->getResponse();
}
return $response;
}
/**
* Updates the redirect limit.
*
* @param integer $limit
* @return League\OAuth2\Client\Provider\AbstractProvider
* @throws InvalidArgumentException
*/
public function setRedirectLimit($limit)
{
if (!\is_int($limit)) {
throw new \InvalidArgumentException('redirectLimit must be an integer.');
}
if ($limit < 1) {
throw new \InvalidArgumentException('redirectLimit must be greater than or equal to one.');
}
$this->redirectLimit = $limit;
return $this;
}
}
vendor_prefixed/league/oauth2-client/src/Tool/MacAuthorizationTrait.php 0000644 00000005133 14720660247 0022363 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Tool;
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken;
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface;
/**
* Enables `MAC` header authorization for providers.
*
* @link http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-05 Message Authentication Code (MAC) Tokens
*/
trait MacAuthorizationTrait
{
/**
* Returns the id of this token for MAC generation.
*
* @param AccessToken $token
* @return string
*/
protected abstract function getTokenId(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token);
/**
* Returns the MAC signature for the current request.
*
* @param string $id
* @param integer $ts
* @param string $nonce
* @return string
*/
protected abstract function getMacSignature($id, $ts, $nonce);
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
* @return string
*/
protected abstract function getRandomState($length = 32);
/**
* Returns the authorization headers for the 'mac' grant.
*
* @param AccessTokenInterface|string|null $token Either a string or an access token instance
* @return array
* @codeCoverageIgnore
*
* @todo This is currently untested and provided only as an example. If you
* complete the implementation, please create a pull request for
* https://github.com/thephpleague/oauth2-client
*/
protected function getAuthorizationHeaders($token = null)
{
if ($token === null) {
return [];
}
$ts = \time();
$id = $this->getTokenId($token);
$nonce = $this->getRandomState(16);
$mac = $this->getMacSignature($id, $ts, $nonce);
$parts = [];
foreach (\compact('id', 'ts', 'nonce', 'mac') as $key => $value) {
$parts[] = \sprintf('%s="%s"', $key, $value);
}
return ['Authorization' => 'MAC ' . \implode(', ', $parts)];
}
}
vendor_prefixed/league/oauth2-client/src/Tool/GuardedPropertyTrait.php 0000644 00000003432 14720660247 0022222 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Tool;
/**
* Provides support for blacklisting explicit properties from the
* mass assignment behavior.
*/
trait GuardedPropertyTrait
{
/**
* The properties that aren't mass assignable.
*
* @var array
*/
protected $guarded = [];
/**
* Attempts to mass assign the given options to explicitly defined properties,
* skipping over any properties that are defined in the guarded array.
*
* @param array $options
* @return mixed
*/
protected function fillProperties(array $options = [])
{
if (isset($options['guarded'])) {
unset($options['guarded']);
}
foreach ($options as $option => $value) {
if (\property_exists($this, $option) && !$this->isGuarded($option)) {
$this->{$option} = $value;
}
}
}
/**
* Returns current guarded properties.
*
* @return array
*/
public function getGuarded()
{
return $this->guarded;
}
/**
* Determines if the given property is guarded.
*
* @param string $property
* @return bool
*/
public function isGuarded($property)
{
return \in_array($property, $this->getGuarded());
}
}
vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php 0000644 00000001630 14720660247 0021514 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Tool;
/**
* Provides a standard way to generate query strings.
*/
trait QueryBuilderTrait
{
/**
* Build a query string from an array.
*
* @param array $params
*
* @return string
*/
protected function buildQueryString(array $params)
{
return \http_build_query($params, '', '&', \PHP_QUERY_RFC3986);
}
}
vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php 0000644 00000004262 14720660247 0021060 0 ustar 00
* @license http://opensource.org/licenses/MIT MIT
* @link http://thephpleague.com/oauth2-client/ Documentation
* @link https://packagist.org/packages/league/oauth2-client Packagist
* @link https://github.com/thephpleague/oauth2-client GitHub
*/
namespace YoastSEO_Vendor\League\OAuth2\Client\Tool;
use YoastSEO_Vendor\GuzzleHttp\Psr7\Request;
/**
* Used to produce PSR-7 Request instances.
*
* @link https://github.com/guzzle/guzzle/pull/1101
*/
class RequestFactory
{
/**
* Creates a PSR-7 Request instance.
*
* @param null|string $method HTTP method for the request.
* @param null|string $uri URI for the request.
* @param array $headers Headers for the message.
* @param string|resource|StreamInterface $body Message body.
* @param string $version HTTP protocol version.
*
* @return Request
*/
public function getRequest($method, $uri, array $headers = [], $body = null, $version = '1.1')
{
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri, $headers, $body, $version);
}
/**
* Parses simplified options.
*
* @param array $options Simplified options.
*
* @return array Extended options for use with getRequest.
*/
protected function parseOptions(array $options)
{
// Should match default values for getRequest
$defaults = ['headers' => [], 'body' => null, 'version' => '1.1'];
return \array_merge($defaults, $options);
}
/**
* Creates a request using a simplified array of options.
*
* @param null|string $method
* @param null|string $uri
* @param array $options
*
* @return Request
*/
public function getRequestWithOptions($method, $uri, array $options = [])
{
$options = $this->parseOptions($options);
return $this->getRequest($method, $uri, $options['headers'], $options['body'], $options['version']);
}
}
vendor_prefixed/symfony/deprecation-contracts/function.php 0000644 00000001760 14720660247 0020300 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
if (!function_exists('trigger_deprecation')) {
/**
* Triggers a silenced deprecation notice.
*
* @param string $package The name of the Composer package that is triggering the deprecation
* @param string $version The version of the package that introduced the deprecation
* @param string $message The message of the deprecation
* @param mixed ...$args Values to insert in the message using printf() formatting
*
* @author Nicolas Grekas
*/
function trigger_deprecation(string $package, string $version, string $message, ...$args): void
{
@trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
}
}
vendor_prefixed/symfony/dependency-injection/Exception/LogicException.php 0000644 00000001014 14720660247 0023120 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
/**
* Base LogicException for Dependency Injection component.
*/
class LogicException extends \LogicException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface
{
}
vendor_prefixed/symfony/dependency-injection/Exception/InvalidArgumentException.php 0000644 00000001151 14720660247 0025156 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
/**
* Base InvalidArgumentException for Dependency Injection component.
*
* @author Bulat Shakirzyanov
*/
class InvalidArgumentException extends \InvalidArgumentException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface
{
}
vendor_prefixed/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php 0000644 00000002101 14720660247 0026765 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
/**
* This exception is thrown when a circular reference is detected.
*
* @author Johannes M. Schmitt
*/
class ServiceCircularReferenceException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException
{
private $serviceId;
private $path;
public function __construct($serviceId, array $path, \Exception $previous = null)
{
parent::__construct(\sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, \implode(' -> ', $path)), 0, $previous);
$this->serviceId = $serviceId;
$this->path = $path;
}
public function getServiceId()
{
return $this->serviceId;
}
public function getPath()
{
return $this->path;
}
}
vendor_prefixed/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php 0000644 00000001757 14720660247 0027325 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
/**
* This exception is thrown when a circular reference in a parameter is detected.
*
* @author Fabien Potencier
*/
class ParameterCircularReferenceException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException
{
private $parameters;
public function __construct($parameters, \Exception $previous = null)
{
parent::__construct(\sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], \implode('" > "', $parameters), $parameters[0]), 0, $previous);
$this->parameters = $parameters;
}
public function getParameters()
{
return $this->parameters;
}
}
vendor_prefixed/symfony/dependency-injection/Exception/ExceptionInterface.php 0000644 00000001223 14720660247 0023765 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
use YoastSEO_Vendor\Psr\Container\ContainerExceptionInterface;
/**
* Base ExceptionInterface for Dependency Injection component.
*
* @author Fabien Potencier
* @author Bulat Shakirzyanov
*/
interface ExceptionInterface extends \YoastSEO_Vendor\Psr\Container\ContainerExceptionInterface
{
}
vendor_prefixed/symfony/dependency-injection/Exception/ServiceNotFoundException.php 0000644 00000003556 14720660247 0025155 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
use YoastSEO_Vendor\Psr\Container\NotFoundExceptionInterface;
/**
* This exception is thrown when a non-existent service is requested.
*
* @author Johannes M. Schmitt
*/
class ServiceNotFoundException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException implements \YoastSEO_Vendor\Psr\Container\NotFoundExceptionInterface
{
private $id;
private $sourceId;
private $alternatives;
public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = [], $msg = null)
{
if (null !== $msg) {
// no-op
} elseif (null === $sourceId) {
$msg = \sprintf('You have requested a non-existent service "%s".', $id);
} else {
$msg = \sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id);
}
if ($alternatives) {
if (1 == \count($alternatives)) {
$msg .= ' Did you mean this: "';
} else {
$msg .= ' Did you mean one of these: "';
}
$msg .= \implode('", "', $alternatives) . '"?';
}
parent::__construct($msg, 0, $previous);
$this->id = $id;
$this->sourceId = $sourceId;
$this->alternatives = $alternatives;
}
public function getId()
{
return $this->id;
}
public function getSourceId()
{
return $this->sourceId;
}
public function getAlternatives()
{
return $this->alternatives;
}
}
vendor_prefixed/symfony/dependency-injection/Exception/EnvNotFoundException.php 0000644 00000001300 14720660247 0024266 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
/**
* This exception is thrown when an environment variable is not found.
*
* @author Nicolas Grekas
*/
class EnvNotFoundException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
{
public function __construct($name)
{
parent::__construct(\sprintf('Environment variable not found: "%s".', $name));
}
}
vendor_prefixed/symfony/dependency-injection/Exception/RuntimeException.php 0000644 00000001113 14720660247 0023506 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception;
/**
* Base RuntimeException for Dependency Injection component.
*
* @author Johannes M. Schmitt
*/
class RuntimeException extends \RuntimeException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface
{
}
vendor_prefixed/symfony/dependency-injection/Argument/RewindableGenerator.php 0000644 00000001613 14720660247 0023760 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Argument;
/**
* @internal
*/
class RewindableGenerator implements \IteratorAggregate, \Countable
{
private $generator;
private $count;
/**
* @param int|callable $count
*/
public function __construct(callable $generator, $count)
{
$this->generator = $generator;
$this->count = $count;
}
public function getIterator()
{
$g = $this->generator;
return $g();
}
public function count()
{
if (\is_callable($count = $this->count)) {
$this->count = $count();
}
return $this->count;
}
}
vendor_prefixed/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php 0000644 00000003633 14720660247 0024327 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException;
/**
* Holds read-only parameters.
*
* @author Fabien Potencier
*/
class FrozenParameterBag extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag
{
/**
* For performance reasons, the constructor assumes that
* all keys are already lowercased.
*
* This is always the case when used internally.
*
* @param array $parameters An array of parameters
*/
public function __construct(array $parameters = [])
{
$this->parameters = $parameters;
$this->resolved = \true;
}
/**
* {@inheritdoc}
*/
public function clear()
{
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call clear() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function add(array $parameters)
{
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call add() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function set($name, $value)
{
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function remove($name)
{
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call remove() on a frozen ParameterBag.');
}
}
vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBag.php 0000644 00000022671 14720660247 0023146 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
* Holds parameters.
*
* @author Fabien Potencier
*/
class ParameterBag implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface
{
protected $parameters = [];
protected $resolved = \false;
private $normalizedNames = [];
/**
* @param array $parameters An array of parameters
*/
public function __construct(array $parameters = [])
{
$this->add($parameters);
}
/**
* Clears all parameters.
*/
public function clear()
{
$this->parameters = [];
}
/**
* Adds parameters to the service container parameters.
*
* @param array $parameters An array of parameters
*/
public function add(array $parameters)
{
foreach ($parameters as $key => $value) {
$this->set($key, $value);
}
}
/**
* {@inheritdoc}
*/
public function all()
{
return $this->parameters;
}
/**
* {@inheritdoc}
*/
public function get($name)
{
$name = $this->normalizeName($name);
if (!\array_key_exists($name, $this->parameters)) {
if (!$name) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException($name);
}
$alternatives = [];
foreach ($this->parameters as $key => $parameterValue) {
$lev = \levenshtein($name, $key);
if ($lev <= \strlen($name) / 3 || \false !== \strpos($key, $name)) {
$alternatives[] = $key;
}
}
$nonNestedAlternative = null;
if (!\count($alternatives) && \false !== \strpos($name, '.')) {
$namePartsLength = \array_map('strlen', \explode('.', $name));
$key = \substr($name, 0, -1 * (1 + \array_pop($namePartsLength)));
while (\count($namePartsLength)) {
if ($this->has($key)) {
if (\is_array($this->get($key))) {
$nonNestedAlternative = $key;
}
break;
}
$key = \substr($key, 0, -1 * (1 + \array_pop($namePartsLength)));
}
}
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative);
}
return $this->parameters[$name];
}
/**
* Sets a service container parameter.
*
* @param string $name The parameter name
* @param mixed $value The parameter value
*/
public function set($name, $value)
{
$this->parameters[$this->normalizeName($name)] = $value;
}
/**
* {@inheritdoc}
*/
public function has($name)
{
return \array_key_exists($this->normalizeName($name), $this->parameters);
}
/**
* Removes a parameter.
*
* @param string $name The parameter name
*/
public function remove($name)
{
unset($this->parameters[$this->normalizeName($name)]);
}
/**
* {@inheritdoc}
*/
public function resolve()
{
if ($this->resolved) {
return;
}
$parameters = [];
foreach ($this->parameters as $key => $value) {
try {
$value = $this->resolveValue($value);
$parameters[$key] = $this->unescapeValue($value);
} catch (\YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException $e) {
$e->setSourceKey($key);
throw $e;
}
}
$this->parameters = $parameters;
$this->resolved = \true;
}
/**
* Replaces parameter placeholders (%name%) by their values.
*
* @param mixed $value A value
* @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
*
* @return mixed The resolved value
*
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
* @throws ParameterCircularReferenceException if a circular reference if detected
* @throws RuntimeException when a given parameter has a type problem
*/
public function resolveValue($value, array $resolving = [])
{
if (\is_array($value)) {
$args = [];
foreach ($value as $k => $v) {
$args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving);
}
return $args;
}
if (!\is_string($value) || 2 > \strlen($value)) {
return $value;
}
return $this->resolveString($value, $resolving);
}
/**
* Resolves parameters inside a string.
*
* @param string $value The string to resolve
* @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
*
* @return mixed The resolved string
*
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
* @throws ParameterCircularReferenceException if a circular reference if detected
* @throws RuntimeException when a given parameter has a type problem
*/
public function resolveString($value, array $resolving = [])
{
// we do this to deal with non string values (Boolean, integer, ...)
// as the preg_replace_callback throw an exception when trying
// a non-string in a parameter value
if (\preg_match('/^%([^%\\s]+)%$/', $value, $match)) {
$key = $match[1];
$lcKey = \strtolower($key);
// strtolower() to be removed in 4.0
if (isset($resolving[$lcKey])) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($resolving));
}
$resolving[$lcKey] = \true;
return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
}
return \preg_replace_callback('/%%|%([^%\\s]+)%/', function ($match) use($resolving, $value) {
// skip %%
if (!isset($match[1])) {
return '%%';
}
$key = $match[1];
$lcKey = \strtolower($key);
// strtolower() to be removed in 4.0
if (isset($resolving[$lcKey])) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($resolving));
}
$resolved = $this->get($key);
if (!\is_string($resolved) && !\is_numeric($resolved)) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type "%s" inside string value "%s".', $key, \gettype($resolved), $value));
}
$resolved = (string) $resolved;
$resolving[$lcKey] = \true;
return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving);
}, $value);
}
public function isResolved()
{
return $this->resolved;
}
/**
* {@inheritdoc}
*/
public function escapeValue($value)
{
if (\is_string($value)) {
return \str_replace('%', '%%', $value);
}
if (\is_array($value)) {
$result = [];
foreach ($value as $k => $v) {
$result[$k] = $this->escapeValue($v);
}
return $result;
}
return $value;
}
/**
* {@inheritdoc}
*/
public function unescapeValue($value)
{
if (\is_string($value)) {
return \str_replace('%%', '%', $value);
}
if (\is_array($value)) {
$result = [];
foreach ($value as $k => $v) {
$result[$k] = $this->unescapeValue($v);
}
return $result;
}
return $value;
}
private function normalizeName($name)
{
if (isset($this->normalizedNames[$normalizedName = \strtolower($name)])) {
$normalizedName = $this->normalizedNames[$normalizedName];
if ((string) $name !== $normalizedName) {
@\trigger_error(\sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.', $name, $normalizedName), \E_USER_DEPRECATED);
}
} else {
$normalizedName = $this->normalizedNames[$normalizedName] = (string) $name;
}
return $normalizedName;
}
}
vendor_prefixed/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php 0000644 00000010007 14720660247 0025750 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
* @author Nicolas Grekas
*/
class EnvPlaceholderParameterBag extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag
{
private $envPlaceholders = [];
private $providedTypes = [];
/**
* {@inheritdoc}
*/
public function get($name)
{
if (0 === \strpos($name, 'env(') && ')' === \substr($name, -1) && 'env()' !== $name) {
$env = \substr($name, 4, -1);
if (isset($this->envPlaceholders[$env])) {
foreach ($this->envPlaceholders[$env] as $placeholder) {
return $placeholder;
// return first result
}
}
if (!\preg_match('/^(?:\\w++:)*+\\w++$/', $env)) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException(\sprintf('Invalid "%s" name: only "word" characters are allowed.', $name));
}
if ($this->has($name)) {
$defaultValue = parent::get($name);
if (null !== $defaultValue && !\is_scalar($defaultValue)) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('The default value of an env() parameter must be scalar or null, but "%s" given to "%s".', \gettype($defaultValue), $name));
}
}
$uniqueName = \md5($name . \uniqid(\mt_rand(), \true));
$placeholder = \sprintf('env_%s_%s', \str_replace(':', '_', $env), $uniqueName);
$this->envPlaceholders[$env][$placeholder] = $placeholder;
return $placeholder;
}
return parent::get($name);
}
/**
* Returns the map of env vars used in the resolved parameter values to their placeholders.
*
* @return string[][] A map of env var names to their placeholders
*/
public function getEnvPlaceholders()
{
return $this->envPlaceholders;
}
/**
* Merges the env placeholders of another EnvPlaceholderParameterBag.
*/
public function mergeEnvPlaceholders(self $bag)
{
if ($newPlaceholders = $bag->getEnvPlaceholders()) {
$this->envPlaceholders += $newPlaceholders;
foreach ($newPlaceholders as $env => $placeholders) {
$this->envPlaceholders[$env] += $placeholders;
}
}
}
/**
* Maps env prefixes to their corresponding PHP types.
*/
public function setProvidedTypes(array $providedTypes)
{
$this->providedTypes = $providedTypes;
}
/**
* Gets the PHP types corresponding to env() parameter prefixes.
*
* @return string[][]
*/
public function getProvidedTypes()
{
return $this->providedTypes;
}
/**
* {@inheritdoc}
*/
public function resolve()
{
if ($this->resolved) {
return;
}
parent::resolve();
foreach ($this->envPlaceholders as $env => $placeholders) {
if (!$this->has($name = "env({$env})")) {
continue;
}
if (\is_numeric($default = $this->parameters[$name])) {
$this->parameters[$name] = (string) $default;
} elseif (null !== $default && !\is_scalar($default)) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('The default value of env parameter "%s" must be scalar or null, "%s" given.', $env, \gettype($default)));
}
}
}
}
vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php 0000644 00000005370 14720660247 0024764 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
/**
* ParameterBagInterface.
*
* @author Fabien Potencier
*/
interface ParameterBagInterface
{
/**
* Clears all parameters.
*
* @throws LogicException if the ParameterBagInterface can not be cleared
*/
public function clear();
/**
* Adds parameters to the service container parameters.
*
* @param array $parameters An array of parameters
*
* @throws LogicException if the parameter can not be added
*/
public function add(array $parameters);
/**
* Gets the service container parameters.
*
* @return array An array of parameters
*/
public function all();
/**
* Gets a service container parameter.
*
* @param string $name The parameter name
*
* @return mixed The parameter value
*
* @throws ParameterNotFoundException if the parameter is not defined
*/
public function get($name);
/**
* Removes a parameter.
*
* @param string $name The parameter name
*/
public function remove($name);
/**
* Sets a service container parameter.
*
* @param string $name The parameter name
* @param mixed $value The parameter value
*
* @throws LogicException if the parameter can not be set
*/
public function set($name, $value);
/**
* Returns true if a parameter name is defined.
*
* @param string $name The parameter name
*
* @return bool true if the parameter name is defined, false otherwise
*/
public function has($name);
/**
* Replaces parameter placeholders (%name%) by their values for all parameters.
*/
public function resolve();
/**
* Replaces parameter placeholders (%name%) by their values.
*
* @param mixed $value A value
*
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
*/
public function resolveValue($value);
/**
* Escape parameter placeholders %.
*
* @param mixed $value
*
* @return mixed
*/
public function escapeValue($value);
/**
* Unescape parameter placeholders %.
*
* @param mixed $value
*
* @return mixed
*/
public function unescapeValue($value);
}
vendor_prefixed/symfony/dependency-injection/ResettableContainerInterface.php 0000644 00000002015 14720660247 0024026 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection;
/**
* ResettableContainerInterface defines additional resetting functionality
* for containers, allowing to release shared services when the container is
* not needed anymore.
*
* @author Christophe Coevoet
*/
interface ResettableContainerInterface extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface
{
/**
* Resets shared services from the container.
*
* The container is not intended to be used again after being reset in a normal workflow. This method is
* meant as a way to release references for ref-counting.
* A subsequent call to ContainerInterface::get will recreate a new instance of the shared service.
*/
public function reset();
}
vendor_prefixed/symfony/dependency-injection/ContainerInterface.php 0000644 00000005677 14720660247 0022034 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection;
use YoastSEO_Vendor\Psr\Container\ContainerInterface as PsrContainerInterface;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
/**
* ContainerInterface is the interface implemented by service container classes.
*
* @author Fabien Potencier
* @author Johannes M. Schmitt
*/
interface ContainerInterface extends \YoastSEO_Vendor\Psr\Container\ContainerInterface
{
const EXCEPTION_ON_INVALID_REFERENCE = 1;
const NULL_ON_INVALID_REFERENCE = 2;
const IGNORE_ON_INVALID_REFERENCE = 3;
const IGNORE_ON_UNINITIALIZED_REFERENCE = 4;
/**
* Sets a service.
*
* @param string $id The service identifier
* @param object|null $service The service instance
*/
public function set($id, $service);
/**
* Gets a service.
*
* @param string $id The service identifier
* @param int $invalidBehavior The behavior when the service does not exist
*
* @return object|null The associated service
*
* @throws ServiceCircularReferenceException When a circular reference is detected
* @throws ServiceNotFoundException When the service is not defined
*
* @see Reference
*/
public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
/**
* Returns true if the given service is defined.
*
* @param string $id The service identifier
*
* @return bool true if the service is defined, false otherwise
*/
public function has($id);
/**
* Check for whether or not a service has been initialized.
*
* @param string $id
*
* @return bool true if the service has been initialized, false otherwise
*/
public function initialized($id);
/**
* Gets a parameter.
*
* @param string $name The parameter name
*
* @return mixed The parameter value
*
* @throws InvalidArgumentException if the parameter is not defined
*/
public function getParameter($name);
/**
* Checks if a parameter exists.
*
* @param string $name The parameter name
*
* @return bool The presence of parameter in container
*/
public function hasParameter($name);
/**
* Sets a parameter.
*
* @param string $name The parameter name
* @param mixed $value The parameter value
*/
public function setParameter($name, $value);
}
vendor_prefixed/symfony/dependency-injection/Container.php 0000644 00000047734 14720660247 0020213 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
/**
* Container is a dependency injection container.
*
* It gives access to object instances (services).
* Services and parameters are simple key/pair stores.
* The container can have four possible behaviors when a service
* does not exist (or is not initialized for the last case):
*
* * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
* * NULL_ON_INVALID_REFERENCE: Returns null
* * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference
* (for instance, ignore a setter if the service does not exist)
* * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references
*
* @author Fabien Potencier
* @author Johannes M. Schmitt
*/
class Container implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ResettableContainerInterface
{
protected $parameterBag;
protected $services = [];
protected $fileMap = [];
protected $methodMap = [];
protected $aliases = [];
protected $loading = [];
protected $resolving = [];
protected $syntheticIds = [];
/**
* @internal
*/
protected $privates = [];
/**
* @internal
*/
protected $normalizedIds = [];
private $underscoreMap = ['_' => '', '.' => '_', '\\' => '_'];
private $envCache = [];
private $compiled = \false;
private $getEnv;
public function __construct(\YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface $parameterBag = null)
{
$this->parameterBag = $parameterBag ?: new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag();
}
/**
* Compiles the container.
*
* This method does two things:
*
* * Parameter values are resolved;
* * The parameter bag is frozen.
*/
public function compile()
{
$this->parameterBag->resolve();
$this->parameterBag = new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag($this->parameterBag->all());
$this->compiled = \true;
}
/**
* Returns true if the container is compiled.
*
* @return bool
*/
public function isCompiled()
{
return $this->compiled;
}
/**
* Returns true if the container parameter bag are frozen.
*
* @deprecated since version 3.3, to be removed in 4.0.
*
* @return bool true if the container parameter bag are frozen, false otherwise
*/
public function isFrozen()
{
@\trigger_error(\sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), \E_USER_DEPRECATED);
return $this->parameterBag instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
}
/**
* Gets the service container parameter bag.
*
* @return ParameterBagInterface A ParameterBagInterface instance
*/
public function getParameterBag()
{
return $this->parameterBag;
}
/**
* Gets a parameter.
*
* @param string $name The parameter name
*
* @return mixed The parameter value
*
* @throws InvalidArgumentException if the parameter is not defined
*/
public function getParameter($name)
{
return $this->parameterBag->get($name);
}
/**
* Checks if a parameter exists.
*
* @param string $name The parameter name
*
* @return bool The presence of parameter in container
*/
public function hasParameter($name)
{
return $this->parameterBag->has($name);
}
/**
* Sets a parameter.
*
* @param string $name The parameter name
* @param mixed $value The parameter value
*/
public function setParameter($name, $value)
{
$this->parameterBag->set($name, $value);
}
/**
* Sets a service.
*
* Setting a synthetic service to null resets it: has() returns false and get()
* behaves in the same way as if the service was never created.
*
* @param string $id The service identifier
* @param object|null $service The service instance
*/
public function set($id, $service)
{
// Runs the internal initializer; used by the dumped container to include always-needed files
if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) {
$initialize = $this->privates['service_container'];
unset($this->privates['service_container']);
$initialize();
}
$id = $this->normalizeId($id);
if ('service_container' === $id) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException('You cannot set service "service_container".');
}
if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) {
// no-op
} elseif (null === $service) {
@\trigger_error(\sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
unset($this->privates[$id]);
} else {
@\trigger_error(\sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
}
} elseif (isset($this->services[$id])) {
if (null === $service) {
@\trigger_error(\sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
} else {
@\trigger_error(\sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
}
}
if (isset($this->aliases[$id])) {
unset($this->aliases[$id]);
}
if (null === $service) {
unset($this->services[$id]);
return;
}
$this->services[$id] = $service;
}
/**
* Returns true if the given service is defined.
*
* @param string $id The service identifier
*
* @return bool true if the service is defined, false otherwise
*/
public function has($id)
{
for ($i = 2;;) {
if (isset($this->privates[$id])) {
@\trigger_error(\sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
}
if (isset($this->aliases[$id])) {
$id = $this->aliases[$id];
}
if (isset($this->services[$id])) {
return \true;
}
if ('service_container' === $id) {
return \true;
}
if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
return \true;
}
if (--$i && $id !== ($normalizedId = $this->normalizeId($id))) {
$id = $normalizedId;
continue;
}
// We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
// and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
if (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class && \method_exists($this, 'get' . \strtr($id, $this->underscoreMap) . 'Service')) {
@\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED);
return \true;
}
return \false;
}
}
/**
* Gets a service.
*
* If a service is defined both through a set() method and
* with a get{$id}Service() method, the former has always precedence.
*
* @param string $id The service identifier
* @param int $invalidBehavior The behavior when the service does not exist
*
* @return object|null The associated service
*
* @throws ServiceCircularReferenceException When a circular reference is detected
* @throws ServiceNotFoundException When the service is not defined
* @throws \Exception if an exception has been thrown when the service has been resolved
*
* @see Reference
*/
public function get($id, $invalidBehavior = 1)
{
// Attempt to retrieve the service by checking first aliases then
// available services. Service IDs are case insensitive, however since
// this method can be called thousands of times during a request, avoid
// calling $this->normalizeId($id) unless necessary.
for ($i = 2;;) {
if (isset($this->privates[$id])) {
@\trigger_error(\sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.', $id), \E_USER_DEPRECATED);
}
if (isset($this->aliases[$id])) {
$id = $this->aliases[$id];
}
// Re-use shared service instance if it exists.
if (isset($this->services[$id])) {
return $this->services[$id];
}
if ('service_container' === $id) {
return $this;
}
if (isset($this->loading[$id])) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException($id, \array_merge(\array_keys($this->loading), [$id]));
}
$this->loading[$id] = \true;
try {
if (isset($this->fileMap[$id])) {
return 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]);
} elseif (isset($this->methodMap[$id])) {
return 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}();
} elseif (--$i && $id !== ($normalizedId = $this->normalizeId($id))) {
unset($this->loading[$id]);
$id = $normalizedId;
continue;
} elseif (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class && \method_exists($this, $method = 'get' . \strtr($id, $this->underscoreMap) . 'Service')) {
// We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
// and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
@\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED);
return 4 === $invalidBehavior ? null : $this->{$method}();
}
break;
} catch (\Exception $e) {
unset($this->services[$id]);
throw $e;
} finally {
unset($this->loading[$id]);
}
}
if (1 === $invalidBehavior) {
if (!$id) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id);
}
if (isset($this->syntheticIds[$id])) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id));
}
if (isset($this->getRemovedIds()[$id])) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id));
}
$alternatives = [];
foreach ($this->getServiceIds() as $knownId) {
$lev = \levenshtein($id, $knownId);
if ($lev <= \strlen($id) / 3 || \false !== \strpos($knownId, $id)) {
$alternatives[] = $knownId;
}
}
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, $alternatives);
}
}
/**
* Returns true if the given service has actually been initialized.
*
* @param string $id The service identifier
*
* @return bool true if service has already been initialized, false otherwise
*/
public function initialized($id)
{
$id = $this->normalizeId($id);
if (isset($this->privates[$id])) {
@\trigger_error(\sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), \E_USER_DEPRECATED);
}
if (isset($this->aliases[$id])) {
$id = $this->aliases[$id];
}
if ('service_container' === $id) {
return \false;
}
return isset($this->services[$id]);
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->services = [];
}
/**
* Gets all service ids.
*
* @return string[] An array of all defined service ids
*/
public function getServiceIds()
{
$ids = [];
if (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class) {
// We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
// and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
@\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED);
foreach (\get_class_methods($this) as $method) {
if (\preg_match('/^get(.+)Service$/', $method, $match)) {
$ids[] = self::underscore($match[1]);
}
}
}
$ids[] = 'service_container';
return \array_map('strval', \array_unique(\array_merge($ids, \array_keys($this->methodMap), \array_keys($this->fileMap), \array_keys($this->aliases), \array_keys($this->services))));
}
/**
* Gets service ids that existed at compile time.
*
* @return array
*/
public function getRemovedIds()
{
return [];
}
/**
* Camelizes a string.
*
* @param string $id A string to camelize
*
* @return string The camelized string
*/
public static function camelize($id)
{
return \strtr(\ucwords(\strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']);
}
/**
* A string to underscore.
*
* @param string $id The string to underscore
*
* @return string The underscored string
*/
public static function underscore($id)
{
return \strtolower(\preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], \str_replace('_', '.', $id)));
}
/**
* Creates a service by requiring its factory file.
*/
protected function load($file)
{
return require $file;
}
/**
* Fetches a variable from the environment.
*
* @param string $name The name of the environment variable
*
* @return mixed The value to use for the provided environment variable name
*
* @throws EnvNotFoundException When the environment variable is not found and has no default value
*/
protected function getEnv($name)
{
if (isset($this->resolving[$envName = "env({$name})"])) {
throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($this->resolving));
}
if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) {
return $this->envCache[$name];
}
if (!$this->has($id = 'container.env_var_processors_locator')) {
$this->set($id, new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ServiceLocator([]));
}
if (!$this->getEnv) {
$this->getEnv = new \ReflectionMethod($this, __FUNCTION__);
$this->getEnv->setAccessible(\true);
$this->getEnv = $this->getEnv->getClosure($this);
}
$processors = $this->get($id);
if (\false !== ($i = \strpos($name, ':'))) {
$prefix = \substr($name, 0, $i);
$localName = \substr($name, 1 + $i);
} else {
$prefix = 'string';
$localName = $name;
}
$processor = $processors->has($prefix) ? $processors->get($prefix) : new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\EnvVarProcessor($this);
$this->resolving[$envName] = \true;
try {
return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv);
} finally {
unset($this->resolving[$envName]);
}
}
/**
* Returns the case sensitive id used at registration time.
*
* @param string $id
*
* @return string
*
* @internal
*/
public function normalizeId($id)
{
if (!\is_string($id)) {
$id = (string) $id;
}
if (isset($this->normalizedIds[$normalizedId = \strtolower($id)])) {
$normalizedId = $this->normalizedIds[$normalizedId];
if ($id !== $normalizedId) {
@\trigger_error(\sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.3.', $id, $normalizedId), \E_USER_DEPRECATED);
}
} else {
$normalizedId = $this->normalizedIds[$normalizedId] = $id;
}
return $normalizedId;
}
private function __clone()
{
}
}
vendor_prefixed/guzzlehttp/promises/src/Promise.php 0000644 00000022177 14720660247 0016747 0 ustar 00 waitFn = $waitFn;
$this->cancelFn = $cancelFn;
}
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
if ($this->state === self::PENDING) {
$p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(null, [$this, 'cancel']);
$this->handlers[] = [$p, $onFulfilled, $onRejected];
$p->waitList = $this->waitList;
$p->waitList[] = $this;
return $p;
}
// Return a fulfilled promise and immediately invoke any callbacks.
if ($this->state === self::FULFILLED) {
$promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($this->result);
return $onFulfilled ? $promise->then($onFulfilled) : $promise;
}
// It's either cancelled or rejected, so return a rejected promise
// and immediately invoke any callbacks.
$rejection = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($this->result);
return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
}
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->then(null, $onRejected);
}
public function wait(bool $unwrap = \true)
{
$this->waitIfPending();
if ($this->result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) {
return $this->result->wait($unwrap);
}
if ($unwrap) {
if ($this->state === self::FULFILLED) {
return $this->result;
}
// It's rejected so "unwrap" and throw an exception.
throw \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($this->result);
}
}
public function getState() : string
{
return $this->state;
}
public function cancel() : void
{
if ($this->state !== self::PENDING) {
return;
}
$this->waitFn = $this->waitList = null;
if ($this->cancelFn) {
$fn = $this->cancelFn;
$this->cancelFn = null;
try {
$fn();
} catch (\Throwable $e) {
$this->reject($e);
}
}
// Reject the promise only if it wasn't rejected in a then callback.
/** @psalm-suppress RedundantCondition */
if ($this->state === self::PENDING) {
$this->reject(new \YoastSEO_Vendor\GuzzleHttp\Promise\CancellationException('Promise has been cancelled'));
}
}
public function resolve($value) : void
{
$this->settle(self::FULFILLED, $value);
}
public function reject($reason) : void
{
$this->settle(self::REJECTED, $reason);
}
private function settle(string $state, $value) : void
{
if ($this->state !== self::PENDING) {
// Ignore calls with the same resolution.
if ($state === $this->state && $value === $this->result) {
return;
}
throw $this->state === $state ? new \LogicException("The promise is already {$state}.") : new \LogicException("Cannot change a {$this->state} promise to {$state}");
}
if ($value === $this) {
throw new \LogicException('Cannot fulfill or reject a promise with itself');
}
// Clear out the state of the promise but stash the handlers.
$this->state = $state;
$this->result = $value;
$handlers = $this->handlers;
$this->handlers = null;
$this->waitList = $this->waitFn = null;
$this->cancelFn = null;
if (!$handlers) {
return;
}
// If the value was not a settled promise or a thenable, then resolve
// it in the task queue using the correct ID.
if (!\is_object($value) || !\method_exists($value, 'then')) {
$id = $state === self::FULFILLED ? 1 : 2;
// It's a success, so resolve the handlers in the queue.
\YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->add(static function () use($id, $value, $handlers) : void {
foreach ($handlers as $handler) {
self::callHandler($id, $value, $handler);
}
});
} elseif ($value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\Promise && \YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($value)) {
// We can just merge our handlers onto the next promise.
$value->handlers = \array_merge($value->handlers, $handlers);
} else {
// Resolve the handlers when the forwarded promise is resolved.
$value->then(static function ($value) use($handlers) : void {
foreach ($handlers as $handler) {
self::callHandler(1, $value, $handler);
}
}, static function ($reason) use($handlers) : void {
foreach ($handlers as $handler) {
self::callHandler(2, $reason, $handler);
}
});
}
}
/**
* Call a stack of handlers using a specific callback index and value.
*
* @param int $index 1 (resolve) or 2 (reject).
* @param mixed $value Value to pass to the callback.
* @param array $handler Array of handler data (promise and callbacks).
*/
private static function callHandler(int $index, $value, array $handler) : void
{
/** @var PromiseInterface $promise */
$promise = $handler[0];
// The promise may have been cancelled or resolved before placing
// this thunk in the queue.
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($promise)) {
return;
}
try {
if (isset($handler[$index])) {
/*
* If $f throws an exception, then $handler will be in the exception
* stack trace. Since $handler contains a reference to the callable
* itself we get a circular reference. We clear the $handler
* here to avoid that memory leak.
*/
$f = $handler[$index];
unset($handler);
$promise->resolve($f($value));
} elseif ($index === 1) {
// Forward resolution values as-is.
$promise->resolve($value);
} else {
// Forward rejections down the chain.
$promise->reject($value);
}
} catch (\Throwable $reason) {
$promise->reject($reason);
}
}
private function waitIfPending() : void
{
if ($this->state !== self::PENDING) {
return;
} elseif ($this->waitFn) {
$this->invokeWaitFn();
} elseif ($this->waitList) {
$this->invokeWaitList();
} else {
// If there's no wait function, then reject the promise.
$this->reject('Cannot wait on a promise that has ' . 'no internal wait function. You must provide a wait ' . 'function when constructing the promise to be able to ' . 'wait on a promise.');
}
\YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->run();
/** @psalm-suppress RedundantCondition */
if ($this->state === self::PENDING) {
$this->reject('Invoking the wait callback did not resolve the promise');
}
}
private function invokeWaitFn() : void
{
try {
$wfn = $this->waitFn;
$this->waitFn = null;
$wfn(\true);
} catch (\Throwable $reason) {
if ($this->state === self::PENDING) {
// The promise has not been resolved yet, so reject the promise
// with the exception.
$this->reject($reason);
} else {
// The promise was already resolved, so there's a problem in
// the application.
throw $reason;
}
}
}
private function invokeWaitList() : void
{
$waitList = $this->waitList;
$this->waitList = null;
foreach ($waitList as $result) {
do {
$result->waitIfPending();
$result = $result->result;
} while ($result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\Promise);
if ($result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) {
$result->wait(\false);
}
}
}
}
vendor_prefixed/guzzlehttp/promises/src/Coroutine.php 0000644 00000010412 14720660247 0017265 0 ustar 00 then(function ($v) { echo $v; });
*
* @param callable $generatorFn Generator function to wrap into a promise.
*
* @return Promise
*
* @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
*/
final class Coroutine implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
/**
* @var PromiseInterface|null
*/
private $currentPromise;
/**
* @var Generator
*/
private $generator;
/**
* @var Promise
*/
private $result;
public function __construct(callable $generatorFn)
{
$this->generator = $generatorFn();
$this->result = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () : void {
while (isset($this->currentPromise)) {
$this->currentPromise->wait();
}
});
try {
$this->nextCoroutine($this->generator->current());
} catch (\Throwable $throwable) {
$this->result->reject($throwable);
}
}
/**
* Create a new coroutine.
*/
public static function of(callable $generatorFn) : self
{
return new self($generatorFn);
}
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->result->then($onFulfilled, $onRejected);
}
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->result->otherwise($onRejected);
}
public function wait(bool $unwrap = \true)
{
return $this->result->wait($unwrap);
}
public function getState() : string
{
return $this->result->getState();
}
public function resolve($value) : void
{
$this->result->resolve($value);
}
public function reject($reason) : void
{
$this->result->reject($reason);
}
public function cancel() : void
{
$this->currentPromise->cancel();
$this->result->cancel();
}
private function nextCoroutine($yielded) : void
{
$this->currentPromise = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
}
/**
* @internal
*/
public function _handleSuccess($value) : void
{
unset($this->currentPromise);
try {
$next = $this->generator->send($value);
if ($this->generator->valid()) {
$this->nextCoroutine($next);
} else {
$this->result->resolve($value);
}
} catch (\Throwable $throwable) {
$this->result->reject($throwable);
}
}
/**
* @internal
*/
public function _handleFailure($reason) : void
{
unset($this->currentPromise);
try {
$nextYield = $this->generator->throw(\YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($reason));
// The throw was caught, so keep iterating on the coroutine
$this->nextCoroutine($nextYield);
} catch (\Throwable $throwable) {
$this->result->reject($throwable);
}
}
}
vendor_prefixed/guzzlehttp/promises/src/Utils.php 0000644 00000021320 14720660247 0016416 0 ustar 00
* while ($eventLoop->isRunning()) {
* GuzzleHttp\Promise\Utils::queue()->run();
* }
*
*
* @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
*/
public static function queue(\YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface $assign = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface
{
static $queue;
if ($assign) {
$queue = $assign;
} elseif (!$queue) {
$queue = new \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueue();
}
return $queue;
}
/**
* Adds a function to run in the task queue when it is next `run()` and
* returns a promise that is fulfilled or rejected with the result.
*
* @param callable $task Task function to run.
*/
public static function task(callable $task) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$queue = self::queue();
$promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']);
$queue->add(function () use($task, $promise) : void {
try {
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) {
$promise->resolve($task());
}
} catch (\Throwable $e) {
$promise->reject($e);
}
});
return $promise;
}
/**
* Synchronously waits on a promise to resolve and returns an inspection
* state array.
*
* Returns a state associative array containing a "state" key mapping to a
* valid promise state. If the state of the promise is "fulfilled", the
* array will contain a "value" key mapping to the fulfilled value of the
* promise. If the promise is rejected, the array will contain a "reason"
* key mapping to the rejection reason of the promise.
*
* @param PromiseInterface $promise Promise or value.
*/
public static function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : array
{
try {
return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $promise->wait()];
} catch (\YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException $e) {
return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e->getReason()];
} catch (\Throwable $e) {
return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e];
}
}
/**
* Waits on all of the provided promises, but does not unwrap rejected
* promises as thrown exception.
*
* Returns an array of inspection state arrays.
*
* @see inspect for the inspection state array format.
*
* @param PromiseInterface[] $promises Traversable of promises to wait upon.
*/
public static function inspectAll($promises) : array
{
$results = [];
foreach ($promises as $key => $promise) {
$results[$key] = self::inspect($promise);
}
return $results;
}
/**
* Waits on all of the provided promises and returns the fulfilled values.
*
* Returns an array that contains the value of each promise (in the same
* order the promises were provided). An exception is thrown if any of the
* promises are rejected.
*
* @param iterable $promises Iterable of PromiseInterface objects to wait on.
*
* @throws \Throwable on error
*/
public static function unwrap($promises) : array
{
$results = [];
foreach ($promises as $key => $promise) {
$results[$key] = $promise->wait();
}
return $results;
}
/**
* Given an array of promises, return a promise that is fulfilled when all
* the items in the array are fulfilled.
*
* The promise's fulfillment value is an array with fulfillment values at
* respective positions to the original array. If any promise in the array
* rejects, the returned promise is rejected with the rejection reason.
*
* @param mixed $promises Promises or values.
* @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
*/
public static function all($promises, bool $recursive = \false) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$results = [];
$promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void {
$results[$idx] = $value;
}, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\Promise $aggregate) : void {
$aggregate->reject($reason);
})->then(function () use(&$results) {
\ksort($results);
return $results;
});
if (\true === $recursive) {
$promise = $promise->then(function ($results) use($recursive, &$promises) {
foreach ($promises as $promise) {
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) {
return self::all($promises, $recursive);
}
}
return $results;
});
}
return $promise;
}
/**
* Initiate a competitive race between multiple promises or values (values
* will become immediately fulfilled promises).
*
* When count amount of promises have been fulfilled, the returned promise
* is fulfilled with an array that contains the fulfillment values of the
* winners in order of resolution.
*
* This promise is rejected with a {@see AggregateException} if the number
* of fulfilled promises is less than the desired $count.
*
* @param int $count Total number of promises.
* @param mixed $promises Promises or values.
*/
public static function some(int $count, $promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$results = [];
$rejections = [];
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $p) use(&$results, $count) : void {
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($p)) {
return;
}
$results[$idx] = $value;
if (\count($results) >= $count) {
$p->resolve(null);
}
}, function ($reason) use(&$rejections) : void {
$rejections[] = $reason;
})->then(function () use(&$results, &$rejections, $count) {
if (\count($results) !== $count) {
throw new \YoastSEO_Vendor\GuzzleHttp\Promise\AggregateException('Not enough promises to fulfill count', $rejections);
}
\ksort($results);
return \array_values($results);
});
}
/**
* Like some(), with 1 as count. However, if the promise fulfills, the
* fulfillment value is not an array of 1 but the value directly.
*
* @param mixed $promises Promises or values.
*/
public static function any($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return self::some(1, $promises)->then(function ($values) {
return $values[0];
});
}
/**
* Returns a promise that is fulfilled when all of the provided promises have
* been fulfilled or rejected.
*
* The returned promise is fulfilled with an array of inspection state arrays.
*
* @see inspect for the inspection state array format.
*
* @param mixed $promises Promises or values.
*/
public static function settle($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$results = [];
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void {
$results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $value];
}, function ($reason, $idx) use(&$results) : void {
$results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $reason];
})->then(function () use(&$results) {
\ksort($results);
return $results;
});
}
}
vendor_prefixed/guzzlehttp/promises/src/TaskQueueInterface.php 0000644 00000000723 14720660247 0021052 0 ustar 00 iterable = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::iterFor($iterable);
if (isset($config['concurrency'])) {
$this->concurrency = $config['concurrency'];
}
if (isset($config['fulfilled'])) {
$this->onFulfilled = $config['fulfilled'];
}
if (isset($config['rejected'])) {
$this->onRejected = $config['rejected'];
}
}
/** @psalm-suppress InvalidNullableReturnType */
public function promise() : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
if ($this->aggregate) {
return $this->aggregate;
}
try {
$this->createPromise();
/** @psalm-assert Promise $this->aggregate */
$this->iterable->rewind();
$this->refillPending();
} catch (\Throwable $e) {
$this->aggregate->reject($e);
}
/**
* @psalm-suppress NullableReturnStatement
*/
return $this->aggregate;
}
private function createPromise() : void
{
$this->mutex = \false;
$this->aggregate = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () : void {
if ($this->checkIfFinished()) {
return;
}
\reset($this->pending);
// Consume a potentially fluctuating list of promises while
// ensuring that indexes are maintained (precluding array_shift).
while ($promise = \current($this->pending)) {
\next($this->pending);
$promise->wait();
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($this->aggregate)) {
return;
}
}
});
// Clear the references when the promise is resolved.
$clearFn = function () : void {
$this->iterable = $this->concurrency = $this->pending = null;
$this->onFulfilled = $this->onRejected = null;
$this->nextPendingIndex = 0;
};
$this->aggregate->then($clearFn, $clearFn);
}
private function refillPending() : void
{
if (!$this->concurrency) {
// Add all pending promises.
while ($this->addPending() && $this->advanceIterator()) {
}
return;
}
// Add only up to N pending promises.
$concurrency = \is_callable($this->concurrency) ? ($this->concurrency)(\count($this->pending)) : $this->concurrency;
$concurrency = \max($concurrency - \count($this->pending), 0);
// Concurrency may be set to 0 to disallow new promises.
if (!$concurrency) {
return;
}
// Add the first pending promise.
$this->addPending();
// Note this is special handling for concurrency=1 so that we do
// not advance the iterator after adding the first promise. This
// helps work around issues with generators that might not have the
// next value to yield until promise callbacks are called.
while (--$concurrency && $this->advanceIterator() && $this->addPending()) {
}
}
private function addPending() : bool
{
if (!$this->iterable || !$this->iterable->valid()) {
return \false;
}
$promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($this->iterable->current());
$key = $this->iterable->key();
// Iterable keys may not be unique, so we use a counter to
// guarantee uniqueness
$idx = $this->nextPendingIndex++;
$this->pending[$idx] = $promise->then(function ($value) use($idx, $key) : void {
if ($this->onFulfilled) {
($this->onFulfilled)($value, $key, $this->aggregate);
}
$this->step($idx);
}, function ($reason) use($idx, $key) : void {
if ($this->onRejected) {
($this->onRejected)($reason, $key, $this->aggregate);
}
$this->step($idx);
});
return \true;
}
private function advanceIterator() : bool
{
// Place a lock on the iterator so that we ensure to not recurse,
// preventing fatal generator errors.
if ($this->mutex) {
return \false;
}
$this->mutex = \true;
try {
$this->iterable->next();
$this->mutex = \false;
return \true;
} catch (\Throwable $e) {
$this->aggregate->reject($e);
$this->mutex = \false;
return \false;
}
}
private function step(int $idx) : void
{
// If the promise was already resolved, then ignore this step.
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($this->aggregate)) {
return;
}
unset($this->pending[$idx]);
// Only refill pending promises if we are not locked, preventing the
// EachPromise to recursively invoke the provided iterator, which
// cause a fatal error: "Cannot resume an already running generator"
if ($this->advanceIterator() && !$this->checkIfFinished()) {
// Add more pending promises if possible.
$this->refillPending();
}
}
private function checkIfFinished() : bool
{
if (!$this->pending && !$this->iterable->valid()) {
// Resolve the promise if there's nothing left to do.
$this->aggregate->resolve(null);
return \true;
}
return \false;
}
}
vendor_prefixed/guzzlehttp/promises/src/CancellationException.php 0000644 00000000405 14720660247 0021572 0 ustar 00 run();
*
* @final
*/
class TaskQueue implements \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface
{
private $enableShutdown = \true;
private $queue = [];
public function __construct(bool $withShutdown = \true)
{
if ($withShutdown) {
\register_shutdown_function(function () : void {
if ($this->enableShutdown) {
// Only run the tasks if an E_ERROR didn't occur.
$err = \error_get_last();
if (!$err || $err['type'] ^ \E_ERROR) {
$this->run();
}
}
});
}
}
public function isEmpty() : bool
{
return !$this->queue;
}
public function add(callable $task) : void
{
$this->queue[] = $task;
}
public function run() : void
{
while ($task = \array_shift($this->queue)) {
/** @var callable $task */
$task();
}
}
/**
* The task queue will be run and exhausted by default when the process
* exits IFF the exit is not the result of a PHP E_ERROR error.
*
* You can disable running the automatic shutdown of the queue by calling
* this function. If you disable the task queue shutdown process, then you
* MUST either run the task queue (as a result of running your event loop
* or manually using the run() method) or wait on each outstanding promise.
*
* Note: This shutdown will occur before any destructors are triggered.
*/
public function disableShutdown() : void
{
$this->enableShutdown = \false;
}
}
vendor_prefixed/guzzlehttp/promises/src/RejectionException.php 0000644 00000002327 14720660247 0021125 0 ustar 00 reason = $reason;
$message = 'The promise was rejected';
if ($description) {
$message .= ' with reason: ' . $description;
} elseif (\is_string($reason) || \is_object($reason) && \method_exists($reason, '__toString')) {
$message .= ' with reason: ' . $this->reason;
} elseif ($reason instanceof \JsonSerializable) {
$message .= ' with reason: ' . \json_encode($this->reason, \JSON_PRETTY_PRINT);
}
parent::__construct($message);
}
/**
* Returns the rejection reason.
*
* @return mixed
*/
public function getReason()
{
return $this->reason;
}
}
vendor_prefixed/guzzlehttp/promises/src/AggregateException.php 0000644 00000000661 14720660247 0021070 0 ustar 00 reason = $reason;
}
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
// If there's no onRejected callback then just return self.
if (!$onRejected) {
return $this;
}
$queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue();
$reason = $this->reason;
$p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']);
$queue->add(static function () use($p, $reason, $onRejected) : void {
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($p)) {
try {
// Return a resolved promise if onRejected does not throw.
$p->resolve($onRejected($reason));
} catch (\Throwable $e) {
// onRejected threw, so return a rejected promise.
$p->reject($e);
}
}
});
return $p;
}
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->then(null, $onRejected);
}
public function wait(bool $unwrap = \true)
{
if ($unwrap) {
throw \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($this->reason);
}
return null;
}
public function getState() : string
{
return self::REJECTED;
}
public function resolve($value) : void
{
throw new \LogicException('Cannot resolve a rejected promise');
}
public function reject($reason) : void
{
if ($reason !== $this->reason) {
throw new \LogicException('Cannot reject a rejected promise');
}
}
public function cancel() : void
{
// pass
}
}
vendor_prefixed/guzzlehttp/promises/src/Each.php 0000644 00000005143 14720660247 0016163 0 ustar 00 $onFulfilled, 'rejected' => $onRejected]))->promise();
}
/**
* Like of, but only allows a certain number of outstanding promises at any
* given time.
*
* $concurrency may be an integer or a function that accepts the number of
* pending promises and returns a numeric concurrency limit value to allow
* for dynamic a concurrency size.
*
* @param mixed $iterable
* @param int|callable $concurrency
*/
public static function ofLimit($iterable, $concurrency, callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return (new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected, 'concurrency' => $concurrency]))->promise();
}
/**
* Like limit, but ensures that no promise in the given $iterable argument
* is rejected. If any promise is rejected, then the aggregate promise is
* rejected with the encountered rejection.
*
* @param mixed $iterable
* @param int|callable $concurrency
*/
public static function ofLimitAll($iterable, $concurrency, callable $onFulfilled = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return self::ofLimit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $aggregate) : void {
$aggregate->reject($reason);
});
}
}
vendor_prefixed/guzzlehttp/promises/src/PromisorInterface.php 0000644 00000000456 14720660247 0020760 0 ustar 00 then([$promise, 'resolve'], [$promise, 'reject']);
return $promise;
}
return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($value);
}
/**
* Creates a rejected promise for a reason if the reason is not a promise.
* If the provided reason is a promise, then it is returned as-is.
*
* @param mixed $reason Promise or reason.
*/
public static function rejectionFor($reason) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
if ($reason instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) {
return $reason;
}
return new \YoastSEO_Vendor\GuzzleHttp\Promise\RejectedPromise($reason);
}
/**
* Create an exception for a rejected promise value.
*
* @param mixed $reason
*/
public static function exceptionFor($reason) : \Throwable
{
if ($reason instanceof \Throwable) {
return $reason;
}
return new \YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException($reason);
}
/**
* Returns an iterator for the given value.
*
* @param mixed $value
*/
public static function iterFor($value) : \Iterator
{
if ($value instanceof \Iterator) {
return $value;
}
if (\is_array($value)) {
return new \ArrayIterator($value);
}
return new \ArrayIterator([$value]);
}
}
vendor_prefixed/guzzlehttp/promises/src/FulfilledPromise.php 0000644 00000004261 14720660247 0020570 0 ustar 00 value = $value;
}
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
// Return itself if there is no onFulfilled function.
if (!$onFulfilled) {
return $this;
}
$queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue();
$p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']);
$value = $this->value;
$queue->add(static function () use($p, $value, $onFulfilled) : void {
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($p)) {
try {
$p->resolve($onFulfilled($value));
} catch (\Throwable $e) {
$p->reject($e);
}
}
});
return $p;
}
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->then(null, $onRejected);
}
public function wait(bool $unwrap = \true)
{
return $unwrap ? $this->value : null;
}
public function getState() : string
{
return self::FULFILLED;
}
public function resolve($value) : void
{
if ($value !== $this->value) {
throw new \LogicException('Cannot resolve a fulfilled promise');
}
}
public function reject($reason) : void
{
throw new \LogicException('Cannot reject a fulfilled promise');
}
public function cancel() : void
{
// pass
}
}
vendor_prefixed/guzzlehttp/promises/src/Is.php 0000644 00000002336 14720660247 0015677 0 ustar 00 getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING;
}
/**
* Returns true if a promise is fulfilled or rejected.
*/
public static function settled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool
{
return $promise->getState() !== \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING;
}
/**
* Returns true if a promise is fulfilled.
*/
public static function fulfilled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool
{
return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED;
}
/**
* Returns true if a promise is rejected.
*/
public static function rejected(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool
{
return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED;
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Exception/TransferException.php 0000644 00000000257 14720660247 0022404 0 ustar 00 request = $request;
$this->handlerContext = $handlerContext;
}
/**
* Get the request that caused the exception
*/
public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
return $this->request;
}
/**
* Get contextual information about the error from the underlying handler.
*
* The contents of this array will vary depending on which handler you are
* using. It may also be just an empty array. Relying on this data will
* couple you to a specific handler, but can give more debug information
* when needed.
*/
public function getHandlerContext() : array
{
return $this->handlerContext;
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php 0000644 00000000304 14720660247 0023702 0 ustar 00 getStatusCode() : 0;
parent::__construct($message, $code, $previous);
$this->request = $request;
$this->response = $response;
$this->handlerContext = $handlerContext;
}
/**
* Wrap non-RequestExceptions with a RequestException
*/
public static function wrapException(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \Throwable $e) : \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException
{
return $e instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $e : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($e->getMessage(), $request, null, $e);
}
/**
* Factory method to create a new exception with a normalized error message
*
* @param RequestInterface $request Request sent
* @param ResponseInterface $response Response received
* @param \Throwable|null $previous Previous exception
* @param array $handlerContext Optional handler context
* @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer
*/
public static function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $previous = null, array $handlerContext = [], \YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface $bodySummarizer = null) : self
{
if (!$response) {
return new self('Error completing request', $request, null, $previous, $handlerContext);
}
$level = (int) \floor($response->getStatusCode() / 100);
if ($level === 4) {
$label = 'Client error';
$className = \YoastSEO_Vendor\GuzzleHttp\Exception\ClientException::class;
} elseif ($level === 5) {
$label = 'Server error';
$className = \YoastSEO_Vendor\GuzzleHttp\Exception\ServerException::class;
} else {
$label = 'Unsuccessful request';
$className = __CLASS__;
}
$uri = $request->getUri();
$uri = static::obfuscateUri($uri);
// Client Error: `GET /` resulted in a `404 Not Found` response:
// ... (truncated)
$message = \sprintf('%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), $uri->__toString(), $response->getStatusCode(), $response->getReasonPhrase());
$summary = ($bodySummarizer ?? new \YoastSEO_Vendor\GuzzleHttp\BodySummarizer())->summarize($response);
if ($summary !== null) {
$message .= ":\n{$summary}\n";
}
return new $className($message, $request, $response, $previous, $handlerContext);
}
/**
* Obfuscates URI if there is a username and a password present
*/
private static function obfuscateUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$userInfo = $uri->getUserInfo();
if (\false !== ($pos = \strpos($userInfo, ':'))) {
return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***');
}
return $uri;
}
/**
* Get the request that caused the exception
*/
public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
return $this->request;
}
/**
* Get the associated response
*/
public function getResponse() : ?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return $this->response;
}
/**
* Check if a response was received
*/
public function hasResponse() : bool
{
return $this->response !== null;
}
/**
* Get contextual information about the error from the underlying handler.
*
* The contents of this array will vary depending on which handler you are
* using. It may also be just an empty array. Relying on this data will
* couple you to a specific handler, but can give more debug information
* when needed.
*/
public function getHandlerContext() : array
{
return $this->handlerContext;
}
}
vendor_prefixed/guzzlehttp/guzzle/src/HandlerStack.php 0000644 00000021246 14720660247 0017347 0 ustar 00 push(\YoastSEO_Vendor\GuzzleHttp\Middleware::httpErrors(), 'http_errors');
$stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::redirect(), 'allow_redirects');
$stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::cookies(), 'cookies');
$stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::prepareBody(), 'prepare_body');
return $stack;
}
/**
* @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler.
*/
public function __construct(callable $handler = null)
{
$this->handler = $handler;
}
/**
* Invokes the handler stack as a composed handler
*
* @return ResponseInterface|PromiseInterface
*/
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
{
$handler = $this->resolve();
return $handler($request, $options);
}
/**
* Dumps a string representation of the stack.
*
* @return string
*/
public function __toString()
{
$depth = 0;
$stack = [];
if ($this->handler !== null) {
$stack[] = '0) Handler: ' . $this->debugCallable($this->handler);
}
$result = '';
foreach (\array_reverse($this->stack) as $tuple) {
++$depth;
$str = "{$depth}) Name: '{$tuple[1]}', ";
$str .= 'Function: ' . $this->debugCallable($tuple[0]);
$result = "> {$str}\n{$result}";
$stack[] = $str;
}
foreach (\array_keys($stack) as $k) {
$result .= "< {$stack[$k]}\n";
}
return $result;
}
/**
* Set the HTTP handler that actually returns a promise.
*
* @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and
* returns a Promise.
*/
public function setHandler(callable $handler) : void
{
$this->handler = $handler;
$this->cached = null;
}
/**
* Returns true if the builder has a handler.
*/
public function hasHandler() : bool
{
return $this->handler !== null;
}
/**
* Unshift a middleware to the bottom of the stack.
*
* @param callable(callable): callable $middleware Middleware function
* @param string $name Name to register for this middleware.
*/
public function unshift(callable $middleware, string $name = null) : void
{
\array_unshift($this->stack, [$middleware, $name]);
$this->cached = null;
}
/**
* Push a middleware to the top of the stack.
*
* @param callable(callable): callable $middleware Middleware function
* @param string $name Name to register for this middleware.
*/
public function push(callable $middleware, string $name = '') : void
{
$this->stack[] = [$middleware, $name];
$this->cached = null;
}
/**
* Add a middleware before another middleware by name.
*
* @param string $findName Middleware to find
* @param callable(callable): callable $middleware Middleware function
* @param string $withName Name to register for this middleware.
*/
public function before(string $findName, callable $middleware, string $withName = '') : void
{
$this->splice($findName, $withName, $middleware, \true);
}
/**
* Add a middleware after another middleware by name.
*
* @param string $findName Middleware to find
* @param callable(callable): callable $middleware Middleware function
* @param string $withName Name to register for this middleware.
*/
public function after(string $findName, callable $middleware, string $withName = '') : void
{
$this->splice($findName, $withName, $middleware, \false);
}
/**
* Remove a middleware by instance or name from the stack.
*
* @param callable|string $remove Middleware to remove by instance or name.
*/
public function remove($remove) : void
{
if (!\is_string($remove) && !\is_callable($remove)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->cached = null;
$idx = \is_callable($remove) ? 0 : 1;
$this->stack = \array_values(\array_filter($this->stack, static function ($tuple) use($idx, $remove) {
return $tuple[$idx] !== $remove;
}));
}
/**
* Compose the middleware and handler into a single callable function.
*
* @return callable(RequestInterface, array): PromiseInterface
*/
public function resolve() : callable
{
if ($this->cached === null) {
if (($prev = $this->handler) === null) {
throw new \LogicException('No handler has been specified');
}
foreach (\array_reverse($this->stack) as $fn) {
/** @var callable(RequestInterface, array): PromiseInterface $prev */
$prev = $fn[0]($prev);
}
$this->cached = $prev;
}
return $this->cached;
}
private function findByName(string $name) : int
{
foreach ($this->stack as $k => $v) {
if ($v[1] === $name) {
return $k;
}
}
throw new \InvalidArgumentException("Middleware not found: {$name}");
}
/**
* Splices a function into the middleware list at a specific position.
*/
private function splice(string $findName, string $withName, callable $middleware, bool $before) : void
{
$this->cached = null;
$idx = $this->findByName($findName);
$tuple = [$middleware, $withName];
if ($before) {
if ($idx === 0) {
\array_unshift($this->stack, $tuple);
} else {
$replacement = [$tuple, $this->stack[$idx]];
\array_splice($this->stack, $idx, 1, $replacement);
}
} elseif ($idx === \count($this->stack) - 1) {
$this->stack[] = $tuple;
} else {
$replacement = [$this->stack[$idx], $tuple];
\array_splice($this->stack, $idx, 1, $replacement);
}
}
/**
* Provides a debug string for a given callable.
*
* @param callable|string $fn Function to write as a string.
*/
private function debugCallable($fn) : string
{
if (\is_string($fn)) {
return "callable({$fn})";
}
if (\is_array($fn)) {
return \is_string($fn[0]) ? "callable({$fn[0]}::{$fn[1]})" : "callable(['" . \get_class($fn[0]) . "', '{$fn[1]}'])";
}
/** @var object $fn */
return 'callable(' . \spl_object_hash($fn) . ')';
}
}
vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php 0000644 00000006442 14720660247 0017610 0 ustar 00 request = $request;
$this->response = $response;
$this->transferTime = $transferTime;
$this->handlerErrorData = $handlerErrorData;
$this->handlerStats = $handlerStats;
}
public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
return $this->request;
}
/**
* Returns the response that was received (if any).
*/
public function getResponse() : ?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return $this->response;
}
/**
* Returns true if a response was received.
*/
public function hasResponse() : bool
{
return $this->response !== null;
}
/**
* Gets handler specific error data.
*
* This might be an exception, a integer representing an error code, or
* anything else. Relying on this value assumes that you know what handler
* you are using.
*
* @return mixed
*/
public function getHandlerErrorData()
{
return $this->handlerErrorData;
}
/**
* Get the effective URI the request was sent to.
*/
public function getEffectiveUri() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
return $this->request->getUri();
}
/**
* Get the estimated time the request was being transferred by the handler.
*
* @return float|null Time in seconds.
*/
public function getTransferTime() : ?float
{
return $this->transferTime;
}
/**
* Gets an array of all of the handler specific transfer data.
*/
public function getHandlerStats() : array
{
return $this->handlerStats;
}
/**
* Get a specific handler statistic from the handler by name.
*
* @param string $stat Handler specific transfer stat to retrieve.
*
* @return mixed|null
*/
public function getHandlerStat(string $stat)
{
return $this->handlerStats[$stat] ?? null;
}
}
vendor_prefixed/guzzlehttp/guzzle/src/ClientTrait.php 0000644 00000022550 14720660247 0017225 0 ustar 00 request('GET', $uri, $options);
}
/**
* Create and send an HTTP HEAD request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function head($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return $this->request('HEAD', $uri, $options);
}
/**
* Create and send an HTTP PUT request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function put($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return $this->request('PUT', $uri, $options);
}
/**
* Create and send an HTTP POST request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function post($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return $this->request('POST', $uri, $options);
}
/**
* Create and send an HTTP PATCH request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function patch($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return $this->request('PATCH', $uri, $options);
}
/**
* Create and send an HTTP DELETE request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function delete($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return $this->request('DELETE', $uri, $options);
}
/**
* Create and send an asynchronous HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string $method HTTP method
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public abstract function requestAsync(string $method, $uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
/**
* Create and send an asynchronous HTTP GET request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function getAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->requestAsync('GET', $uri, $options);
}
/**
* Create and send an asynchronous HTTP HEAD request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function headAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->requestAsync('HEAD', $uri, $options);
}
/**
* Create and send an asynchronous HTTP PUT request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function putAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->requestAsync('PUT', $uri, $options);
}
/**
* Create and send an asynchronous HTTP POST request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function postAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->requestAsync('POST', $uri, $options);
}
/**
* Create and send an asynchronous HTTP PATCH request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function patchAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->requestAsync('PATCH', $uri, $options);
}
/**
* Create and send an asynchronous HTTP DELETE request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function deleteAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->requestAsync('DELETE', $uri, $options);
}
}
vendor_prefixed/guzzlehttp/guzzle/src/RequestOptions.php 0000644 00000025314 14720660247 0020010 0 ustar 00 5, 'protocols' => ['http', 'https'], 'strict' => \false, 'referer' => \false, 'track_redirects' => \false];
/**
* @var callable(RequestInterface, array): PromiseInterface
*/
private $nextHandler;
/**
* @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke.
*/
public function __construct(callable $nextHandler)
{
$this->nextHandler = $nextHandler;
}
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$fn = $this->nextHandler;
if (empty($options['allow_redirects'])) {
return $fn($request, $options);
}
if ($options['allow_redirects'] === \true) {
$options['allow_redirects'] = self::$defaultSettings;
} elseif (!\is_array($options['allow_redirects'])) {
throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
} else {
// Merge the default settings with the provided settings
$options['allow_redirects'] += self::$defaultSettings;
}
if (empty($options['allow_redirects']['max'])) {
return $fn($request, $options);
}
return $fn($request, $options)->then(function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request, $options) {
return $this->checkRedirect($request, $options, $response);
});
}
/**
* @return ResponseInterface|PromiseInterface
*/
public function checkRedirect(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
{
if (\strpos((string) $response->getStatusCode(), '3') !== 0 || !$response->hasHeader('Location')) {
return $response;
}
$this->guardMax($request, $response, $options);
$nextRequest = $this->modifyRequest($request, $options, $response);
// If authorization is handled by curl, unset it if URI is cross-origin.
if (\YoastSEO_Vendor\GuzzleHttp\Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && \defined('\\CURLOPT_HTTPAUTH')) {
unset($options['curl'][\CURLOPT_HTTPAUTH], $options['curl'][\CURLOPT_USERPWD]);
}
if (isset($options['allow_redirects']['on_redirect'])) {
$options['allow_redirects']['on_redirect']($request, $response, $nextRequest->getUri());
}
$promise = $this($nextRequest, $options);
// Add headers to be able to track history of redirects.
if (!empty($options['allow_redirects']['track_redirects'])) {
return $this->withTracking($promise, (string) $nextRequest->getUri(), $response->getStatusCode());
}
return $promise;
}
/**
* Enable tracking on promise.
*/
private function withTracking(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise, string $uri, int $statusCode) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $promise->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($uri, $statusCode) {
// Note that we are pushing to the front of the list as this
// would be an earlier response than what is currently present
// in the history header.
$historyHeader = $response->getHeader(self::HISTORY_HEADER);
$statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
\array_unshift($historyHeader, $uri);
\array_unshift($statusHeader, (string) $statusCode);
return $response->withHeader(self::HISTORY_HEADER, $historyHeader)->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
});
}
/**
* Check for too many redirects.
*
* @throws TooManyRedirectsException Too many redirects.
*/
private function guardMax(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array &$options) : void
{
$current = $options['__redirect_count'] ?? 0;
$options['__redirect_count'] = $current + 1;
$max = $options['allow_redirects']['max'];
if ($options['__redirect_count'] > $max) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\TooManyRedirectsException("Will not follow more than {$max} redirects", $request, $response);
}
}
public function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
// Request modifications to apply.
$modify = [];
$protocols = $options['allow_redirects']['protocols'];
// Use a GET request if this is an entity enclosing request and we are
// not forcing RFC compliance, but rather emulating what all browsers
// would do.
$statusCode = $response->getStatusCode();
if ($statusCode == 303 || $statusCode <= 302 && !$options['allow_redirects']['strict']) {
$safeMethods = ['GET', 'HEAD', 'OPTIONS'];
$requestMethod = $request->getMethod();
$modify['method'] = \in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET';
$modify['body'] = '';
}
$uri = self::redirectUri($request, $response, $protocols);
if (isset($options['idn_conversion']) && $options['idn_conversion'] !== \false) {
$idnOptions = $options['idn_conversion'] === \true ? \IDNA_DEFAULT : $options['idn_conversion'];
$uri = \YoastSEO_Vendor\GuzzleHttp\Utils::idnUriConvert($uri, $idnOptions);
}
$modify['uri'] = $uri;
\YoastSEO_Vendor\GuzzleHttp\Psr7\Message::rewindBody($request);
// Add the Referer header if it is told to do so and only
// add the header if we are not redirecting from https to http.
if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme()) {
$uri = $request->getUri()->withUserInfo('');
$modify['set_headers']['Referer'] = (string) $uri;
} else {
$modify['remove_headers'][] = 'Referer';
}
// Remove Authorization and Cookie headers if URI is cross-origin.
if (\YoastSEO_Vendor\GuzzleHttp\Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) {
$modify['remove_headers'][] = 'Authorization';
$modify['remove_headers'][] = 'Cookie';
}
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify);
}
/**
* Set the appropriate URL on the request based on the location header.
*/
private static function redirectUri(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array $protocols) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$location = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($request->getUri(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($response->getHeaderLine('Location')));
// Ensure that the redirect URI is allowed based on the protocols.
if (!\in_array($location->getScheme(), $protocols)) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response);
}
return $location;
}
}
vendor_prefixed/guzzlehttp/guzzle/src/BodySummarizer.php 0000644 00000001333 14720660247 0017753 0 ustar 00 truncateAt = $truncateAt;
}
/**
* Returns a summarized message body.
*/
public function summarize(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : ?string
{
return $this->truncateAt === null ? \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::bodySummary($message) : \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt);
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Utils.php 0000644 00000032615 14720660247 0016106 0 ustar 00 getHost()) {
$asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
if ($asciiHost === \false) {
$errorBitSet = $info['errors'] ?? 0;
$errorConstants = \array_filter(\array_keys(\get_defined_constants()), static function (string $name) : bool {
return \substr($name, 0, 11) === 'IDNA_ERROR_';
});
$errors = [];
foreach ($errorConstants as $errorConstant) {
if ($errorBitSet & \constant($errorConstant)) {
$errors[] = $errorConstant;
}
}
$errorMessage = 'IDN conversion failed';
if ($errors) {
$errorMessage .= ' (errors: ' . \implode(', ', $errors) . ')';
}
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException($errorMessage);
}
if ($uri->getHost() !== $asciiHost) {
// Replace URI only if the ASCII version is different
$uri = $uri->withHost($asciiHost);
}
}
return $uri;
}
/**
* @internal
*/
public static function getenv(string $name) : ?string
{
if (isset($_SERVER[$name])) {
return (string) $_SERVER[$name];
}
if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== \false && $value !== null) {
return (string) $value;
}
return null;
}
/**
* @return string|false
*/
private static function idnToAsci(string $domain, int $options, ?array &$info = [])
{
if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) {
return \idn_to_ascii($domain, $options, \INTL_IDNA_VARIANT_UTS46, $info);
}
throw new \Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old');
}
}
vendor_prefixed/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php 0000644 00000006376 14720660247 0021225 0 ustar 00 nextHandler = $nextHandler;
}
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$fn = $this->nextHandler;
// Don't do anything if the request has no body.
if ($request->getBody()->getSize() === 0) {
return $fn($request, $options);
}
$modify = [];
// Add a default content-type if possible.
if (!$request->hasHeader('Content-Type')) {
if ($uri = $request->getBody()->getMetadata('uri')) {
if (\is_string($uri) && ($type = \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($uri))) {
$modify['set_headers']['Content-Type'] = $type;
}
}
}
// Add a default content-length or transfer-encoding header.
if (!$request->hasHeader('Content-Length') && !$request->hasHeader('Transfer-Encoding')) {
$size = $request->getBody()->getSize();
if ($size !== null) {
$modify['set_headers']['Content-Length'] = $size;
} else {
$modify['set_headers']['Transfer-Encoding'] = 'chunked';
}
}
// Add the expect header if needed.
$this->addExpectHeader($request, $options, $modify);
return $fn(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify), $options);
}
/**
* Add expect header
*/
private function addExpectHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$modify) : void
{
// Determine if the Expect header should be used
if ($request->hasHeader('Expect')) {
return;
}
$expect = $options['expect'] ?? null;
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
if ($expect === \false || $request->getProtocolVersion() < 1.1) {
return;
}
// The expect header is unconditionally enabled
if ($expect === \true) {
$modify['set_headers']['Expect'] = '100-Continue';
return;
}
// By default, send the expect header when the payload is > 1mb
if ($expect === null) {
$expect = 1048576;
}
// Always add if the body cannot be rewound, the size cannot be
// determined, or the size is greater than the cutoff threshold
$body = $request->getBody();
$size = $body->getSize();
if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
$modify['set_headers']['Expect'] = '100-Continue';
}
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Handler/EasyHandle.php 0000644 00000005703 14720660247 0020376 0 ustar 00 headers);
$normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\Utils::normalizeHeaderKeys($headers);
if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) {
$headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
unset($headers[$normalizedKeys['content-encoding']]);
if (isset($normalizedKeys['content-length'])) {
$headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
$bodyLength = (int) $this->sink->getSize();
if ($bodyLength) {
$headers[$normalizedKeys['content-length']] = $bodyLength;
} else {
unset($headers[$normalizedKeys['content-length']]);
}
}
}
// Attach a response to the easy handle with the parsed headers.
$this->response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $this->sink, $ver, $reason);
}
/**
* @param string $name
*
* @return void
*
* @throws \BadMethodCallException
*/
public function __get($name)
{
$msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name;
throw new \BadMethodCallException($msg);
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php 0000644 00000002127 14720660247 0021446 0 ustar 00 withoutHeader('Expect');
// Append a content-length header if body size is zero to match
// cURL's behavior.
if (0 === $request->getBody()->getSize()) {
$request = $request->withHeader('Content-Length', '0');
}
return $this->createResponse($request, $options, $this->createStream($request, $options), $startTime);
} catch (\InvalidArgumentException $e) {
throw $e;
} catch (\Exception $e) {
// Determine if the error was a networking error.
$message = $e->getMessage();
// This list can probably get more comprehensive.
if (\false !== \strpos($message, 'getaddrinfo') || \false !== \strpos($message, 'Connection refused') || \false !== \strpos($message, "couldn't connect to host") || \false !== \strpos($message, 'connection attempt failed')) {
$e = new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($e->getMessage(), $request, $e);
} else {
$e = \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::wrapException($request, $e);
}
$this->invokeStats($options, $request, $startTime, null, $e);
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($e);
}
}
private function invokeStats(array $options, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, ?float $startTime, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $error = null) : void
{
if (isset($options['on_stats'])) {
$stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime() - $startTime, $error, []);
$options['on_stats']($stats);
}
}
/**
* @param resource $stream
*/
private function createResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, $stream, ?float $startTime) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$hdrs = $this->lastHeaders;
$this->lastHeaders = [];
try {
[$ver, $status, $reason, $headers] = \YoastSEO_Vendor\GuzzleHttp\Handler\HeaderProcessor::parseHeaders($hdrs);
} catch (\Exception $e) {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $request, null, $e));
}
[$stream, $headers] = $this->checkDecode($options, $headers, $stream);
$stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($stream);
$sink = $stream;
if (\strcasecmp('HEAD', $request->getMethod())) {
$sink = $this->createSink($stream, $options);
}
try {
$response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $sink, $ver, $reason);
} catch (\Exception $e) {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $request, null, $e));
}
if (isset($options['on_headers'])) {
try {
$options['on_headers']($response);
} catch (\Exception $e) {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $request, $response, $e));
}
}
// Do not drain when the request is a HEAD request because they have
// no body.
if ($sink !== $stream) {
$this->drain($stream, $sink, $response->getHeaderLine('Content-Length'));
}
$this->invokeStats($options, $request, $startTime, $response, null);
return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($response);
}
private function createSink(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $options) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
if (!empty($options['stream'])) {
return $stream;
}
$sink = $options['sink'] ?? \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'r+');
return \is_string($sink) ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+') : \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
}
/**
* @param resource $stream
*/
private function checkDecode(array $options, array $headers, $stream) : array
{
// Automatically decode responses when instructed.
if (!empty($options['decode_content'])) {
$normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\Utils::normalizeHeaderKeys($headers);
if (isset($normalizedKeys['content-encoding'])) {
$encoding = $headers[$normalizedKeys['content-encoding']];
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
$stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\InflateStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($stream));
$headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
// Remove content-encoding header
unset($headers[$normalizedKeys['content-encoding']]);
// Fix content-length header
if (isset($normalizedKeys['content-length'])) {
$headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
$length = (int) $stream->getSize();
if ($length === 0) {
unset($headers[$normalizedKeys['content-length']]);
} else {
$headers[$normalizedKeys['content-length']] = [$length];
}
}
}
}
}
return [$stream, $headers];
}
/**
* Drains the source stream into the "sink" client option.
*
* @param string $contentLength Header specifying the amount of
* data to read.
*
* @throws \RuntimeException when the sink option is invalid.
*/
private function drain(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $sink, string $contentLength) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
// If a content-length header is provided, then stop reading once
// that number of bytes has been read. This can prevent infinitely
// reading from a stream when dealing with servers that do not honor
// Connection: Close headers.
\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($source, $sink, \strlen($contentLength) > 0 && (int) $contentLength > 0 ? (int) $contentLength : -1);
$sink->seek(0);
$source->close();
return $sink;
}
/**
* Create a resource and check to ensure it was created successfully
*
* @param callable $callback Callable that returns stream resource
*
* @return resource
*
* @throws \RuntimeException on error
*/
private function createResource(callable $callback)
{
$errors = [];
\set_error_handler(static function ($_, $msg, $file, $line) use(&$errors) : bool {
$errors[] = ['message' => $msg, 'file' => $file, 'line' => $line];
return \true;
});
try {
$resource = $callback();
} finally {
\restore_error_handler();
}
if (!$resource) {
$message = 'Error creating resource: ';
foreach ($errors as $err) {
foreach ($err as $key => $value) {
$message .= "[{$key}] {$value}" . \PHP_EOL;
}
}
throw new \RuntimeException(\trim($message));
}
return $resource;
}
/**
* @return resource
*/
private function createStream(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
{
static $methods;
if (!$methods) {
$methods = \array_flip(\get_class_methods(__CLASS__));
}
if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request);
}
// HTTP/1.1 streams using the PHP stream wrapper require a
// Connection: close header
if ($request->getProtocolVersion() == '1.1' && !$request->hasHeader('Connection')) {
$request = $request->withHeader('Connection', 'close');
}
// Ensure SSL is verified by default
if (!isset($options['verify'])) {
$options['verify'] = \true;
}
$params = [];
$context = $this->getDefaultContext($request);
if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) {
throw new \InvalidArgumentException('on_headers must be callable');
}
if (!empty($options)) {
foreach ($options as $key => $value) {
$method = "add_{$key}";
if (isset($methods[$method])) {
$this->{$method}($request, $context, $value, $params);
}
}
}
if (isset($options['stream_context'])) {
if (!\is_array($options['stream_context'])) {
throw new \InvalidArgumentException('stream_context must be an array');
}
$context = \array_replace_recursive($context, $options['stream_context']);
}
// Microsoft NTLM authentication only supported with curl handler
if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) {
throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
}
$uri = $this->resolveHost($request, $options);
$contextResource = $this->createResource(static function () use($context, $params) {
return \stream_context_create($context, $params);
});
return $this->createResource(function () use($uri, &$http_response_header, $contextResource, $context, $options, $request) {
$resource = @\fopen((string) $uri, 'r', \false, $contextResource);
$this->lastHeaders = $http_response_header ?? [];
if (\false === $resource) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf('Connection refused for URI %s', $uri), $request, null, $context);
}
if (isset($options['read_timeout'])) {
$readTimeout = $options['read_timeout'];
$sec = (int) $readTimeout;
$usec = ($readTimeout - $sec) * 100000;
\stream_set_timeout($resource, $sec, $usec);
}
return $resource;
});
}
private function resolveHost(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$uri = $request->getUri();
if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) {
if ('v4' === $options['force_ip_resolve']) {
$records = \dns_get_record($uri->getHost(), \DNS_A);
if (\false === $records || !isset($records[0]['ip'])) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
}
return $uri->withHost($records[0]['ip']);
}
if ('v6' === $options['force_ip_resolve']) {
$records = \dns_get_record($uri->getHost(), \DNS_AAAA);
if (\false === $records || !isset($records[0]['ipv6'])) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
}
return $uri->withHost('[' . $records[0]['ipv6'] . ']');
}
}
return $uri;
}
private function getDefaultContext(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : array
{
$headers = '';
foreach ($request->getHeaders() as $name => $value) {
foreach ($value as $val) {
$headers .= "{$name}: {$val}\r\n";
}
}
$context = ['http' => ['method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => \true, 'follow_location' => 0], 'ssl' => ['peer_name' => $request->getUri()->getHost()]];
$body = (string) $request->getBody();
if ('' !== $body) {
$context['http']['content'] = $body;
// Prevent the HTTP handler from adding a Content-Type header.
if (!$request->hasHeader('Content-Type')) {
$context['http']['header'] .= "Content-Type:\r\n";
}
}
$context['http']['header'] = \rtrim($context['http']['header']);
return $context;
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_proxy(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
{
$uri = null;
if (!\is_array($value)) {
$uri = $value;
} else {
$scheme = $request->getUri()->getScheme();
if (isset($value[$scheme])) {
if (!isset($value['no']) || !\YoastSEO_Vendor\GuzzleHttp\Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) {
$uri = $value[$scheme];
}
}
}
if (!$uri) {
return;
}
$parsed = $this->parse_proxy($uri);
$options['http']['proxy'] = $parsed['proxy'];
if ($parsed['auth']) {
if (!isset($options['http']['header'])) {
$options['http']['header'] = [];
}
$options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}";
}
}
/**
* Parses the given proxy URL to make it compatible with the format PHP's stream context expects.
*/
private function parse_proxy(string $url) : array
{
$parsed = \parse_url($url);
if ($parsed !== \false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') {
if (isset($parsed['host']) && isset($parsed['port'])) {
$auth = null;
if (isset($parsed['user']) && isset($parsed['pass'])) {
$auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}");
}
return ['proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth ? "Basic {$auth}" : null];
}
}
// Return proxy as-is.
return ['proxy' => $url, 'auth' => null];
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_timeout(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
{
if ($value > 0) {
$options['http']['timeout'] = $value;
}
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_crypto_method(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
{
if ($value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT || \defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) {
$options['http']['crypto_method'] = $value;
return;
}
throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_verify(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
{
if ($value === \false) {
$options['ssl']['verify_peer'] = \false;
$options['ssl']['verify_peer_name'] = \false;
return;
}
if (\is_string($value)) {
$options['ssl']['cafile'] = $value;
if (!\file_exists($value)) {
throw new \RuntimeException("SSL CA bundle not found: {$value}");
}
} elseif ($value !== \true) {
throw new \InvalidArgumentException('Invalid verify request option');
}
$options['ssl']['verify_peer'] = \true;
$options['ssl']['verify_peer_name'] = \true;
$options['ssl']['allow_self_signed'] = \false;
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_cert(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
{
if (\is_array($value)) {
$options['ssl']['passphrase'] = $value[1];
$value = $value[0];
}
if (!\file_exists($value)) {
throw new \RuntimeException("SSL certificate not found: {$value}");
}
$options['ssl']['local_cert'] = $value;
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_progress(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
{
self::addNotification($params, static function ($code, $a, $b, $c, $transferred, $total) use($value) {
if ($code == \STREAM_NOTIFY_PROGRESS) {
// The upload progress cannot be determined. Use 0 for cURL compatibility:
// https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
$value($total, $transferred, 0, 0);
}
});
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_debug(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
{
if ($value === \false) {
return;
}
static $map = [\STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE'];
static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
$value = \YoastSEO_Vendor\GuzzleHttp\Utils::debugResource($value);
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
self::addNotification($params, static function (int $code, ...$passed) use($ident, $value, $map, $args) : void {
\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
foreach (\array_filter($passed) as $i => $v) {
\fwrite($value, $args[$i] . ': "' . $v . '" ');
}
\fwrite($value, "\n");
});
}
private static function addNotification(array &$params, callable $notify) : void
{
// Wrap the existing function if needed.
if (!isset($params['notification'])) {
$params['notification'] = $notify;
} else {
$params['notification'] = self::callArray([$params['notification'], $notify]);
}
}
private static function callArray(array $functions) : callable
{
return static function (...$args) use($functions) {
foreach ($functions as $fn) {
$fn(...$args);
}
};
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Handler/MockHandler.php 0000644 00000015330 14720660247 0020545 0 ustar 00 |null $queue The parameters to be passed to the append function, as an indexed array.
* @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
* @param callable|null $onRejected Callback to invoke when the return value is rejected.
*/
public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null)
{
$this->onFulfilled = $onFulfilled;
$this->onRejected = $onRejected;
if ($queue) {
// array_values included for BC
$this->append(...\array_values($queue));
}
}
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
if (!$this->queue) {
throw new \OutOfBoundsException('Mock queue is empty');
}
if (isset($options['delay']) && \is_numeric($options['delay'])) {
\usleep((int) $options['delay'] * 1000);
}
$this->lastRequest = $request;
$this->lastOptions = $options;
$response = \array_shift($this->queue);
if (isset($options['on_headers'])) {
if (!\is_callable($options['on_headers'])) {
throw new \InvalidArgumentException('on_headers must be callable');
}
try {
$options['on_headers']($response);
} catch (\Exception $e) {
$msg = 'An error was encountered during the on_headers event';
$response = new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($msg, $request, $response, $e);
}
}
if (\is_callable($response)) {
$response = $response($request, $options);
}
$response = $response instanceof \Throwable ? \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($response) : \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($response);
return $response->then(function (?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $value) use($request, $options) {
$this->invokeStats($request, $options, $value);
if ($this->onFulfilled) {
($this->onFulfilled)($value);
}
if ($value !== null && isset($options['sink'])) {
$contents = (string) $value->getBody();
$sink = $options['sink'];
if (\is_resource($sink)) {
\fwrite($sink, $contents);
} elseif (\is_string($sink)) {
\file_put_contents($sink, $contents);
} elseif ($sink instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) {
$sink->write($contents);
}
}
return $value;
}, function ($reason) use($request, $options) {
$this->invokeStats($request, $options, null, $reason);
if ($this->onRejected) {
($this->onRejected)($reason);
}
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
});
}
/**
* Adds one or more variadic requests, exceptions, callables, or promises
* to the queue.
*
* @param mixed ...$values
*/
public function append(...$values) : void
{
foreach ($values as $value) {
if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface || $value instanceof \Throwable || $value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface || \is_callable($value)) {
$this->queue[] = $value;
} else {
throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found ' . \YoastSEO_Vendor\GuzzleHttp\Utils::describeType($value));
}
}
}
/**
* Get the last received request.
*/
public function getLastRequest() : ?\YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
return $this->lastRequest;
}
/**
* Get the last received request options.
*/
public function getLastOptions() : array
{
return $this->lastOptions;
}
/**
* Returns the number of remaining items in the queue.
*/
public function count() : int
{
return \count($this->queue);
}
public function reset() : void
{
$this->queue = [];
}
/**
* @param mixed $reason Promise or reason.
*/
private function invokeStats(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $reason = null) : void
{
if (isset($options['on_stats'])) {
$transferTime = $options['transfer_time'] ?? 0;
$stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, $transferTime, $reason);
$options['on_stats']($stats);
}
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlHandler.php 0000644 00000002740 14720660247 0020562 0 ustar 00 factory = $options['handle_factory'] ?? new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(3);
}
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
if (isset($options['delay'])) {
\usleep($options['delay'] * 1000);
}
$easy = $this->factory->create($request, $options);
\curl_exec($easy->handle);
$easy->errno = \curl_errno($easy->handle);
return \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory::finish($this, $easy, $this->factory);
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php 0000644 00000020160 14720660247 0021571 0 ustar 00 An array of delay times, indexed by handle id in `addRequest`.
*
* @see CurlMultiHandler::addRequest
*/
private $delays = [];
/**
* @var array An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt()
*/
private $options = [];
/** @var resource|\CurlMultiHandle */
private $_mh;
/**
* This handler accepts the following options:
*
* - handle_factory: An optional factory used to create curl handles
* - select_timeout: Optional timeout (in seconds) to block before timing
* out while selecting curl handles. Defaults to 1 second.
* - options: An associative array of CURLMOPT_* options and
* corresponding values for curl_multi_setopt()
*/
public function __construct(array $options = [])
{
$this->factory = $options['handle_factory'] ?? new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(50);
if (isset($options['select_timeout'])) {
$this->selectTimeout = $options['select_timeout'];
} elseif ($selectTimeout = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
@\trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED);
$this->selectTimeout = (int) $selectTimeout;
} else {
$this->selectTimeout = 1;
}
$this->options = $options['options'] ?? [];
// unsetting the property forces the first access to go through
// __get().
unset($this->_mh);
}
/**
* @param string $name
*
* @return resource|\CurlMultiHandle
*
* @throws \BadMethodCallException when another field as `_mh` will be gotten
* @throws \RuntimeException when curl can not initialize a multi handle
*/
public function __get($name)
{
if ($name !== '_mh') {
throw new \BadMethodCallException("Can not get other property as '_mh'.");
}
$multiHandle = \curl_multi_init();
if (\false === $multiHandle) {
throw new \RuntimeException('Can not initialize curl multi handle.');
}
$this->_mh = $multiHandle;
foreach ($this->options as $option => $value) {
// A warning is raised in case of a wrong option.
\curl_multi_setopt($this->_mh, $option, $value);
}
return $this->_mh;
}
public function __destruct()
{
if (isset($this->_mh)) {
\curl_multi_close($this->_mh);
unset($this->_mh);
}
}
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$easy = $this->factory->create($request, $options);
$id = (int) $easy->handle;
$promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$this, 'execute'], function () use($id) {
return $this->cancel($id);
});
$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
return $promise;
}
/**
* Ticks the curl event loop.
*/
public function tick() : void
{
// Add any delayed handles if needed.
if ($this->delays) {
$currentTime = \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime();
foreach ($this->delays as $id => $delay) {
if ($currentTime >= $delay) {
unset($this->delays[$id]);
\curl_multi_add_handle($this->_mh, $this->handles[$id]['easy']->handle);
}
}
}
// Step through the task queue which may add additional requests.
\YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->run();
if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) {
// Perform a usleep if a select returns -1.
// See: https://bugs.php.net/bug.php?id=61141
\usleep(250);
}
while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
}
$this->processMessages();
}
/**
* Runs until all outstanding connections have completed.
*/
public function execute() : void
{
$queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue();
while ($this->handles || !$queue->isEmpty()) {
// If there are no transfers, then sleep for the next delay
if (!$this->active && $this->delays) {
\usleep($this->timeToNext());
}
$this->tick();
}
}
private function addRequest(array $entry) : void
{
$easy = $entry['easy'];
$id = (int) $easy->handle;
$this->handles[$id] = $entry;
if (empty($easy->options['delay'])) {
\curl_multi_add_handle($this->_mh, $easy->handle);
} else {
$this->delays[$id] = \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime() + $easy->options['delay'] / 1000;
}
}
/**
* Cancels a handle from sending and removes references to it.
*
* @param int $id Handle ID to cancel and remove.
*
* @return bool True on success, false on failure.
*/
private function cancel($id) : bool
{
if (!\is_int($id)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
// Cannot cancel if it has been processed.
if (!isset($this->handles[$id])) {
return \false;
}
$handle = $this->handles[$id]['easy']->handle;
unset($this->delays[$id], $this->handles[$id]);
\curl_multi_remove_handle($this->_mh, $handle);
\curl_close($handle);
return \true;
}
private function processMessages() : void
{
while ($done = \curl_multi_info_read($this->_mh)) {
if ($done['msg'] !== \CURLMSG_DONE) {
// if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216
continue;
}
$id = (int) $done['handle'];
\curl_multi_remove_handle($this->_mh, $done['handle']);
if (!isset($this->handles[$id])) {
// Probably was cancelled.
continue;
}
$entry = $this->handles[$id];
unset($this->handles[$id], $this->delays[$id]);
$entry['easy']->errno = $done['result'];
$entry['deferred']->resolve(\YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory::finish($this, $entry['easy'], $this->factory));
}
}
private function timeToNext() : int
{
$currentTime = \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime();
$nextTime = \PHP_INT_MAX;
foreach ($this->delays as $time) {
if ($time < $nextTime) {
$nextTime = $time;
}
}
return (int) \max(0, $nextTime - $currentTime) * 1000000;
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Handler/Proxy.php 0000644 00000004616 14720660247 0017504 0 ustar 00 maxHandles = $maxHandles;
}
public function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle
{
if (isset($options['curl']['body_as_string'])) {
$options['_body_as_string'] = $options['curl']['body_as_string'];
unset($options['curl']['body_as_string']);
}
$easy = new \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle();
$easy->request = $request;
$easy->options = $options;
$conf = $this->getDefaultConf($easy);
$this->applyMethod($easy, $conf);
$this->applyHandlerOptions($easy, $conf);
$this->applyHeaders($easy, $conf);
unset($conf['_headers']);
// Add handler options from the request configuration options
if (isset($options['curl'])) {
$conf = \array_replace($conf, $options['curl']);
}
$conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
$easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init();
\curl_setopt_array($easy->handle, $conf);
return $easy;
}
public function release(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : void
{
$resource = $easy->handle;
unset($easy->handle);
if (\count($this->handles) >= $this->maxHandles) {
\curl_close($resource);
} else {
// Remove all callback functions as they can hold onto references
// and are not cleaned up by curl_reset. Using curl_setopt_array
// does not work for some reason, so removing each one
// individually.
\curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null);
\curl_setopt($resource, \CURLOPT_READFUNCTION, null);
\curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null);
\curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null);
\curl_reset($resource);
$this->handles[] = $resource;
}
}
/**
* Completes a cURL transaction, either returning a response promise or a
* rejected promise.
*
* @param callable(RequestInterface, array): PromiseInterface $handler
* @param CurlFactoryInterface $factory Dictates how the handle is released
*/
public static function finish(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
if (isset($easy->options['on_stats'])) {
self::invokeStats($easy);
}
if (!$easy->response || $easy->errno) {
return self::finishError($handler, $easy, $factory);
}
// Return the response if it is present and there is no error.
$factory->release($easy);
// Rewind the body of the response if possible.
$body = $easy->response->getBody();
if ($body->isSeekable()) {
$body->rewind();
}
return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($easy->response);
}
private static function invokeStats(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : void
{
$curlStats = \curl_getinfo($easy->handle);
$curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME);
$stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats);
$easy->options['on_stats']($stats);
}
/**
* @param callable(RequestInterface, array): PromiseInterface $handler
*/
private static function finishError(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
// Get error information and release the handle to the factory.
$ctx = ['errno' => $easy->errno, 'error' => \curl_error($easy->handle), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME)] + \curl_getinfo($easy->handle);
$ctx[self::CURL_VERSION_STR] = \curl_version()['version'];
$factory->release($easy);
// Retry when nothing is present or when curl failed to rewind.
if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) {
return self::retryFailedRewind($handler, $easy, $ctx);
}
return self::createRejection($easy, $ctx);
}
private static function createRejection(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
static $connectionErrors = [\CURLE_OPERATION_TIMEOUTED => \true, \CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true];
if ($easy->createResponseException) {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $easy->request, $easy->response, $easy->createResponseException, $ctx));
}
// If an exception was encountered during the onHeaders event, then
// return a rejected promise that wraps that exception.
if ($easy->onHeadersException) {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx));
}
$message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $ctx['error'], 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html');
$uriString = (string) $easy->request->getUri();
if ($uriString !== '' && \false === \strpos($ctx['error'], $uriString)) {
$message .= \sprintf(' for %s', $uriString);
}
// Create a connection exception if it was a specific error code.
$error = isset($connectionErrors[$easy->errno]) ? new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($message, $easy->request, null, $ctx) : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($message, $easy->request, $easy->response, null, $ctx);
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($error);
}
/**
* @return array
*/
private function getDefaultConf(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : array
{
$conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 300];
if (\defined('CURLOPT_PROTOCOLS')) {
$conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
}
$version = $easy->request->getProtocolVersion();
if ($version == 1.1) {
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
} elseif ($version == 2.0) {
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
} else {
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
}
return $conf;
}
private function applyMethod(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void
{
$body = $easy->request->getBody();
$size = $body->getSize();
if ($size === null || $size > 0) {
$this->applyBody($easy->request, $easy->options, $conf);
return;
}
$method = $easy->request->getMethod();
if ($method === 'PUT' || $method === 'POST') {
// See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
if (!$easy->request->hasHeader('Content-Length')) {
$conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
}
} elseif ($method === 'HEAD') {
$conf[\CURLOPT_NOBODY] = \true;
unset($conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE]);
}
}
private function applyBody(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$conf) : void
{
$size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null;
// Send the body as a string if the size is less than 1MB OR if the
// [curl][body_as_string] request value is set.
if ($size !== null && $size < 1000000 || !empty($options['_body_as_string'])) {
$conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody();
// Don't duplicate the Content-Length header
$this->removeHeader('Content-Length', $conf);
$this->removeHeader('Transfer-Encoding', $conf);
} else {
$conf[\CURLOPT_UPLOAD] = \true;
if ($size !== null) {
$conf[\CURLOPT_INFILESIZE] = $size;
$this->removeHeader('Content-Length', $conf);
}
$body = $request->getBody();
if ($body->isSeekable()) {
$body->rewind();
}
$conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use($body) {
return $body->read($length);
};
}
// If the Expect header is not present, prevent curl from adding it
if (!$request->hasHeader('Expect')) {
$conf[\CURLOPT_HTTPHEADER][] = 'Expect:';
}
// cURL sometimes adds a content-type by default. Prevent this.
if (!$request->hasHeader('Content-Type')) {
$conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:';
}
}
private function applyHeaders(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void
{
foreach ($conf['_headers'] as $name => $values) {
foreach ($values as $value) {
$value = (string) $value;
if ($value === '') {
// cURL requires a special format for empty headers.
// See https://github.com/guzzle/guzzle/issues/1882 for more details.
$conf[\CURLOPT_HTTPHEADER][] = "{$name};";
} else {
$conf[\CURLOPT_HTTPHEADER][] = "{$name}: {$value}";
}
}
}
// Remove the Accept header if one was not set
if (!$easy->request->hasHeader('Accept')) {
$conf[\CURLOPT_HTTPHEADER][] = 'Accept:';
}
}
/**
* Remove a header from the options array.
*
* @param string $name Case-insensitive header to remove
* @param array $options Array of options to modify
*/
private function removeHeader(string $name, array &$options) : void
{
foreach (\array_keys($options['_headers']) as $key) {
if (!\strcasecmp($key, $name)) {
unset($options['_headers'][$key]);
return;
}
}
}
private function applyHandlerOptions(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void
{
$options = $easy->options;
if (isset($options['verify'])) {
if ($options['verify'] === \false) {
unset($conf[\CURLOPT_CAINFO]);
$conf[\CURLOPT_SSL_VERIFYHOST] = 0;
$conf[\CURLOPT_SSL_VERIFYPEER] = \false;
} else {
$conf[\CURLOPT_SSL_VERIFYHOST] = 2;
$conf[\CURLOPT_SSL_VERIFYPEER] = \true;
if (\is_string($options['verify'])) {
// Throw an error if the file/folder/link path is not valid or doesn't exist.
if (!\file_exists($options['verify'])) {
throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}");
}
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
if (\is_dir($options['verify']) || \is_link($options['verify']) === \true && ($verifyLink = \readlink($options['verify'])) !== \false && \is_dir($verifyLink)) {
$conf[\CURLOPT_CAPATH] = $options['verify'];
} else {
$conf[\CURLOPT_CAINFO] = $options['verify'];
}
}
}
}
if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) {
$accept = $easy->request->getHeaderLine('Accept-Encoding');
if ($accept) {
$conf[\CURLOPT_ENCODING] = $accept;
} else {
// The empty string enables all available decoders and implicitly
// sets a matching 'Accept-Encoding' header.
$conf[\CURLOPT_ENCODING] = '';
// But as the user did not specify any acceptable encodings we need
// to overwrite this implicit header with an empty one.
$conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
}
}
if (!isset($options['sink'])) {
// Use a default temp stream if no sink was set.
$options['sink'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+');
}
$sink = $options['sink'];
if (!\is_string($sink)) {
$sink = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
} elseif (!\is_dir(\dirname($sink))) {
// Ensure that the directory exists before failing in curl.
throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink));
} else {
$sink = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+');
}
$easy->sink = $sink;
$conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use($sink) : int {
return $sink->write($write);
};
$timeoutRequiresNoSignal = \false;
if (isset($options['timeout'])) {
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
$conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
}
// CURL default value is CURL_IPRESOLVE_WHATEVER
if (isset($options['force_ip_resolve'])) {
if ('v4' === $options['force_ip_resolve']) {
$conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4;
} elseif ('v6' === $options['force_ip_resolve']) {
$conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6;
}
}
if (isset($options['connect_timeout'])) {
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
$conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
}
if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') {
$conf[\CURLOPT_NOSIGNAL] = \true;
}
if (isset($options['proxy'])) {
if (!\is_array($options['proxy'])) {
$conf[\CURLOPT_PROXY] = $options['proxy'];
} else {
$scheme = $easy->request->getUri()->getScheme();
if (isset($options['proxy'][$scheme])) {
$host = $easy->request->getUri()->getHost();
if (isset($options['proxy']['no']) && \YoastSEO_Vendor\GuzzleHttp\Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
unset($conf[\CURLOPT_PROXY]);
} else {
$conf[\CURLOPT_PROXY] = $options['proxy'][$scheme];
}
}
}
}
if (isset($options['crypto_method'])) {
if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
if (!\defined('CURL_SSLVERSION_TLSv1_0')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
if (!\defined('CURL_SSLVERSION_TLSv1_1')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
if (!\defined('CURL_SSLVERSION_TLSv1_2')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
} elseif (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
if (!\defined('CURL_SSLVERSION_TLSv1_3')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
} else {
throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
}
}
if (isset($options['cert'])) {
$cert = $options['cert'];
if (\is_array($cert)) {
$conf[\CURLOPT_SSLCERTPASSWD] = $cert[1];
$cert = $cert[0];
}
if (!\file_exists($cert)) {
throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
}
// OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
// see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
$ext = \pathinfo($cert, \PATHINFO_EXTENSION);
if (\preg_match('#^(der|p12)$#i', $ext)) {
$conf[\CURLOPT_SSLCERTTYPE] = \strtoupper($ext);
}
$conf[\CURLOPT_SSLCERT] = $cert;
}
if (isset($options['ssl_key'])) {
if (\is_array($options['ssl_key'])) {
if (\count($options['ssl_key']) === 2) {
[$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key'];
} else {
[$sslKey] = $options['ssl_key'];
}
}
$sslKey = $sslKey ?? $options['ssl_key'];
if (!\file_exists($sslKey)) {
throw new \InvalidArgumentException("SSL private key not found: {$sslKey}");
}
$conf[\CURLOPT_SSLKEY] = $sslKey;
}
if (isset($options['progress'])) {
$progress = $options['progress'];
if (!\is_callable($progress)) {
throw new \InvalidArgumentException('progress client option must be callable');
}
$conf[\CURLOPT_NOPROGRESS] = \false;
$conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use($progress) {
$progress($downloadSize, $downloaded, $uploadSize, $uploaded);
};
}
if (!empty($options['debug'])) {
$conf[\CURLOPT_STDERR] = \YoastSEO_Vendor\GuzzleHttp\Utils::debugResource($options['debug']);
$conf[\CURLOPT_VERBOSE] = \true;
}
}
/**
* This function ensures that a response was set on a transaction. If one
* was not set, then the request is retried if possible. This error
* typically means you are sending a payload, curl encountered a
* "Connection died, retrying a fresh connect" error, tried to rewind the
* stream, and then encountered a "necessary data rewind wasn't possible"
* error, causing the request to be sent through curl_multi_info_read()
* without an error status.
*
* @param callable(RequestInterface, array): PromiseInterface $handler
*/
private static function retryFailedRewind(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
try {
// Only rewind if the body has been read from.
$body = $easy->request->getBody();
if ($body->tell() > 0) {
$body->rewind();
}
} catch (\RuntimeException $e) {
$ctx['error'] = 'The connection unexpectedly failed without ' . 'providing an error. The request would have been retried, ' . 'but attempting to rewind the request body failed. ' . 'Exception: ' . $e;
return self::createRejection($easy, $ctx);
}
// Retry no more than 3 times before giving up.
if (!isset($easy->options['_curl_retries'])) {
$easy->options['_curl_retries'] = 1;
} elseif ($easy->options['_curl_retries'] == 2) {
$ctx['error'] = 'The cURL request was retried 3 times ' . 'and did not succeed. The most likely reason for the failure ' . 'is that cURL was unable to rewind the body of the request ' . 'and subsequent retries resulted in the same error. Turn on ' . 'the debug option to see what went wrong. See ' . 'https://bugs.php.net/bug.php?id=47204 for more information.';
return self::createRejection($easy, $ctx);
} else {
++$easy->options['_curl_retries'];
}
return $handler($easy->request, $easy->options);
}
private function createHeaderFn(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : callable
{
if (isset($easy->options['on_headers'])) {
$onHeaders = $easy->options['on_headers'];
if (!\is_callable($onHeaders)) {
throw new \InvalidArgumentException('on_headers must be callable');
}
} else {
$onHeaders = null;
}
return static function ($ch, $h) use($onHeaders, $easy, &$startingResponse) {
$value = \trim($h);
if ($value === '') {
$startingResponse = \true;
try {
$easy->createResponse();
} catch (\Exception $e) {
$easy->createResponseException = $e;
return -1;
}
if ($onHeaders !== null) {
try {
$onHeaders($easy->response);
} catch (\Exception $e) {
// Associate the exception with the handle and trigger
// a curl header write error by returning 0.
$easy->onHeadersException = $e;
return -1;
}
}
} elseif ($startingResponse) {
$startingResponse = \false;
$easy->headers = [$value];
} else {
$easy->headers[] = $value;
}
return \strlen($h);
};
}
public function __destruct()
{
foreach ($this->handles as $id => $handle) {
\curl_close($handle);
unset($this->handles[$id]);
}
}
}
vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php 0000644 00000006202 14720660247 0020036 0 ustar 00 'http://www.foo.com/1.0/',
* 'timeout' => 0,
* 'allow_redirects' => false,
* 'proxy' => '192.168.16.1:10'
* ]);
*
* Client configuration settings include the following options:
*
* - handler: (callable) Function that transfers HTTP requests over the
* wire. The function is called with a Psr7\Http\Message\RequestInterface
* and array of transfer options, and must return a
* GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
* Psr7\Http\Message\ResponseInterface on success.
* If no handler is provided, a default handler will be created
* that enables all of the request options below by attaching all of the
* default middleware to the handler.
* - base_uri: (string|UriInterface) Base URI of the client that is merged
* into relative URIs. Can be a string or instance of UriInterface.
* - **: any request option
*
* @param array $config Client configuration settings.
*
* @see \GuzzleHttp\RequestOptions for a list of available request options.
*/
public function __construct(array $config = [])
{
if (!isset($config['handler'])) {
$config['handler'] = \YoastSEO_Vendor\GuzzleHttp\HandlerStack::create();
} elseif (!\is_callable($config['handler'])) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('handler must be a callable');
}
// Convert the base_uri to a UriInterface
if (isset($config['base_uri'])) {
$config['base_uri'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($config['base_uri']);
}
$this->configureDefaults($config);
}
/**
* @param string $method
* @param array $args
*
* @return PromiseInterface|ResponseInterface
*
* @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0.
*/
public function __call($method, $args)
{
if (\count($args) < 1) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('Magic request methods require a URI and optional options array');
}
$uri = $args[0];
$opts = $args[1] ?? [];
return \substr($method, -5) === 'Async' ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) : $this->request($method, $uri, $opts);
}
/**
* Asynchronously send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*/
public function sendAsync(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
// Merge the base URI into the request URI if needed.
$options = $this->prepareDefaults($options);
return $this->transfer($request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')), $options);
}
/**
* Send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*
* @throws GuzzleException
*/
public function send(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true;
return $this->sendAsync($request, $options)->wait();
}
/**
* The HttpClient PSR (PSR-18) specify this method.
*
* {@inheritDoc}
*/
public function sendRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true;
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS] = \false;
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::HTTP_ERRORS] = \false;
return $this->sendAsync($request, $options)->wait();
}
/**
* Create and send an asynchronous HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string $method HTTP method
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*/
public function requestAsync(string $method, $uri = '', array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$options = $this->prepareDefaults($options);
// Remove request modifying parameter because it can be done up-front.
$headers = $options['headers'] ?? [];
$body = $options['body'] ?? null;
$version = $options['version'] ?? '1.1';
// Merge the URI into the base URI.
$uri = $this->buildUri(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($uri), $options);
if (\is_array($body)) {
throw $this->invalidBody();
}
$request = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri, $headers, $body, $version);
// Remove the option so that they are not doubly-applied.
unset($options['headers'], $options['body'], $options['version']);
return $this->transfer($request, $options);
}
/**
* Create and send an HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string $method HTTP method.
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*
* @throws GuzzleException
*/
public function request(string $method, $uri = '', array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true;
return $this->requestAsync($method, $uri, $options)->wait();
}
/**
* Get a client configuration option.
*
* These options include default request options of the client, a "handler"
* (if utilized by the concrete client), and a "base_uri" if utilized by
* the concrete client.
*
* @param string|null $option The config option to retrieve.
*
* @return mixed
*
* @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.
*/
public function getConfig(string $option = null)
{
return $option === null ? $this->config : $this->config[$option] ?? null;
}
private function buildUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $config) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
if (isset($config['base_uri'])) {
$uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($config['base_uri']), $uri);
}
if (isset($config['idn_conversion']) && $config['idn_conversion'] !== \false) {
$idnOptions = $config['idn_conversion'] === \true ? \IDNA_DEFAULT : $config['idn_conversion'];
$uri = \YoastSEO_Vendor\GuzzleHttp\Utils::idnUriConvert($uri, $idnOptions);
}
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
}
/**
* Configures the default options for a client.
*/
private function configureDefaults(array $config) : void
{
$defaults = ['allow_redirects' => \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware::$defaultSettings, 'http_errors' => \true, 'decode_content' => \true, 'verify' => \true, 'cookies' => \false, 'idn_conversion' => \false];
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
// We can only trust the HTTP_PROXY environment variable in a CLI
// process due to the fact that PHP has no reliable mechanism to
// get environment variables that start with "HTTP_".
if (\PHP_SAPI === 'cli' && ($proxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('HTTP_PROXY'))) {
$defaults['proxy']['http'] = $proxy;
}
if ($proxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('HTTPS_PROXY')) {
$defaults['proxy']['https'] = $proxy;
}
if ($noProxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('NO_PROXY')) {
$cleanedNoProxy = \str_replace(' ', '', $noProxy);
$defaults['proxy']['no'] = \explode(',', $cleanedNoProxy);
}
$this->config = $config + $defaults;
if (!empty($config['cookies']) && $config['cookies'] === \true) {
$this->config['cookies'] = new \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar();
}
// Add the default user-agent header.
if (!isset($this->config['headers'])) {
$this->config['headers'] = ['User-Agent' => \YoastSEO_Vendor\GuzzleHttp\Utils::defaultUserAgent()];
} else {
// Add the User-Agent header if one was not already set.
foreach (\array_keys($this->config['headers']) as $name) {
if (\strtolower($name) === 'user-agent') {
return;
}
}
$this->config['headers']['User-Agent'] = \YoastSEO_Vendor\GuzzleHttp\Utils::defaultUserAgent();
}
}
/**
* Merges default options into the array.
*
* @param array $options Options to modify by reference
*/
private function prepareDefaults(array $options) : array
{
$defaults = $this->config;
if (!empty($defaults['headers'])) {
// Default headers are only added if they are not present.
$defaults['_conditional'] = $defaults['headers'];
unset($defaults['headers']);
}
// Special handling for headers is required as they are added as
// conditional headers and as headers passed to a request ctor.
if (\array_key_exists('headers', $options)) {
// Allows default headers to be unset.
if ($options['headers'] === null) {
$defaults['_conditional'] = [];
unset($options['headers']);
} elseif (!\is_array($options['headers'])) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('headers must be an array');
}
}
// Shallow merge defaults underneath options.
$result = $options + $defaults;
// Remove null values.
foreach ($result as $k => $v) {
if ($v === null) {
unset($result[$k]);
}
}
return $result;
}
/**
* Transfers the given request and applies request options.
*
* The URI of the request is not modified and the request options are used
* as-is without merging in default options.
*
* @param array $options See \GuzzleHttp\RequestOptions.
*/
private function transfer(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$request = $this->applyOptions($request, $options);
/** @var HandlerStack $handler */
$handler = $options['handler'];
try {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($handler($request, $options));
} catch (\Exception $e) {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($e);
}
}
/**
* Applies the array of request options to a request.
*/
private function applyOptions(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
$modify = ['set_headers' => []];
if (isset($options['headers'])) {
if (\array_keys($options['headers']) === \range(0, \count($options['headers']) - 1)) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('The headers array must have header name as keys.');
}
$modify['set_headers'] = $options['headers'];
unset($options['headers']);
}
if (isset($options['form_params'])) {
if (isset($options['multipart'])) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('You cannot use ' . 'form_params and multipart at the same time. Use the ' . 'form_params option if you want to send application/' . 'x-www-form-urlencoded requests, and the multipart ' . 'option to send multipart/form-data requests.');
}
$options['body'] = \http_build_query($options['form_params'], '', '&');
unset($options['form_params']);
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
}
if (isset($options['multipart'])) {
$options['body'] = new \YoastSEO_Vendor\GuzzleHttp\Psr7\MultipartStream($options['multipart']);
unset($options['multipart']);
}
if (isset($options['json'])) {
$options['body'] = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonEncode($options['json']);
unset($options['json']);
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'application/json';
}
if (!empty($options['decode_content']) && $options['decode_content'] !== \true) {
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']);
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
}
if (isset($options['body'])) {
if (\is_array($options['body'])) {
throw $this->invalidBody();
}
$modify['body'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($options['body']);
unset($options['body']);
}
if (!empty($options['auth']) && \is_array($options['auth'])) {
$value = $options['auth'];
$type = isset($value[2]) ? \strtolower($value[2]) : 'basic';
switch ($type) {
case 'basic':
// Ensure that we don't have the header in different case and set the new value.
$modify['set_headers'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']);
$modify['set_headers']['Authorization'] = 'Basic ' . \base64_encode("{$value[0]}:{$value[1]}");
break;
case 'digest':
// @todo: Do not rely on curl
$options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST;
$options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}";
break;
case 'ntlm':
$options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM;
$options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}";
break;
}
}
if (isset($options['query'])) {
$value = $options['query'];
if (\is_array($value)) {
$value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986);
}
if (!\is_string($value)) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('query must be a string or array');
}
$modify['query'] = $value;
unset($options['query']);
}
// Ensure that sink is not an invalid value.
if (isset($options['sink'])) {
// TODO: Add more sink validation?
if (\is_bool($options['sink'])) {
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('sink must not be a boolean');
}
}
if (isset($options['version'])) {
$modify['version'] = $options['version'];
}
$request = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify);
if ($request->getBody() instanceof \YoastSEO_Vendor\GuzzleHttp\Psr7\MultipartStream) {
// Use a multipart/form-data POST if a Content-Type is not set.
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' . $request->getBody()->getBoundary();
}
// Merge in conditional headers if they are not present.
if (isset($options['_conditional'])) {
// Build up the changes so it's in a single clone of the message.
$modify = [];
foreach ($options['_conditional'] as $k => $v) {
if (!$request->hasHeader($k)) {
$modify['set_headers'][$k] = $v;
}
}
$request = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify);
// Don't pass this internal value along to middleware/handlers.
unset($options['_conditional']);
}
return $request;
}
/**
* Return an InvalidArgumentException with pre-set message.
*/
private function invalidBody() : \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException
{
return new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('Passing in the "body" request ' . 'option as an array to send a request is not supported. ' . 'Please use the "form_params" request option to send a ' . 'application/x-www-form-urlencoded request, or the "multipart" ' . 'request option to send a multipart/form-data request.');
}
}
vendor_prefixed/guzzlehttp/guzzle/src/BodySummarizerInterface.php 0000644 00000000453 14720660247 0021576 0 ustar 00 $rfn) {
if ($rfn instanceof \YoastSEO_Vendor\Psr\Http\Message\RequestInterface) {
(yield $key => $client->sendAsync($rfn, $opts));
} elseif (\is_callable($rfn)) {
(yield $key => $rfn($opts));
} else {
throw new \InvalidArgumentException('Each value yielded by the iterator must be a Psr7\\Http\\Message\\RequestInterface or a callable that returns a promise that fulfills with a Psr7\\Message\\Http\\ResponseInterface object.');
}
}
};
$this->each = new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($requests(), $config);
}
/**
* Get promise
*/
public function promise() : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
return $this->each->promise();
}
/**
* Sends multiple requests concurrently and returns an array of responses
* and exceptions that uses the same ordering as the provided requests.
*
* IMPORTANT: This method keeps every request and response in memory, and
* as such, is NOT recommended when sending a large number or an
* indeterminate number of requests concurrently.
*
* @param ClientInterface $client Client used to send the requests
* @param array|\Iterator $requests Requests to send concurrently.
* @param array $options Passes through the options available in
* {@see \GuzzleHttp\Pool::__construct}
*
* @return array Returns an array containing the response or an exception
* in the same order that the requests were sent.
*
* @throws \InvalidArgumentException if the event format is incorrect.
*/
public static function batch(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client, $requests, array $options = []) : array
{
$res = [];
self::cmpCallback($options, 'fulfilled', $res);
self::cmpCallback($options, 'rejected', $res);
$pool = new static($client, $requests, $options);
$pool->promise()->wait();
\ksort($res);
return $res;
}
/**
* Execute callback(s)
*/
private static function cmpCallback(array &$options, string $name, array &$results) : void
{
if (!isset($options[$name])) {
$options[$name] = static function ($v, $k) use(&$results) {
$results[$k] = $v;
};
} else {
$currentFn = $options[$name];
$options[$name] = static function ($v, $k) use(&$results, $currentFn) {
$currentFn($v, $k);
$results[$k] = $v;
};
}
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Middleware.php 0000644 00000026130 14720660247 0017056 0 ustar 00 withCookieHeader($request);
return $handler($request, $options)->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($cookieJar, $request) : ResponseInterface {
$cookieJar->extractCookies($request, $response);
return $response;
});
};
};
}
/**
* Middleware that throws exceptions for 4xx or 5xx responses when the
* "http_errors" request option is set to true.
*
* @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages.
*
* @return callable(callable): callable Returns a function that accepts the next handler.
*/
public static function httpErrors(\YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface $bodySummarizer = null) : callable
{
return static function (callable $handler) use($bodySummarizer) : callable {
return static function ($request, array $options) use($handler, $bodySummarizer) {
if (empty($options['http_errors'])) {
return $handler($request, $options);
}
return $handler($request, $options)->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request, $bodySummarizer) {
$code = $response->getStatusCode();
if ($code < 400) {
return $response;
}
throw \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::create($request, $response, null, [], $bodySummarizer);
});
};
};
}
/**
* Middleware that pushes history data to an ArrayAccess container.
*
* @param array|\ArrayAccess $container Container to hold the history (by reference).
*
* @return callable(callable): callable Returns a function that accepts the next handler.
*
* @throws \InvalidArgumentException if container is not an array or ArrayAccess.
*/
public static function history(&$container) : callable
{
if (!\is_array($container) && !$container instanceof \ArrayAccess) {
throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
}
return static function (callable $handler) use(&$container) : callable {
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, &$container) {
return $handler($request, $options)->then(static function ($value) use($request, &$container, $options) {
$container[] = ['request' => $request, 'response' => $value, 'error' => null, 'options' => $options];
return $value;
}, static function ($reason) use($request, &$container, $options) {
$container[] = ['request' => $request, 'response' => null, 'error' => $reason, 'options' => $options];
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
});
};
};
}
/**
* Middleware that invokes a callback before and after sending a request.
*
* The provided listener cannot modify or alter the response. It simply
* "taps" into the chain to be notified before returning the promise. The
* before listener accepts a request and options array, and the after
* listener accepts a request, options array, and response promise.
*
* @param callable $before Function to invoke before forwarding the request.
* @param callable $after Function invoked after forwarding.
*
* @return callable Returns a function that accepts the next handler.
*/
public static function tap(callable $before = null, callable $after = null) : callable
{
return static function (callable $handler) use($before, $after) : callable {
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $before, $after) {
if ($before) {
$before($request, $options);
}
$response = $handler($request, $options);
if ($after) {
$after($request, $options, $response);
}
return $response;
};
};
}
/**
* Middleware that handles request redirects.
*
* @return callable Returns a function that accepts the next handler.
*/
public static function redirect() : callable
{
return static function (callable $handler) : RedirectMiddleware {
return new \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware($handler);
};
}
/**
* Middleware that retries requests based on the boolean result of
* invoking the provided "decider" function.
*
* If no delay function is provided, a simple implementation of exponential
* backoff will be utilized.
*
* @param callable $decider Function that accepts the number of retries,
* a request, [response], and [exception] and
* returns true if the request is to be retried.
* @param callable $delay Function that accepts the number of retries and
* returns the number of milliseconds to delay.
*
* @return callable Returns a function that accepts the next handler.
*/
public static function retry(callable $decider, callable $delay = null) : callable
{
return static function (callable $handler) use($decider, $delay) : RetryMiddleware {
return new \YoastSEO_Vendor\GuzzleHttp\RetryMiddleware($decider, $handler, $delay);
};
}
/**
* Middleware that logs requests, responses, and errors using a message
* formatter.
*
* @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests.
*
* @param LoggerInterface $logger Logs messages.
* @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings.
* @param string $logLevel Level at which to log requests.
*
* @return callable Returns a function that accepts the next handler.
*/
public static function log(\YoastSEO_Vendor\Psr\Log\LoggerInterface $logger, $formatter, string $logLevel = 'info') : callable
{
// To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter
if (!$formatter instanceof \YoastSEO_Vendor\GuzzleHttp\MessageFormatter && !$formatter instanceof \YoastSEO_Vendor\GuzzleHttp\MessageFormatterInterface) {
throw new \LogicException(\sprintf('Argument 2 to %s::log() must be of type %s', self::class, \YoastSEO_Vendor\GuzzleHttp\MessageFormatterInterface::class));
}
return static function (callable $handler) use($logger, $formatter, $logLevel) : callable {
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) use($handler, $logger, $formatter, $logLevel) {
return $handler($request, $options)->then(static function ($response) use($logger, $request, $formatter, $logLevel) : ResponseInterface {
$message = $formatter->format($request, $response);
$logger->log($logLevel, $message);
return $response;
}, static function ($reason) use($logger, $request, $formatter) : PromiseInterface {
$response = $reason instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $reason->getResponse() : null;
$message = $formatter->format($request, $response, \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($reason));
$logger->error($message);
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
});
};
};
}
/**
* This middleware adds a default content-type if possible, a default
* content-length or transfer-encoding header, and the expect header.
*/
public static function prepareBody() : callable
{
return static function (callable $handler) : PrepareBodyMiddleware {
return new \YoastSEO_Vendor\GuzzleHttp\PrepareBodyMiddleware($handler);
};
}
/**
* Middleware that applies a map function to the request before passing to
* the next handler.
*
* @param callable $fn Function that accepts a RequestInterface and returns
* a RequestInterface.
*/
public static function mapRequest(callable $fn) : callable
{
return static function (callable $handler) use($fn) : callable {
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $fn) {
return $handler($fn($request), $options);
};
};
}
/**
* Middleware that applies a map function to the resolved promise's
* response.
*
* @param callable $fn Function that accepts a ResponseInterface and
* returns a ResponseInterface.
*/
public static function mapResponse(callable $fn) : callable
{
return static function (callable $handler) use($fn) : callable {
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $fn) {
return $handler($request, $options)->then($fn);
};
};
}
}
vendor_prefixed/guzzlehttp/guzzle/src/RetryMiddleware.php 0000644 00000007241 14720660247 0020106 0 ustar 00 decider = $decider;
$this->nextHandler = $nextHandler;
$this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
}
/**
* Default exponential backoff delay function.
*
* @return int milliseconds.
*/
public static function exponentialDelay(int $retries) : int
{
return (int) 2 ** ($retries - 1) * 1000;
}
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
if (!isset($options['retries'])) {
$options['retries'] = 0;
}
$fn = $this->nextHandler;
return $fn($request, $options)->then($this->onFulfilled($request, $options), $this->onRejected($request, $options));
}
/**
* Execute fulfilled closure
*/
private function onFulfilled(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : callable
{
return function ($value) use($request, $options) {
if (!($this->decider)($options['retries'], $request, $value, null)) {
return $value;
}
return $this->doRetry($request, $options, $value);
};
}
/**
* Execute rejected closure
*/
private function onRejected(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $req, array $options) : callable
{
return function ($reason) use($req, $options) {
if (!($this->decider)($options['retries'], $req, null, $reason)) {
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
}
return $this->doRetry($req, $options);
};
}
private function doRetry(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
{
$options['delay'] = ($this->delay)(++$options['retries'], $response, $request);
return $this($request, $options);
}
}
vendor_prefixed/guzzlehttp/guzzle/src/MessageFormatter.php 0000644 00000016166 14720660247 0020261 0 ustar 00 >>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
/**
* @var string Template used to format log messages
*/
private $template;
/**
* @param string $template Log message template
*/
public function __construct(?string $template = self::CLF)
{
$this->template = $template ?: self::CLF;
}
/**
* Returns a formatted message string.
*
* @param RequestInterface $request Request that was sent
* @param ResponseInterface|null $response Response that was received
* @param \Throwable|null $error Exception that was received
*/
public function format(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $error = null) : string
{
$cache = [];
/** @var string */
return \preg_replace_callback('/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/', function (array $matches) use($request, $response, $error, &$cache) {
if (isset($cache[$matches[1]])) {
return $cache[$matches[1]];
}
$result = '';
switch ($matches[1]) {
case 'request':
$result = \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::toString($request);
break;
case 'response':
$result = $response ? \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::toString($response) : '';
break;
case 'req_headers':
$result = \trim($request->getMethod() . ' ' . $request->getRequestTarget()) . ' HTTP/' . $request->getProtocolVersion() . "\r\n" . $this->headers($request);
break;
case 'res_headers':
$result = $response ? \sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase()) . "\r\n" . $this->headers($response) : 'NULL';
break;
case 'req_body':
$result = $request->getBody()->__toString();
break;
case 'res_body':
if (!$response instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface) {
$result = 'NULL';
break;
}
$body = $response->getBody();
if (!$body->isSeekable()) {
$result = 'RESPONSE_NOT_LOGGEABLE';
break;
}
$result = $response->getBody()->__toString();
break;
case 'ts':
case 'date_iso_8601':
$result = \gmdate('c');
break;
case 'date_common_log':
$result = \date('d/M/Y:H:i:s O');
break;
case 'method':
$result = $request->getMethod();
break;
case 'version':
$result = $request->getProtocolVersion();
break;
case 'uri':
case 'url':
$result = $request->getUri()->__toString();
break;
case 'target':
$result = $request->getRequestTarget();
break;
case 'req_version':
$result = $request->getProtocolVersion();
break;
case 'res_version':
$result = $response ? $response->getProtocolVersion() : 'NULL';
break;
case 'host':
$result = $request->getHeaderLine('Host');
break;
case 'hostname':
$result = \gethostname();
break;
case 'code':
$result = $response ? $response->getStatusCode() : 'NULL';
break;
case 'phrase':
$result = $response ? $response->getReasonPhrase() : 'NULL';
break;
case 'error':
$result = $error ? $error->getMessage() : 'NULL';
break;
default:
// handle prefixed dynamic headers
if (\strpos($matches[1], 'req_header_') === 0) {
$result = $request->getHeaderLine(\substr($matches[1], 11));
} elseif (\strpos($matches[1], 'res_header_') === 0) {
$result = $response ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL';
}
}
$cache[$matches[1]] = $result;
return $result;
}, $this->template);
}
/**
* Get headers from message as string
*/
private function headers(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : string
{
$result = '';
foreach ($message->getHeaders() as $name => $values) {
$result .= $name . ': ' . \implode(', ', $values) . "\r\n";
}
return \trim($result);
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SetCookie.php 0000644 00000033464 14720660247 0020107 0 ustar 00 null, 'Value' => null, 'Domain' => null, 'Path' => '/', 'Max-Age' => null, 'Expires' => null, 'Secure' => \false, 'Discard' => \false, 'HttpOnly' => \false];
/**
* @var array Cookie data
*/
private $data;
/**
* Create a new SetCookie object from a string.
*
* @param string $cookie Set-Cookie header string
*/
public static function fromString(string $cookie) : self
{
// Create the default return array
$data = self::$defaults;
// Explode the cookie string using a series of semicolons
$pieces = \array_filter(\array_map('trim', \explode(';', $cookie)));
// The name of the cookie (first kvp) must exist and include an equal sign.
if (!isset($pieces[0]) || \strpos($pieces[0], '=') === \false) {
return new self($data);
}
// Add the cookie pieces into the parsed data array
foreach ($pieces as $part) {
$cookieParts = \explode('=', $part, 2);
$key = \trim($cookieParts[0]);
$value = isset($cookieParts[1]) ? \trim($cookieParts[1], " \n\r\t\x00\v") : \true;
// Only check for non-cookies when cookies have been found
if (!isset($data['Name'])) {
$data['Name'] = $key;
$data['Value'] = $value;
} else {
foreach (\array_keys(self::$defaults) as $search) {
if (!\strcasecmp($search, $key)) {
if ($search === 'Max-Age') {
if (\is_numeric($value)) {
$data[$search] = (int) $value;
}
} else {
$data[$search] = $value;
}
continue 2;
}
}
$data[$key] = $value;
}
}
return new self($data);
}
/**
* @param array $data Array of cookie data provided by a Cookie parser
*/
public function __construct(array $data = [])
{
$this->data = self::$defaults;
if (isset($data['Name'])) {
$this->setName($data['Name']);
}
if (isset($data['Value'])) {
$this->setValue($data['Value']);
}
if (isset($data['Domain'])) {
$this->setDomain($data['Domain']);
}
if (isset($data['Path'])) {
$this->setPath($data['Path']);
}
if (isset($data['Max-Age'])) {
$this->setMaxAge($data['Max-Age']);
}
if (isset($data['Expires'])) {
$this->setExpires($data['Expires']);
}
if (isset($data['Secure'])) {
$this->setSecure($data['Secure']);
}
if (isset($data['Discard'])) {
$this->setDiscard($data['Discard']);
}
if (isset($data['HttpOnly'])) {
$this->setHttpOnly($data['HttpOnly']);
}
// Set the remaining values that don't have extra validation logic
foreach (\array_diff(\array_keys($data), \array_keys(self::$defaults)) as $key) {
$this->data[$key] = $data[$key];
}
// Extract the Expires value and turn it into a UNIX timestamp if needed
if (!$this->getExpires() && $this->getMaxAge()) {
// Calculate the Expires date
$this->setExpires(\time() + $this->getMaxAge());
} elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) {
$this->setExpires($expires);
}
}
public function __toString()
{
$str = $this->data['Name'] . '=' . ($this->data['Value'] ?? '') . '; ';
foreach ($this->data as $k => $v) {
if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== \false) {
if ($k === 'Expires') {
$str .= 'Expires=' . \gmdate('D, d M Y H:i:s \\G\\M\\T', $v) . '; ';
} else {
$str .= ($v === \true ? $k : "{$k}={$v}") . '; ';
}
}
}
return \rtrim($str, '; ');
}
public function toArray() : array
{
return $this->data;
}
/**
* Get the cookie name.
*
* @return string
*/
public function getName()
{
return $this->data['Name'];
}
/**
* Set the cookie name.
*
* @param string $name Cookie name
*/
public function setName($name) : void
{
if (!\is_string($name)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Name'] = (string) $name;
}
/**
* Get the cookie value.
*
* @return string|null
*/
public function getValue()
{
return $this->data['Value'];
}
/**
* Set the cookie value.
*
* @param string $value Cookie value
*/
public function setValue($value) : void
{
if (!\is_string($value)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Value'] = (string) $value;
}
/**
* Get the domain.
*
* @return string|null
*/
public function getDomain()
{
return $this->data['Domain'];
}
/**
* Set the domain of the cookie.
*
* @param string|null $domain
*/
public function setDomain($domain) : void
{
if (!\is_string($domain) && null !== $domain) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Domain'] = null === $domain ? null : (string) $domain;
}
/**
* Get the path.
*
* @return string
*/
public function getPath()
{
return $this->data['Path'];
}
/**
* Set the path of the cookie.
*
* @param string $path Path of the cookie
*/
public function setPath($path) : void
{
if (!\is_string($path)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Path'] = (string) $path;
}
/**
* Maximum lifetime of the cookie in seconds.
*
* @return int|null
*/
public function getMaxAge()
{
return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age'];
}
/**
* Set the max-age of the cookie.
*
* @param int|null $maxAge Max age of the cookie in seconds
*/
public function setMaxAge($maxAge) : void
{
if (!\is_int($maxAge) && null !== $maxAge) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge;
}
/**
* The UNIX timestamp when the cookie Expires.
*
* @return string|int|null
*/
public function getExpires()
{
return $this->data['Expires'];
}
/**
* Set the unix timestamp for which the cookie will expire.
*
* @param int|string|null $timestamp Unix timestamp or any English textual datetime description.
*/
public function setExpires($timestamp) : void
{
if (!\is_int($timestamp) && !\is_string($timestamp) && null !== $timestamp) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp));
}
/**
* Get whether or not this is a secure cookie.
*
* @return bool
*/
public function getSecure()
{
return $this->data['Secure'];
}
/**
* Set whether or not the cookie is secure.
*
* @param bool $secure Set to true or false if secure
*/
public function setSecure($secure) : void
{
if (!\is_bool($secure)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Secure'] = (bool) $secure;
}
/**
* Get whether or not this is a session cookie.
*
* @return bool|null
*/
public function getDiscard()
{
return $this->data['Discard'];
}
/**
* Set whether or not this is a session cookie.
*
* @param bool $discard Set to true or false if this is a session cookie
*/
public function setDiscard($discard) : void
{
if (!\is_bool($discard)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Discard'] = (bool) $discard;
}
/**
* Get whether or not this is an HTTP only cookie.
*
* @return bool
*/
public function getHttpOnly()
{
return $this->data['HttpOnly'];
}
/**
* Set whether or not this is an HTTP only cookie.
*
* @param bool $httpOnly Set to true or false if this is HTTP only
*/
public function setHttpOnly($httpOnly) : void
{
if (!\is_bool($httpOnly)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['HttpOnly'] = (bool) $httpOnly;
}
/**
* Check if the cookie matches a path value.
*
* A request-path path-matches a given cookie-path if at least one of
* the following conditions holds:
*
* - The cookie-path and the request-path are identical.
* - The cookie-path is a prefix of the request-path, and the last
* character of the cookie-path is %x2F ("/").
* - The cookie-path is a prefix of the request-path, and the first
* character of the request-path that is not included in the cookie-
* path is a %x2F ("/") character.
*
* @param string $requestPath Path to check against
*/
public function matchesPath(string $requestPath) : bool
{
$cookiePath = $this->getPath();
// Match on exact matches or when path is the default empty "/"
if ($cookiePath === '/' || $cookiePath == $requestPath) {
return \true;
}
// Ensure that the cookie-path is a prefix of the request path.
if (0 !== \strpos($requestPath, $cookiePath)) {
return \false;
}
// Match if the last character of the cookie-path is "/"
if (\substr($cookiePath, -1, 1) === '/') {
return \true;
}
// Match if the first character not included in cookie path is "/"
return \substr($requestPath, \strlen($cookiePath), 1) === '/';
}
/**
* Check if the cookie matches a domain value.
*
* @param string $domain Domain to check against
*/
public function matchesDomain(string $domain) : bool
{
$cookieDomain = $this->getDomain();
if (null === $cookieDomain) {
return \true;
}
// Remove the leading '.' as per spec in RFC 6265.
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3
$cookieDomain = \ltrim(\strtolower($cookieDomain), '.');
$domain = \strtolower($domain);
// Domain not set or exact match.
if ('' === $cookieDomain || $domain === $cookieDomain) {
return \true;
}
// Matching the subdomain according to RFC 6265.
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3
if (\filter_var($domain, \FILTER_VALIDATE_IP)) {
return \false;
}
return (bool) \preg_match('/\\.' . \preg_quote($cookieDomain, '/') . '$/', $domain);
}
/**
* Check if the cookie is expired.
*/
public function isExpired() : bool
{
return $this->getExpires() !== null && \time() > $this->getExpires();
}
/**
* Check if the cookie is valid according to RFC 6265.
*
* @return bool|string Returns true if valid or an error message if invalid
*/
public function validate()
{
$name = $this->getName();
if ($name === '') {
return 'The cookie name must not be empty';
}
// Check if any of the invalid characters are present in the cookie name
if (\preg_match('/[\\x00-\\x20\\x22\\x28-\\x29\\x2c\\x2f\\x3a-\\x40\\x5c\\x7b\\x7d\\x7f]/', $name)) {
return 'Cookie name must not contain invalid characters: ASCII ' . 'Control characters (0-31;127), space, tab and the ' . 'following characters: ()<>@,;:\\"/?={}';
}
// Value must not be null. 0 and empty string are valid. Empty strings
// are technically against RFC 6265, but known to happen in the wild.
$value = $this->getValue();
if ($value === null) {
return 'The cookie value must not be empty';
}
// Domains must not be empty, but can be 0. "0" is not a valid internet
// domain, but may be used as server name in a private network.
$domain = $this->getDomain();
if ($domain === null || $domain === '') {
return 'The cookie domain must not be empty';
}
return \true;
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php 0000644 00000022706 14720660247 0020065 0 ustar 00 strictMode = $strictMode;
foreach ($cookieArray as $cookie) {
if (!$cookie instanceof \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie) {
$cookie = new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie);
}
$this->setCookie($cookie);
}
}
/**
* Create a new Cookie jar from an associative array and domain.
*
* @param array $cookies Cookies to create the jar from
* @param string $domain Domain to set the cookies to
*/
public static function fromArray(array $cookies, string $domain) : self
{
$cookieJar = new self();
foreach ($cookies as $name => $value) {
$cookieJar->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie(['Domain' => $domain, 'Name' => $name, 'Value' => $value, 'Discard' => \true]));
}
return $cookieJar;
}
/**
* Evaluate if this cookie should be persisted to storage
* that survives between requests.
*
* @param SetCookie $cookie Being evaluated.
* @param bool $allowSessionCookies If we should persist session cookies
*/
public static function shouldPersist(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie, bool $allowSessionCookies = \false) : bool
{
if ($cookie->getExpires() || $allowSessionCookies) {
if (!$cookie->getDiscard()) {
return \true;
}
}
return \false;
}
/**
* Finds and returns the cookie based on the name
*
* @param string $name cookie name to search for
*
* @return SetCookie|null cookie that was found or null if not found
*/
public function getCookieByName(string $name) : ?\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie
{
foreach ($this->cookies as $cookie) {
if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) {
return $cookie;
}
}
return null;
}
public function toArray() : array
{
return \array_map(static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : array {
return $cookie->toArray();
}, $this->getIterator()->getArrayCopy());
}
public function clear(string $domain = null, string $path = null, string $name = null) : void
{
if (!$domain) {
$this->cookies = [];
return;
} elseif (!$path) {
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($domain) : bool {
return !$cookie->matchesDomain($domain);
});
} elseif (!$name) {
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain) : bool {
return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain));
});
} else {
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain, $name) {
return !($cookie->getName() == $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain));
});
}
}
public function clearSessionCookies() : void
{
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool {
return !$cookie->getDiscard() && $cookie->getExpires();
});
}
public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool
{
// If the name string is empty (but not 0), ignore the set-cookie
// string entirely.
$name = $cookie->getName();
if (!$name && $name !== '0') {
return \false;
}
// Only allow cookies with set and valid domain, name, value
$result = $cookie->validate();
if ($result !== \true) {
if ($this->strictMode) {
throw new \RuntimeException('Invalid cookie: ' . $result);
}
$this->removeCookieIfEmpty($cookie);
return \false;
}
// Resolve conflicts with previously set cookies
foreach ($this->cookies as $i => $c) {
// Two cookies are identical, when their path, and domain are
// identical.
if ($c->getPath() != $cookie->getPath() || $c->getDomain() != $cookie->getDomain() || $c->getName() != $cookie->getName()) {
continue;
}
// The previously set cookie is a discard cookie and this one is
// not so allow the new cookie to be set
if (!$cookie->getDiscard() && $c->getDiscard()) {
unset($this->cookies[$i]);
continue;
}
// If the new cookie's expiration is further into the future, then
// replace the old cookie
if ($cookie->getExpires() > $c->getExpires()) {
unset($this->cookies[$i]);
continue;
}
// If the value has changed, we better change it
if ($cookie->getValue() !== $c->getValue()) {
unset($this->cookies[$i]);
continue;
}
// The cookie exists, so no need to continue
return \false;
}
$this->cookies[] = $cookie;
return \true;
}
public function count() : int
{
return \count($this->cookies);
}
/**
* @return \ArrayIterator
*/
public function getIterator() : \ArrayIterator
{
return new \ArrayIterator(\array_values($this->cookies));
}
public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : void
{
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
foreach ($cookieHeader as $cookie) {
$sc = \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie::fromString($cookie);
if (!$sc->getDomain()) {
$sc->setDomain($request->getUri()->getHost());
}
if (0 !== \strpos($sc->getPath(), '/')) {
$sc->setPath($this->getCookiePathFromRequest($request));
}
if (!$sc->matchesDomain($request->getUri()->getHost())) {
continue;
}
// Note: At this point `$sc->getDomain()` being a public suffix should
// be rejected, but we don't want to pull in the full PSL dependency.
$this->setCookie($sc);
}
}
}
/**
* Computes cookie path following RFC 6265 section 5.1.4
*
* @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
*/
private function getCookiePathFromRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : string
{
$uriPath = $request->getUri()->getPath();
if ('' === $uriPath) {
return '/';
}
if (0 !== \strpos($uriPath, '/')) {
return '/';
}
if ('/' === $uriPath) {
return '/';
}
$lastSlashPos = \strrpos($uriPath, '/');
if (0 === $lastSlashPos || \false === $lastSlashPos) {
return '/';
}
return \substr($uriPath, 0, $lastSlashPos);
}
public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
$values = [];
$uri = $request->getUri();
$scheme = $uri->getScheme();
$host = $uri->getHost();
$path = $uri->getPath() ?: '/';
foreach ($this->cookies as $cookie) {
if ($cookie->matchesPath($path) && $cookie->matchesDomain($host) && !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https')) {
$values[] = $cookie->getName() . '=' . $cookie->getValue();
}
}
return $values ? $request->withHeader('Cookie', \implode('; ', $values)) : $request;
}
/**
* If a cookie already exists and the server asks to set it again with a
* null value, the cookie must be deleted.
*/
private function removeCookieIfEmpty(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : void
{
$cookieValue = $cookie->getValue();
if ($cookieValue === null || $cookieValue === '') {
$this->clear($cookie->getDomain(), $cookie->getPath(), $cookie->getName());
}
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php 0000644 00000004112 14720660247 0021420 0 ustar 00 sessionKey = $sessionKey;
$this->storeSessionCookies = $storeSessionCookies;
$this->load();
}
/**
* Saves cookies to session when shutting down
*/
public function __destruct()
{
$this->save();
}
/**
* Save cookies to the client session
*/
public function save() : void
{
$json = [];
/** @var SetCookie $cookie */
foreach ($this as $cookie) {
if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
$json[] = $cookie->toArray();
}
}
$_SESSION[$this->sessionKey] = \json_encode($json);
}
/**
* Load the contents of the client session into the data array
*/
protected function load() : void
{
if (!isset($_SESSION[$this->sessionKey])) {
return;
}
$data = \json_decode($_SESSION[$this->sessionKey], \true);
if (\is_array($data)) {
foreach ($data as $cookie) {
$this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie));
}
} elseif (\strlen($data)) {
throw new \RuntimeException('Invalid cookie data');
}
}
}
vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php 0000644 00000005745 14720660247 0021712 0 ustar 00
*/
interface CookieJarInterface extends \Countable, \IteratorAggregate
{
/**
* Create a request with added cookie headers.
*
* If no matching cookies are found in the cookie jar, then no Cookie
* header is added to the request and the same request is returned.
*
* @param RequestInterface $request Request object to modify.
*
* @return RequestInterface returns the modified request.
*/
public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
/**
* Extract cookies from an HTTP response and store them in the CookieJar.
*
* @param RequestInterface $request Request that was sent
* @param ResponseInterface $response Response that was received
*/
public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : void;
/**
* Sets a cookie in the cookie jar.
*
* @param SetCookie $cookie Cookie to set.
*
* @return bool Returns true on success or false on failure
*/
public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool;
/**
* Remove cookies currently held in the cookie jar.
*
* Invoking this method without arguments will empty the whole cookie jar.
* If given a $domain argument only cookies belonging to that domain will
* be removed. If given a $domain and $path argument, cookies belonging to
* the specified path within that domain are removed. If given all three
* arguments, then the cookie with the specified name, path and domain is
* removed.
*
* @param string|null $domain Clears cookies matching a domain
* @param string|null $path Clears cookies matching a domain and path
* @param string|null $name Clears cookies matching a domain, path, and name
*/
public function clear(string $domain = null, string $path = null, string $name = null) : void;
/**
* Discard all sessions cookies.
*
* Removes cookies that don't have an expire field or a have a discard
* field set to true. To be called when the user agent shuts down according
* to RFC 2965.
*/
public function clearSessionCookies() : void;
/**
* Converts the cookie jar to an array.
*/
public function toArray() : array;
}
vendor_prefixed/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php 0000644 00000005604 14720660247 0020663 0 ustar 00 filename = $cookieFile;
$this->storeSessionCookies = $storeSessionCookies;
if (\file_exists($cookieFile)) {
$this->load($cookieFile);
}
}
/**
* Saves the file when shutting down
*/
public function __destruct()
{
$this->save($this->filename);
}
/**
* Saves the cookies to a file.
*
* @param string $filename File to save
*
* @throws \RuntimeException if the file cannot be found or created
*/
public function save(string $filename) : void
{
$json = [];
/** @var SetCookie $cookie */
foreach ($this as $cookie) {
if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
$json[] = $cookie->toArray();
}
}
$jsonStr = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonEncode($json);
if (\false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) {
throw new \RuntimeException("Unable to save file {$filename}");
}
}
/**
* Load cookies from a JSON formatted file.
*
* Old cookies are kept unless overwritten by newly loaded ones.
*
* @param string $filename Cookie file to load.
*
* @throws \RuntimeException if the file cannot be loaded.
*/
public function load(string $filename) : void
{
$json = \file_get_contents($filename);
if (\false === $json) {
throw new \RuntimeException("Unable to load file {$filename}");
}
if ($json === '') {
return;
}
$data = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonDecode($json, \true);
if (\is_array($data)) {
foreach ($data as $cookie) {
$this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie));
}
} elseif (\is_scalar($data) && !empty($data)) {
throw new \RuntimeException("Invalid cookie file: {$filename}");
}
}
}
vendor_prefixed/guzzlehttp/guzzle/src/MessageFormatterInterface.php 0000644 00000001243 14720660247 0022070 0 ustar 00 ]+>|[^=]+/', $kvp, $matches)) {
$m = $matches[0];
if (isset($m[1])) {
$part[\trim($m[0], $trimmed)] = \trim($m[1], $trimmed);
} else {
$part[] = \trim($m[0], $trimmed);
}
}
}
if ($part) {
$params[] = $part;
}
}
}
return $params;
}
/**
* Converts an array of header values that may contain comma separated
* headers into an array of headers with no comma separated values.
*
* @param string|array $header Header to normalize.
*
* @deprecated Use self::splitList() instead.
*/
public static function normalize($header) : array
{
$result = [];
foreach ((array) $header as $value) {
foreach (self::splitList($value) as $parsed) {
$result[] = $parsed;
}
}
return $result;
}
/**
* Splits a HTTP header defined to contain a comma-separated list into
* each individual value. Empty values will be removed.
*
* Example headers include 'accept', 'cache-control' and 'if-none-match'.
*
* This method must not be used to parse headers that are not defined as
* a list, such as 'user-agent' or 'set-cookie'.
*
* @param string|string[] $values Header value as returned by MessageInterface::getHeader()
*
* @return string[]
*/
public static function splitList($values) : array
{
if (!\is_array($values)) {
$values = [$values];
}
$result = [];
foreach ($values as $value) {
if (!\is_string($value)) {
throw new \TypeError('$header must either be a string or an array containing strings.');
}
$v = '';
$isQuoted = \false;
$isEscaped = \false;
for ($i = 0, $max = \strlen($value); $i < $max; ++$i) {
if ($isEscaped) {
$v .= $value[$i];
$isEscaped = \false;
continue;
}
if (!$isQuoted && $value[$i] === ',') {
$v = \trim($v);
if ($v !== '') {
$result[] = $v;
}
$v = '';
continue;
}
if ($isQuoted && $value[$i] === '\\') {
$isEscaped = \true;
$v .= $value[$i];
continue;
}
if ($value[$i] === '"') {
$isQuoted = !$isQuoted;
$v .= $value[$i];
continue;
}
$v .= $value[$i];
}
$v = \trim($v);
if ($v !== '') {
$result[] = $v;
}
}
return $result;
}
}
vendor_prefixed/guzzlehttp/psr7/src/Rfc7230.php 0000644 00000001232 14720660247 0015376 0 ustar 00 @,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r?\n)m";
public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)";
}
vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php 0000644 00000017343 14720660247 0016752 0 ustar 00 array of values */
private $headers = [];
/** @var string[] Map of lowercase header name => original name at registration */
private $headerNames = [];
/** @var string */
private $protocol = '1.1';
/** @var StreamInterface|null */
private $stream;
public function getProtocolVersion() : string
{
return $this->protocol;
}
public function withProtocolVersion($version) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
{
if ($this->protocol === $version) {
return $this;
}
$new = clone $this;
$new->protocol = $version;
return $new;
}
public function getHeaders() : array
{
return $this->headers;
}
public function hasHeader($header) : bool
{
return isset($this->headerNames[\strtolower($header)]);
}
public function getHeader($header) : array
{
$header = \strtolower($header);
if (!isset($this->headerNames[$header])) {
return [];
}
$header = $this->headerNames[$header];
return $this->headers[$header];
}
public function getHeaderLine($header) : string
{
return \implode(', ', $this->getHeader($header));
}
public function withHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
{
$this->assertHeader($header);
$value = $this->normalizeHeaderValue($value);
$normalized = \strtolower($header);
$new = clone $this;
if (isset($new->headerNames[$normalized])) {
unset($new->headers[$new->headerNames[$normalized]]);
}
$new->headerNames[$normalized] = $header;
$new->headers[$header] = $value;
return $new;
}
public function withAddedHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
{
$this->assertHeader($header);
$value = $this->normalizeHeaderValue($value);
$normalized = \strtolower($header);
$new = clone $this;
if (isset($new->headerNames[$normalized])) {
$header = $this->headerNames[$normalized];
$new->headers[$header] = \array_merge($this->headers[$header], $value);
} else {
$new->headerNames[$normalized] = $header;
$new->headers[$header] = $value;
}
return $new;
}
public function withoutHeader($header) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
{
$normalized = \strtolower($header);
if (!isset($this->headerNames[$normalized])) {
return $this;
}
$header = $this->headerNames[$normalized];
$new = clone $this;
unset($new->headers[$header], $new->headerNames[$normalized]);
return $new;
}
public function getBody() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
if (!$this->stream) {
$this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor('');
}
return $this->stream;
}
public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
{
if ($body === $this->stream) {
return $this;
}
$new = clone $this;
$new->stream = $body;
return $new;
}
/**
* @param (string|string[])[] $headers
*/
private function setHeaders(array $headers) : void
{
$this->headerNames = $this->headers = [];
foreach ($headers as $header => $value) {
// Numeric array keys are converted to int by PHP.
$header = (string) $header;
$this->assertHeader($header);
$value = $this->normalizeHeaderValue($value);
$normalized = \strtolower($header);
if (isset($this->headerNames[$normalized])) {
$header = $this->headerNames[$normalized];
$this->headers[$header] = \array_merge($this->headers[$header], $value);
} else {
$this->headerNames[$normalized] = $header;
$this->headers[$header] = $value;
}
}
}
/**
* @param mixed $value
*
* @return string[]
*/
private function normalizeHeaderValue($value) : array
{
if (!\is_array($value)) {
return $this->trimAndValidateHeaderValues([$value]);
}
if (\count($value) === 0) {
throw new \InvalidArgumentException('Header value can not be an empty array.');
}
return $this->trimAndValidateHeaderValues($value);
}
/**
* Trims whitespace from the header values.
*
* Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
*
* header-field = field-name ":" OWS field-value OWS
* OWS = *( SP / HTAB )
*
* @param mixed[] $values Header values
*
* @return string[] Trimmed header values
*
* @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
*/
private function trimAndValidateHeaderValues(array $values) : array
{
return \array_map(function ($value) {
if (!\is_scalar($value) && null !== $value) {
throw new \InvalidArgumentException(\sprintf('Header value must be scalar or null but %s provided.', \is_object($value) ? \get_class($value) : \gettype($value)));
}
$trimmed = \trim((string) $value, " \t");
$this->assertValue($trimmed);
return $trimmed;
}, \array_values($values));
}
/**
* @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
*
* @param mixed $header
*/
private function assertHeader($header) : void
{
if (!\is_string($header)) {
throw new \InvalidArgumentException(\sprintf('Header name must be a string but %s provided.', \is_object($header) ? \get_class($header) : \gettype($header)));
}
if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name.', $header));
}
}
/**
* @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
*
* field-value = *( field-content / obs-fold )
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
* field-vchar = VCHAR / obs-text
* VCHAR = %x21-7E
* obs-text = %x80-FF
* obs-fold = CRLF 1*( SP / HTAB )
*/
private function assertValue(string $value) : void
{
// The regular expression intentionally does not support the obs-fold production, because as
// per RFC 7230#3.2.4:
//
// A sender MUST NOT generate a message that includes
// line folding (i.e., that has any field-value that contains a match to
// the obs-fold rule) unless the message is intended for packaging
// within the message/http media type.
//
// Clients must not send a request with line folding and a server sending folded headers is
// likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
// folding is not likely to break any legitimate use case.
if (!\preg_match('/^[\\x20\\x09\\x21-\\x7E\\x80-\\xFF]*$/D', $value)) {
throw new \InvalidArgumentException(\sprintf('"%s" is not valid header value.', $value));
}
}
}
vendor_prefixed/guzzlehttp/psr7/src/Exception/MalformedUriException.php 0000644 00000000405 14720660247 0022554 0 ustar 00 stream = $stream;
$this->maxLength = $maxLength;
}
public function write($string) : int
{
$diff = $this->maxLength - $this->stream->getSize();
// Begin returning 0 when the underlying stream is too large.
if ($diff <= 0) {
return 0;
}
// Write the stream or a subset of the stream if needed.
if (\strlen($string) < $diff) {
return $this->stream->write($string);
}
return $this->stream->write(\substr($string, 0, $diff));
}
}
vendor_prefixed/guzzlehttp/psr7/src/Message.php 0000644 00000020640 14720660247 0015740 0 ustar 00 getMethod() . ' ' . $message->getRequestTarget()) . ' HTTP/' . $message->getProtocolVersion();
if (!$message->hasHeader('host')) {
$msg .= "\r\nHost: " . $message->getUri()->getHost();
}
} elseif ($message instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface) {
$msg = 'HTTP/' . $message->getProtocolVersion() . ' ' . $message->getStatusCode() . ' ' . $message->getReasonPhrase();
} else {
throw new \InvalidArgumentException('Unknown message type');
}
foreach ($message->getHeaders() as $name => $values) {
if (\is_string($name) && \strtolower($name) === 'set-cookie') {
foreach ($values as $value) {
$msg .= "\r\n{$name}: " . $value;
}
} else {
$msg .= "\r\n{$name}: " . \implode(', ', $values);
}
}
return "{$msg}\r\n\r\n" . $message->getBody();
}
/**
* Get a short summary of the message body.
*
* Will return `null` if the response is not printable.
*
* @param MessageInterface $message The message to get the body summary
* @param int $truncateAt The maximum allowed size of the summary
*/
public static function bodySummary(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message, int $truncateAt = 120) : ?string
{
$body = $message->getBody();
if (!$body->isSeekable() || !$body->isReadable()) {
return null;
}
$size = $body->getSize();
if ($size === 0) {
return null;
}
$body->rewind();
$summary = $body->read($truncateAt);
$body->rewind();
if ($size > $truncateAt) {
$summary .= ' (truncated...)';
}
// Matches any printable character, including unicode characters:
// letters, marks, numbers, punctuation, spacing, and separators.
if (\preg_match('/[^\\pL\\pM\\pN\\pP\\pS\\pZ\\n\\r\\t]/u', $summary) !== 0) {
return null;
}
return $summary;
}
/**
* Attempts to rewind a message body and throws an exception on failure.
*
* The body of the message will only be rewound if a call to `tell()`
* returns a value other than `0`.
*
* @param MessageInterface $message Message to rewind
*
* @throws \RuntimeException
*/
public static function rewindBody(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : void
{
$body = $message->getBody();
if ($body->tell()) {
$body->rewind();
}
}
/**
* Parses an HTTP message into an associative array.
*
* The array contains the "start-line" key containing the start line of
* the message, "headers" key containing an associative array of header
* array values, and a "body" key containing the body of the message.
*
* @param string $message HTTP request or response to parse.
*/
public static function parseMessage(string $message) : array
{
if (!$message) {
throw new \InvalidArgumentException('Invalid message');
}
$message = \ltrim($message, "\r\n");
$messageParts = \preg_split("/\r?\n\r?\n/", $message, 2);
if ($messageParts === \false || \count($messageParts) !== 2) {
throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
}
[$rawHeaders, $body] = $messageParts;
$rawHeaders .= "\r\n";
// Put back the delimiter we split previously
$headerParts = \preg_split("/\r?\n/", $rawHeaders, 2);
if ($headerParts === \false || \count($headerParts) !== 2) {
throw new \InvalidArgumentException('Invalid message: Missing status line');
}
[$startLine, $rawHeaders] = $headerParts;
if (\preg_match("/(?:^HTTP\\/|^[A-Z]+ \\S+ HTTP\\/)(\\d+(?:\\.\\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
// Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
$rawHeaders = \preg_replace(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
}
/** @var array[] $headerLines */
$count = \preg_match_all(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, \PREG_SET_ORDER);
// If these aren't the same, then one line didn't match and there's an invalid header.
if ($count !== \substr_count($rawHeaders, "\n")) {
// Folding is deprecated, see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
if (\preg_match(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {
throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding');
}
throw new \InvalidArgumentException('Invalid header syntax');
}
$headers = [];
foreach ($headerLines as $headerLine) {
$headers[$headerLine[1]][] = $headerLine[2];
}
return ['start-line' => $startLine, 'headers' => $headers, 'body' => $body];
}
/**
* Constructs a URI for an HTTP request message.
*
* @param string $path Path from the start-line
* @param array $headers Array of headers (each value an array).
*/
public static function parseRequestUri(string $path, array $headers) : string
{
$hostKey = \array_filter(\array_keys($headers), function ($k) {
// Numeric array keys are converted to int by PHP.
$k = (string) $k;
return \strtolower($k) === 'host';
});
// If no host is found, then a full URI cannot be constructed.
if (!$hostKey) {
return $path;
}
$host = $headers[\reset($hostKey)][0];
$scheme = \substr($host, -4) === ':443' ? 'https' : 'http';
return $scheme . '://' . $host . '/' . \ltrim($path, '/');
}
/**
* Parses a request message string into a request object.
*
* @param string $message Request message string.
*/
public static function parseRequest(string $message) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
$data = self::parseMessage($message);
$matches = [];
if (!\preg_match('/^[\\S]+\\s+([a-zA-Z]+:\\/\\/|\\/).*/', $data['start-line'], $matches)) {
throw new \InvalidArgumentException('Invalid request string');
}
$parts = \explode(' ', $data['start-line'], 3);
$version = isset($parts[2]) ? \explode('/', $parts[2])[1] : '1.1';
$request = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($parts[0], $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1], $data['headers'], $data['body'], $version);
return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]);
}
/**
* Parses a response message string into a response object.
*
* @param string $message Response message string.
*/
public static function parseResponse(string $message) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
$data = self::parseMessage($message);
// According to https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
// the space between status-code and reason-phrase is required. But
// browsers accept responses without space and reason as well.
if (!\preg_match('/^HTTP\\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
}
$parts = \explode(' ', $data['start-line'], 3);
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response((int) $parts[1], $data['headers'], $data['body'], \explode('/', $parts[0])[1], $parts[2] ?? null);
}
}
vendor_prefixed/guzzlehttp/psr7/src/Request.php 0000644 00000010143 14720660247 0016001 0 ustar 00 assertMethod($method);
if (!$uri instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) {
$uri = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri);
}
$this->method = \strtoupper($method);
$this->uri = $uri;
$this->setHeaders($headers);
$this->protocol = $version;
if (!isset($this->headerNames['host'])) {
$this->updateHostFromUri();
}
if ($body !== '' && $body !== null) {
$this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($body);
}
}
public function getRequestTarget() : string
{
if ($this->requestTarget !== null) {
return $this->requestTarget;
}
$target = $this->uri->getPath();
if ($target === '') {
$target = '/';
}
if ($this->uri->getQuery() != '') {
$target .= '?' . $this->uri->getQuery();
}
return $target;
}
public function withRequestTarget($requestTarget) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
if (\preg_match('#\\s#', $requestTarget)) {
throw new \InvalidArgumentException('Invalid request target provided; cannot contain whitespace');
}
$new = clone $this;
$new->requestTarget = $requestTarget;
return $new;
}
public function getMethod() : string
{
return $this->method;
}
public function withMethod($method) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
$this->assertMethod($method);
$new = clone $this;
$new->method = \strtoupper($method);
return $new;
}
public function getUri() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
return $this->uri;
}
public function withUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $preserveHost = \false) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
if ($uri === $this->uri) {
return $this;
}
$new = clone $this;
$new->uri = $uri;
if (!$preserveHost || !isset($this->headerNames['host'])) {
$new->updateHostFromUri();
}
return $new;
}
private function updateHostFromUri() : void
{
$host = $this->uri->getHost();
if ($host == '') {
return;
}
if (($port = $this->uri->getPort()) !== null) {
$host .= ':' . $port;
}
if (isset($this->headerNames['host'])) {
$header = $this->headerNames['host'];
} else {
$header = 'Host';
$this->headerNames['host'] = 'Host';
}
// Ensure Host is the first header.
// See: https://datatracker.ietf.org/doc/html/rfc7230#section-5.4
$this->headers = [$header => [$host]] + $this->headers;
}
/**
* @param mixed $method
*/
private function assertMethod($method) : void
{
if (!\is_string($method) || $method === '') {
throw new \InvalidArgumentException('Method must be a non-empty string.');
}
}
}
vendor_prefixed/guzzlehttp/psr7/src/Query.php 0000644 00000007140 14720660247 0015461 0 ustar 00 '1', 'foo[b]' => '2'])`.
*
* @param string $str Query string to parse
* @param int|bool $urlEncoding How the query string is encoded
*/
public static function parse(string $str, $urlEncoding = \true) : array
{
$result = [];
if ($str === '') {
return $result;
}
if ($urlEncoding === \true) {
$decoder = function ($value) {
return \rawurldecode(\str_replace('+', ' ', (string) $value));
};
} elseif ($urlEncoding === \PHP_QUERY_RFC3986) {
$decoder = 'rawurldecode';
} elseif ($urlEncoding === \PHP_QUERY_RFC1738) {
$decoder = 'urldecode';
} else {
$decoder = function ($str) {
return $str;
};
}
foreach (\explode('&', $str) as $kvp) {
$parts = \explode('=', $kvp, 2);
$key = $decoder($parts[0]);
$value = isset($parts[1]) ? $decoder($parts[1]) : null;
if (!\array_key_exists($key, $result)) {
$result[$key] = $value;
} else {
if (!\is_array($result[$key])) {
$result[$key] = [$result[$key]];
}
$result[$key][] = $value;
}
}
return $result;
}
/**
* Build a query string from an array of key value pairs.
*
* This function can use the return value of `parse()` to build a query
* string. This function does not modify the provided keys when an array is
* encountered (like `http_build_query()` would).
*
* @param array $params Query string parameters.
* @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986
* to encode using RFC3986, or PHP_QUERY_RFC1738
* to encode using RFC1738.
*/
public static function build(array $params, $encoding = \PHP_QUERY_RFC3986) : string
{
if (!$params) {
return '';
}
if ($encoding === \false) {
$encoder = function (string $str) : string {
return $str;
};
} elseif ($encoding === \PHP_QUERY_RFC3986) {
$encoder = 'rawurlencode';
} elseif ($encoding === \PHP_QUERY_RFC1738) {
$encoder = 'urlencode';
} else {
throw new \InvalidArgumentException('Invalid type');
}
$qs = '';
foreach ($params as $k => $v) {
$k = $encoder((string) $k);
if (!\is_array($v)) {
$qs .= $k;
$v = \is_bool($v) ? (int) $v : $v;
if ($v !== null) {
$qs .= '=' . $encoder((string) $v);
}
$qs .= '&';
} else {
foreach ($v as $vv) {
$qs .= $k;
$vv = \is_bool($vv) ? (int) $vv : $vv;
if ($vv !== null) {
$qs .= '=' . $encoder((string) $vv);
}
$qs .= '&';
}
}
}
return $qs ? (string) \substr($qs, 0, -1) : '';
}
}
vendor_prefixed/guzzlehttp/psr7/src/MultipartStream.php 0000644 00000012371 14720660247 0017513 0 ustar 00 boundary = $boundary ?: \bin2hex(\random_bytes(20));
$this->stream = $this->createStream($elements);
}
public function getBoundary() : string
{
return $this->boundary;
}
public function isWritable() : bool
{
return \false;
}
/**
* Get the headers needed before transferring the content of a POST file
*
* @param string[] $headers
*/
private function getHeaders(array $headers) : string
{
$str = '';
foreach ($headers as $key => $value) {
$str .= "{$key}: {$value}\r\n";
}
return "--{$this->boundary}\r\n" . \trim($str) . "\r\n\r\n";
}
/**
* Create the aggregate stream that will be used to upload the POST data
*/
protected function createStream(array $elements = []) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
$stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream();
foreach ($elements as $element) {
if (!\is_array($element)) {
throw new \UnexpectedValueException('An array is expected');
}
$this->addElement($stream, $element);
}
// Add the trailing boundary with CRLF
$stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor("--{$this->boundary}--\r\n"));
return $stream;
}
private function addElement(\YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream $stream, array $element) : void
{
foreach (['contents', 'name'] as $key) {
if (!\array_key_exists($key, $element)) {
throw new \InvalidArgumentException("A '{$key}' key is required");
}
}
$element['contents'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($element['contents']);
if (empty($element['filename'])) {
$uri = $element['contents']->getMetadata('uri');
if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') {
$element['filename'] = $uri;
}
}
[$body, $headers] = $this->createElement($element['name'], $element['contents'], $element['filename'] ?? null, $element['headers'] ?? []);
$stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($this->getHeaders($headers)));
$stream->addStream($body);
$stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor("\r\n"));
}
/**
* @param string[] $headers
*
* @return array{0: StreamInterface, 1: string[]}
*/
private function createElement(string $name, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, ?string $filename, array $headers) : array
{
// Set a default content-disposition header if one was no provided
$disposition = self::getHeader($headers, 'content-disposition');
if (!$disposition) {
$headers['Content-Disposition'] = $filename === '0' || $filename ? \sprintf('form-data; name="%s"; filename="%s"', $name, \basename($filename)) : "form-data; name=\"{$name}\"";
}
// Set a default content-length header if one was no provided
$length = self::getHeader($headers, 'content-length');
if (!$length) {
if ($length = $stream->getSize()) {
$headers['Content-Length'] = (string) $length;
}
}
// Set a default Content-Type if one was not supplied
$type = self::getHeader($headers, 'content-type');
if (!$type && ($filename === '0' || $filename)) {
$headers['Content-Type'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($filename) ?? 'application/octet-stream';
}
return [$stream, $headers];
}
/**
* @param string[] $headers
*/
private static function getHeader(array $headers, string $key) : ?string
{
$lowercaseHeader = \strtolower($key);
foreach ($headers as $k => $v) {
if (\strtolower((string) $k) === $lowercaseHeader) {
return $v;
}
}
return null;
}
}
vendor_prefixed/guzzlehttp/psr7/src/UriNormalizer.php 0000644 00000020702 14720660247 0017155 0 ustar 00 getPath() === '' && ($uri->getScheme() === 'http' || $uri->getScheme() === 'https')) {
$uri = $uri->withPath('/');
}
if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {
$uri = $uri->withHost('');
}
if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isDefaultPort($uri)) {
$uri = $uri->withPort(null);
}
if ($flags & self::REMOVE_DOT_SEGMENTS && !\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isRelativePathReference($uri)) {
$uri = $uri->withPath(\YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::removeDotSegments($uri->getPath()));
}
if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
$uri = $uri->withPath(\preg_replace('#//++#', '/', $uri->getPath()));
}
if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
$queryKeyValues = \explode('&', $uri->getQuery());
\sort($queryKeyValues);
$uri = $uri->withQuery(\implode('&', $queryKeyValues));
}
return $uri;
}
/**
* Whether two URIs can be considered equivalent.
*
* Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also
* accepts relative URI references and returns true when they are equivalent. This of course assumes they will be
* resolved against the same base URI. If this is not the case, determination of equivalence or difference of
* relative references does not mean anything.
*
* @param UriInterface $uri1 An URI to compare
* @param UriInterface $uri2 An URI to compare
* @param int $normalizations A bitmask of normalizations to apply, see constants
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-6.1
*/
public static function isEquivalent(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri1, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS) : bool
{
return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
}
private static function capitalizePercentEncoding(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$regex = '/(?:%[A-Fa-f0-9]{2})++/';
$callback = function (array $match) : string {
return \strtoupper($match[0]);
};
return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery()));
}
private static function decodeUnreservedCharacters(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
$callback = function (array $match) : string {
return \rawurldecode($match[0]);
};
return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery()));
}
private function __construct()
{
// cannot be instantiated
}
}
vendor_prefixed/guzzlehttp/psr7/src/Utils.php 0000644 00000036735 14720660247 0015470 0 ustar 00 $v) {
if (!\in_array(\strtolower((string) $k), $keys)) {
$result[$k] = $v;
}
}
return $result;
}
/**
* Copy the contents of a stream into another stream until the given number
* of bytes have been read.
*
* @param StreamInterface $source Stream to read from
* @param StreamInterface $dest Stream to write to
* @param int $maxLen Maximum number of bytes to read. Pass -1
* to read the entire stream.
*
* @throws \RuntimeException on error.
*/
public static function copyToStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $dest, int $maxLen = -1) : void
{
$bufferSize = 8192;
if ($maxLen === -1) {
while (!$source->eof()) {
if (!$dest->write($source->read($bufferSize))) {
break;
}
}
} else {
$remaining = $maxLen;
while ($remaining > 0 && !$source->eof()) {
$buf = $source->read(\min($bufferSize, $remaining));
$len = \strlen($buf);
if (!$len) {
break;
}
$remaining -= $len;
$dest->write($buf);
}
}
}
/**
* Copy the contents of a stream into a string until the given number of
* bytes have been read.
*
* @param StreamInterface $stream Stream to read
* @param int $maxLen Maximum number of bytes to read. Pass -1
* to read the entire stream.
*
* @throws \RuntimeException on error.
*/
public static function copyToString(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $maxLen = -1) : string
{
$buffer = '';
if ($maxLen === -1) {
while (!$stream->eof()) {
$buf = $stream->read(1048576);
if ($buf === '') {
break;
}
$buffer .= $buf;
}
return $buffer;
}
$len = 0;
while (!$stream->eof() && $len < $maxLen) {
$buf = $stream->read($maxLen - $len);
if ($buf === '') {
break;
}
$buffer .= $buf;
$len = \strlen($buffer);
}
return $buffer;
}
/**
* Calculate a hash of a stream.
*
* This method reads the entire stream to calculate a rolling hash, based
* on PHP's `hash_init` functions.
*
* @param StreamInterface $stream Stream to calculate the hash for
* @param string $algo Hash algorithm (e.g. md5, crc32, etc)
* @param bool $rawOutput Whether or not to use raw output
*
* @throws \RuntimeException on error.
*/
public static function hash(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, string $algo, bool $rawOutput = \false) : string
{
$pos = $stream->tell();
if ($pos > 0) {
$stream->rewind();
}
$ctx = \hash_init($algo);
while (!$stream->eof()) {
\hash_update($ctx, $stream->read(1048576));
}
$out = \hash_final($ctx, $rawOutput);
$stream->seek($pos);
return $out;
}
/**
* Clone and modify a request with the given changes.
*
* This method is useful for reducing the number of clones needed to mutate
* a message.
*
* The changes can be one of:
* - method: (string) Changes the HTTP method.
* - set_headers: (array) Sets the given headers.
* - remove_headers: (array) Remove the given headers.
* - body: (mixed) Sets the given body.
* - uri: (UriInterface) Set the URI.
* - query: (string) Set the query string value of the URI.
* - version: (string) Set the protocol version.
*
* @param RequestInterface $request Request to clone and modify.
* @param array $changes Changes to apply.
*/
public static function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $changes) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
if (!$changes) {
return $request;
}
$headers = $request->getHeaders();
if (!isset($changes['uri'])) {
$uri = $request->getUri();
} else {
// Remove the host header if one is on the URI
if ($host = $changes['uri']->getHost()) {
$changes['set_headers']['Host'] = $host;
if ($port = $changes['uri']->getPort()) {
$standardPorts = ['http' => 80, 'https' => 443];
$scheme = $changes['uri']->getScheme();
if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) {
$changes['set_headers']['Host'] .= ':' . $port;
}
}
}
$uri = $changes['uri'];
}
if (!empty($changes['remove_headers'])) {
$headers = self::caselessRemove($changes['remove_headers'], $headers);
}
if (!empty($changes['set_headers'])) {
$headers = self::caselessRemove(\array_keys($changes['set_headers']), $headers);
$headers = $changes['set_headers'] + $headers;
}
if (isset($changes['query'])) {
$uri = $uri->withQuery($changes['query']);
}
if ($request instanceof \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface) {
$new = (new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion(), $request->getServerParams()))->withParsedBody($request->getParsedBody())->withQueryParams($request->getQueryParams())->withCookieParams($request->getCookieParams())->withUploadedFiles($request->getUploadedFiles());
foreach ($request->getAttributes() as $key => $value) {
$new = $new->withAttribute($key, $value);
}
return $new;
}
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion());
}
/**
* Read a line from the stream up to the maximum allowed buffer length.
*
* @param StreamInterface $stream Stream to read from
* @param int|null $maxLength Maximum buffer length
*/
public static function readLine(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $maxLength = null) : string
{
$buffer = '';
$size = 0;
while (!$stream->eof()) {
if ('' === ($byte = $stream->read(1))) {
return $buffer;
}
$buffer .= $byte;
// Break when a new line is found or the max length - 1 is reached
if ($byte === "\n" || ++$size === $maxLength - 1) {
break;
}
}
return $buffer;
}
/**
* Create a new stream based on the input type.
*
* Options is an associative array that can contain the following keys:
* - metadata: Array of custom metadata.
* - size: Size of the stream.
*
* This method accepts the following `$resource` types:
* - `Psr\Http\Message\StreamInterface`: Returns the value as-is.
* - `string`: Creates a stream object that uses the given string as the contents.
* - `resource`: Creates a stream object that wraps the given PHP stream resource.
* - `Iterator`: If the provided value implements `Iterator`, then a read-only
* stream object will be created that wraps the given iterable. Each time the
* stream is read from, data from the iterator will fill a buffer and will be
* continuously called until the buffer is equal to the requested read size.
* Subsequent read calls will first read from the buffer and then call `next`
* on the underlying iterator until it is exhausted.
* - `object` with `__toString()`: If the object has the `__toString()` method,
* the object will be cast to a string and then a stream will be returned that
* uses the string value.
* - `NULL`: When `null` is passed, an empty stream object is returned.
* - `callable` When a callable is passed, a read-only stream object will be
* created that invokes the given callable. The callable is invoked with the
* number of suggested bytes to read. The callable can return any number of
* bytes, but MUST return `false` when there is no more data to return. The
* stream object that wraps the callable will invoke the callable until the
* number of requested bytes are available. Any additional bytes will be
* buffered and used in subsequent reads.
*
* @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data
* @param array{size?: int, metadata?: array} $options Additional options
*
* @throws \InvalidArgumentException if the $resource arg is not valid.
*/
public static function streamFor($resource = '', array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
if (\is_scalar($resource)) {
$stream = self::tryFopen('php://temp', 'r+');
if ($resource !== '') {
\fwrite($stream, (string) $resource);
\fseek($stream, 0);
}
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($stream, $options);
}
switch (\gettype($resource)) {
case 'resource':
/*
* The 'php://input' is a special stream with quirks and inconsistencies.
* We avoid using that stream by reading it into php://temp
*/
/** @var resource $resource */
if ((\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') {
$stream = self::tryFopen('php://temp', 'w+');
\stream_copy_to_stream($resource, $stream);
\fseek($stream, 0);
$resource = $stream;
}
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource, $options);
case 'object':
/** @var object $resource */
if ($resource instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) {
return $resource;
} elseif ($resource instanceof \Iterator) {
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\PumpStream(function () use($resource) {
if (!$resource->valid()) {
return \false;
}
$result = $resource->current();
$resource->next();
return $result;
}, $options);
} elseif (\method_exists($resource, '__toString')) {
return self::streamFor((string) $resource, $options);
}
break;
case 'NULL':
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream(self::tryFopen('php://temp', 'r+'), $options);
}
if (\is_callable($resource)) {
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\PumpStream($resource, $options);
}
throw new \InvalidArgumentException('Invalid resource type: ' . \gettype($resource));
}
/**
* Safely opens a PHP stream resource using a filename.
*
* When fopen fails, PHP normally raises a warning. This function adds an
* error handler that checks for errors and throws an exception instead.
*
* @param string $filename File to open
* @param string $mode Mode used to open the file
*
* @return resource
*
* @throws \RuntimeException if the file cannot be opened
*/
public static function tryFopen(string $filename, string $mode)
{
$ex = null;
\set_error_handler(static function (int $errno, string $errstr) use($filename, $mode, &$ex) : bool {
$ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $errstr));
return \true;
});
try {
/** @var resource $handle */
$handle = \fopen($filename, $mode);
} catch (\Throwable $e) {
$ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $e->getMessage()), 0, $e);
}
\restore_error_handler();
if ($ex) {
/** @var $ex \RuntimeException */
throw $ex;
}
return $handle;
}
/**
* Safely gets the contents of a given stream.
*
* When stream_get_contents fails, PHP normally raises a warning. This
* function adds an error handler that checks for errors and throws an
* exception instead.
*
* @param resource $stream
*
* @throws \RuntimeException if the stream cannot be read
*/
public static function tryGetContents($stream) : string
{
$ex = null;
\set_error_handler(static function (int $errno, string $errstr) use(&$ex) : bool {
$ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $errstr));
return \true;
});
try {
/** @var string|false $contents */
$contents = \stream_get_contents($stream);
if ($contents === \false) {
$ex = new \RuntimeException('Unable to read stream contents');
}
} catch (\Throwable $e) {
$ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $e->getMessage()), 0, $e);
}
\restore_error_handler();
if ($ex) {
/** @var $ex \RuntimeException */
throw $ex;
}
return $contents;
}
/**
* Returns a UriInterface for the given value.
*
* This function accepts a string or UriInterface and returns a
* UriInterface for the given value. If the value is already a
* UriInterface, it is returned as-is.
*
* @param string|UriInterface $uri
*
* @throws \InvalidArgumentException
*/
public static function uriFor($uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
if ($uri instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) {
return $uri;
}
if (\is_string($uri)) {
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri);
}
throw new \InvalidArgumentException('URI must be a string or UriInterface');
}
}
vendor_prefixed/guzzlehttp/psr7/src/FnStream.php 0000644 00000010416 14720660247 0016073 0 ustar 00 */
private $methods;
/**
* @param array $methods Hash of method name to a callable.
*/
public function __construct(array $methods)
{
$this->methods = $methods;
// Create the functions on the class
foreach ($methods as $name => $fn) {
$this->{'_fn_' . $name} = $fn;
}
}
/**
* Lazily determine which methods are not implemented.
*
* @throws \BadMethodCallException
*/
public function __get(string $name) : void
{
throw new \BadMethodCallException(\str_replace('_fn_', '', $name) . '() is not implemented in the FnStream');
}
/**
* The close method is called on the underlying stream only if possible.
*/
public function __destruct()
{
if (isset($this->_fn_close)) {
($this->_fn_close)();
}
}
/**
* An unserialize would allow the __destruct to run when the unserialized value goes out of scope.
*
* @throws \LogicException
*/
public function __wakeup() : void
{
throw new \LogicException('FnStream should never be unserialized');
}
/**
* Adds custom functionality to an underlying stream by intercepting
* specific method calls.
*
* @param StreamInterface $stream Stream to decorate
* @param array $methods Hash of method name to a closure
*
* @return FnStream
*/
public static function decorate(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $methods)
{
// If any of the required methods were not provided, then simply
// proxy to the decorated stream.
foreach (\array_diff(self::SLOTS, \array_keys($methods)) as $diff) {
/** @var callable $callable */
$callable = [$stream, $diff];
$methods[$diff] = $callable;
}
return new self($methods);
}
public function __toString() : string
{
try {
/** @var string */
return ($this->_fn___toString)();
} catch (\Throwable $e) {
if (\PHP_VERSION_ID >= 70400) {
throw $e;
}
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
return '';
}
}
public function close() : void
{
($this->_fn_close)();
}
public function detach()
{
return ($this->_fn_detach)();
}
public function getSize() : ?int
{
return ($this->_fn_getSize)();
}
public function tell() : int
{
return ($this->_fn_tell)();
}
public function eof() : bool
{
return ($this->_fn_eof)();
}
public function isSeekable() : bool
{
return ($this->_fn_isSeekable)();
}
public function rewind() : void
{
($this->_fn_rewind)();
}
public function seek($offset, $whence = \SEEK_SET) : void
{
($this->_fn_seek)($offset, $whence);
}
public function isWritable() : bool
{
return ($this->_fn_isWritable)();
}
public function write($string) : int
{
return ($this->_fn_write)($string);
}
public function isReadable() : bool
{
return ($this->_fn_isReadable)();
}
public function read($length) : string
{
return ($this->_fn_read)($length);
}
public function getContents() : string
{
return ($this->_fn_getContents)();
}
/**
* @return mixed
*/
public function getMetadata($key = null)
{
return ($this->_fn_getMetadata)($key);
}
}
vendor_prefixed/guzzlehttp/psr7/src/LimitStream.php 0000644 00000010316 14720660247 0016605 0 ustar 00 stream = $stream;
$this->setLimit($limit);
$this->setOffset($offset);
}
public function eof() : bool
{
// Always return true if the underlying stream is EOF
if ($this->stream->eof()) {
return \true;
}
// No limit and the underlying stream is not at EOF
if ($this->limit === -1) {
return \false;
}
return $this->stream->tell() >= $this->offset + $this->limit;
}
/**
* Returns the size of the limited subset of data
*/
public function getSize() : ?int
{
if (null === ($length = $this->stream->getSize())) {
return null;
} elseif ($this->limit === -1) {
return $length - $this->offset;
} else {
return \min($this->limit, $length - $this->offset);
}
}
/**
* Allow for a bounded seek on the read limited stream
*/
public function seek($offset, $whence = \SEEK_SET) : void
{
if ($whence !== \SEEK_SET || $offset < 0) {
throw new \RuntimeException(\sprintf('Cannot seek to offset %s with whence %s', $offset, $whence));
}
$offset += $this->offset;
if ($this->limit !== -1) {
if ($offset > $this->offset + $this->limit) {
$offset = $this->offset + $this->limit;
}
}
$this->stream->seek($offset);
}
/**
* Give a relative tell()
*/
public function tell() : int
{
return $this->stream->tell() - $this->offset;
}
/**
* Set the offset to start limiting from
*
* @param int $offset Offset to seek to and begin byte limiting from
*
* @throws \RuntimeException if the stream cannot be seeked.
*/
public function setOffset(int $offset) : void
{
$current = $this->stream->tell();
if ($current !== $offset) {
// If the stream cannot seek to the offset position, then read to it
if ($this->stream->isSeekable()) {
$this->stream->seek($offset);
} elseif ($current > $offset) {
throw new \RuntimeException("Could not seek to stream offset {$offset}");
} else {
$this->stream->read($offset - $current);
}
}
$this->offset = $offset;
}
/**
* Set the limit of bytes that the decorator allows to be read from the
* stream.
*
* @param int $limit Number of bytes to allow to be read from the stream.
* Use -1 for no limit.
*/
public function setLimit(int $limit) : void
{
$this->limit = $limit;
}
public function read($length) : string
{
if ($this->limit === -1) {
return $this->stream->read($length);
}
// Check if the current position is less than the total allowed
// bytes + original offset
$remaining = $this->offset + $this->limit - $this->stream->tell();
if ($remaining > 0) {
// Only return the amount of requested data, ensuring that the byte
// limit is not exceeded
return $this->stream->read(\min($remaining, $length));
}
return '';
}
}
vendor_prefixed/guzzlehttp/psr7/src/MimeType.php 0000644 00000130251 14720660247 0016105 0 ustar 00 'application/vnd.1000minds.decision-model+xml', '3dml' => 'text/vnd.in3d.3dml', '3ds' => 'image/x-3ds', '3g2' => 'video/3gpp2', '3gp' => 'video/3gp', '3gpp' => 'video/3gpp', '3mf' => 'model/3mf', '7z' => 'application/x-7z-compressed', '7zip' => 'application/x-7z-compressed', '123' => 'application/vnd.lotus-1-2-3', 'aab' => 'application/x-authorware-bin', 'aac' => 'audio/aac', 'aam' => 'application/x-authorware-map', 'aas' => 'application/x-authorware-seg', 'abw' => 'application/x-abiword', 'ac' => 'application/vnd.nokia.n-gage.ac+xml', 'ac3' => 'audio/ac3', 'acc' => 'application/vnd.americandynamics.acc', 'ace' => 'application/x-ace-compressed', 'acu' => 'application/vnd.acucobol', 'acutc' => 'application/vnd.acucorp', 'adp' => 'audio/adpcm', 'adts' => 'audio/aac', 'aep' => 'application/vnd.audiograph', 'afm' => 'application/x-font-type1', 'afp' => 'application/vnd.ibm.modcap', 'age' => 'application/vnd.age', 'ahead' => 'application/vnd.ahead.space', 'ai' => 'application/pdf', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'air' => 'application/vnd.adobe.air-application-installer-package+zip', 'ait' => 'application/vnd.dvb.ait', 'ami' => 'application/vnd.amiga.ami', 'aml' => 'application/automationml-aml+xml', 'amlx' => 'application/automationml-amlx+zip', 'amr' => 'audio/amr', 'apk' => 'application/vnd.android.package-archive', 'apng' => 'image/apng', 'appcache' => 'text/cache-manifest', 'appinstaller' => 'application/appinstaller', 'application' => 'application/x-ms-application', 'appx' => 'application/appx', 'appxbundle' => 'application/appxbundle', 'apr' => 'application/vnd.lotus-approach', 'arc' => 'application/x-freearc', 'arj' => 'application/x-arj', 'asc' => 'application/pgp-signature', 'asf' => 'video/x-ms-asf', 'asm' => 'text/x-asm', 'aso' => 'application/vnd.accpac.simply.aso', 'asx' => 'video/x-ms-asf', 'atc' => 'application/vnd.acucorp', 'atom' => 'application/atom+xml', 'atomcat' => 'application/atomcat+xml', 'atomdeleted' => 'application/atomdeleted+xml', 'atomsvc' => 'application/atomsvc+xml', 'atx' => 'application/vnd.antix.game-component', 'au' => 'audio/x-au', 'avci' => 'image/avci', 'avcs' => 'image/avcs', 'avi' => 'video/x-msvideo', 'avif' => 'image/avif', 'aw' => 'application/applixware', 'azf' => 'application/vnd.airzip.filesecure.azf', 'azs' => 'application/vnd.airzip.filesecure.azs', 'azv' => 'image/vnd.airzip.accelerator.azv', 'azw' => 'application/vnd.amazon.ebook', 'b16' => 'image/vnd.pco.b16', 'bat' => 'application/x-msdownload', 'bcpio' => 'application/x-bcpio', 'bdf' => 'application/x-font-bdf', 'bdm' => 'application/vnd.syncml.dm+wbxml', 'bdoc' => 'application/x-bdoc', 'bed' => 'application/vnd.realvnc.bed', 'bh2' => 'application/vnd.fujitsu.oasysprs', 'bin' => 'application/octet-stream', 'blb' => 'application/x-blorb', 'blorb' => 'application/x-blorb', 'bmi' => 'application/vnd.bmi', 'bmml' => 'application/vnd.balsamiq.bmml+xml', 'bmp' => 'image/bmp', 'book' => 'application/vnd.framemaker', 'box' => 'application/vnd.previewsystems.box', 'boz' => 'application/x-bzip2', 'bpk' => 'application/octet-stream', 'bpmn' => 'application/octet-stream', 'bsp' => 'model/vnd.valve.source.compiled-map', 'btf' => 'image/prs.btif', 'btif' => 'image/prs.btif', 'buffer' => 'application/octet-stream', 'bz' => 'application/x-bzip', 'bz2' => 'application/x-bzip2', 'c' => 'text/x-c', 'c4d' => 'application/vnd.clonk.c4group', 'c4f' => 'application/vnd.clonk.c4group', 'c4g' => 'application/vnd.clonk.c4group', 'c4p' => 'application/vnd.clonk.c4group', 'c4u' => 'application/vnd.clonk.c4group', 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'cab' => 'application/vnd.ms-cab-compressed', 'caf' => 'audio/x-caf', 'cap' => 'application/vnd.tcpdump.pcap', 'car' => 'application/vnd.curl.car', 'cat' => 'application/vnd.ms-pki.seccat', 'cb7' => 'application/x-cbr', 'cba' => 'application/x-cbr', 'cbr' => 'application/x-cbr', 'cbt' => 'application/x-cbr', 'cbz' => 'application/x-cbr', 'cc' => 'text/x-c', 'cco' => 'application/x-cocoa', 'cct' => 'application/x-director', 'ccxml' => 'application/ccxml+xml', 'cdbcmsg' => 'application/vnd.contact.cmsg', 'cdf' => 'application/x-netcdf', 'cdfx' => 'application/cdfx+xml', 'cdkey' => 'application/vnd.mediastation.cdkey', 'cdmia' => 'application/cdmi-capability', 'cdmic' => 'application/cdmi-container', 'cdmid' => 'application/cdmi-domain', 'cdmio' => 'application/cdmi-object', 'cdmiq' => 'application/cdmi-queue', 'cdr' => 'application/cdr', 'cdx' => 'chemical/x-cdx', 'cdxml' => 'application/vnd.chemdraw+xml', 'cdy' => 'application/vnd.cinderella', 'cer' => 'application/pkix-cert', 'cfs' => 'application/x-cfs-compressed', 'cgm' => 'image/cgm', 'chat' => 'application/x-chat', 'chm' => 'application/vnd.ms-htmlhelp', 'chrt' => 'application/vnd.kde.kchart', 'cif' => 'chemical/x-cif', 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', 'cil' => 'application/vnd.ms-artgalry', 'cjs' => 'application/node', 'cla' => 'application/vnd.claymore', 'class' => 'application/octet-stream', 'cld' => 'model/vnd.cld', 'clkk' => 'application/vnd.crick.clicker.keyboard', 'clkp' => 'application/vnd.crick.clicker.palette', 'clkt' => 'application/vnd.crick.clicker.template', 'clkw' => 'application/vnd.crick.clicker.wordbank', 'clkx' => 'application/vnd.crick.clicker', 'clp' => 'application/x-msclip', 'cmc' => 'application/vnd.cosmocaller', 'cmdf' => 'chemical/x-cmdf', 'cml' => 'chemical/x-cml', 'cmp' => 'application/vnd.yellowriver-custom-menu', 'cmx' => 'image/x-cmx', 'cod' => 'application/vnd.rim.cod', 'coffee' => 'text/coffeescript', 'com' => 'application/x-msdownload', 'conf' => 'text/plain', 'cpio' => 'application/x-cpio', 'cpl' => 'application/cpl+xml', 'cpp' => 'text/x-c', 'cpt' => 'application/mac-compactpro', 'crd' => 'application/x-mscardfile', 'crl' => 'application/pkix-crl', 'crt' => 'application/x-x509-ca-cert', 'crx' => 'application/x-chrome-extension', 'cryptonote' => 'application/vnd.rig.cryptonote', 'csh' => 'application/x-csh', 'csl' => 'application/vnd.citationstyles.style+xml', 'csml' => 'chemical/x-csml', 'csp' => 'application/vnd.commonspace', 'csr' => 'application/octet-stream', 'css' => 'text/css', 'cst' => 'application/x-director', 'csv' => 'text/csv', 'cu' => 'application/cu-seeme', 'curl' => 'text/vnd.curl', 'cwl' => 'application/cwl', 'cww' => 'application/prs.cww', 'cxt' => 'application/x-director', 'cxx' => 'text/x-c', 'dae' => 'model/vnd.collada+xml', 'daf' => 'application/vnd.mobius.daf', 'dart' => 'application/vnd.dart', 'dataless' => 'application/vnd.fdsn.seed', 'davmount' => 'application/davmount+xml', 'dbf' => 'application/vnd.dbf', 'dbk' => 'application/docbook+xml', 'dcr' => 'application/x-director', 'dcurl' => 'text/vnd.curl.dcurl', 'dd2' => 'application/vnd.oma.dd2+xml', 'ddd' => 'application/vnd.fujixerox.ddd', 'ddf' => 'application/vnd.syncml.dmddf+xml', 'dds' => 'image/vnd.ms-dds', 'deb' => 'application/x-debian-package', 'def' => 'text/plain', 'deploy' => 'application/octet-stream', 'der' => 'application/x-x509-ca-cert', 'dfac' => 'application/vnd.dreamfactory', 'dgc' => 'application/x-dgc-compressed', 'dib' => 'image/bmp', 'dic' => 'text/x-c', 'dir' => 'application/x-director', 'dis' => 'application/vnd.mobius.dis', 'disposition-notification' => 'message/disposition-notification', 'dist' => 'application/octet-stream', 'distz' => 'application/octet-stream', 'djv' => 'image/vnd.djvu', 'djvu' => 'image/vnd.djvu', 'dll' => 'application/octet-stream', 'dmg' => 'application/x-apple-diskimage', 'dmn' => 'application/octet-stream', 'dmp' => 'application/vnd.tcpdump.pcap', 'dms' => 'application/octet-stream', 'dna' => 'application/vnd.dna', 'doc' => 'application/msword', 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dot' => 'application/msword', 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'dp' => 'application/vnd.osgi.dp', 'dpg' => 'application/vnd.dpgraph', 'dpx' => 'image/dpx', 'dra' => 'audio/vnd.dra', 'drle' => 'image/dicom-rle', 'dsc' => 'text/prs.lines.tag', 'dssc' => 'application/dssc+der', 'dtb' => 'application/x-dtbook+xml', 'dtd' => 'application/xml-dtd', 'dts' => 'audio/vnd.dts', 'dtshd' => 'audio/vnd.dts.hd', 'dump' => 'application/octet-stream', 'dvb' => 'video/vnd.dvb.file', 'dvi' => 'application/x-dvi', 'dwd' => 'application/atsc-dwd+xml', 'dwf' => 'model/vnd.dwf', 'dwg' => 'image/vnd.dwg', 'dxf' => 'image/vnd.dxf', 'dxp' => 'application/vnd.spotfire.dxp', 'dxr' => 'application/x-director', 'ear' => 'application/java-archive', 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', 'ecma' => 'application/ecmascript', 'edm' => 'application/vnd.novadigm.edm', 'edx' => 'application/vnd.novadigm.edx', 'efif' => 'application/vnd.picsel', 'ei6' => 'application/vnd.pg.osasli', 'elc' => 'application/octet-stream', 'emf' => 'image/emf', 'eml' => 'message/rfc822', 'emma' => 'application/emma+xml', 'emotionml' => 'application/emotionml+xml', 'emz' => 'application/x-msmetafile', 'eol' => 'audio/vnd.digital-winds', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'epub' => 'application/epub+zip', 'es3' => 'application/vnd.eszigno3+xml', 'esa' => 'application/vnd.osgi.subsystem', 'esf' => 'application/vnd.epson.esf', 'et3' => 'application/vnd.eszigno3+xml', 'etx' => 'text/x-setext', 'eva' => 'application/x-eva', 'evy' => 'application/x-envoy', 'exe' => 'application/octet-stream', 'exi' => 'application/exi', 'exp' => 'application/express', 'exr' => 'image/aces', 'ext' => 'application/vnd.novadigm.ext', 'ez' => 'application/andrew-inset', 'ez2' => 'application/vnd.ezpix-album', 'ez3' => 'application/vnd.ezpix-package', 'f' => 'text/x-fortran', 'f4v' => 'video/mp4', 'f77' => 'text/x-fortran', 'f90' => 'text/x-fortran', 'fbs' => 'image/vnd.fastbidsheet', 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', 'fcs' => 'application/vnd.isac.fcs', 'fdf' => 'application/vnd.fdf', 'fdt' => 'application/fdt+xml', 'fe_launch' => 'application/vnd.denovo.fcselayout-link', 'fg5' => 'application/vnd.fujitsu.oasysgp', 'fgd' => 'application/x-director', 'fh' => 'image/x-freehand', 'fh4' => 'image/x-freehand', 'fh5' => 'image/x-freehand', 'fh7' => 'image/x-freehand', 'fhc' => 'image/x-freehand', 'fig' => 'application/x-xfig', 'fits' => 'image/fits', 'flac' => 'audio/x-flac', 'fli' => 'video/x-fli', 'flo' => 'application/vnd.micrografx.flo', 'flv' => 'video/x-flv', 'flw' => 'application/vnd.kde.kivio', 'flx' => 'text/vnd.fmi.flexstor', 'fly' => 'text/vnd.fly', 'fm' => 'application/vnd.framemaker', 'fnc' => 'application/vnd.frogans.fnc', 'fo' => 'application/vnd.software602.filler.form+xml', 'for' => 'text/x-fortran', 'fpx' => 'image/vnd.fpx', 'frame' => 'application/vnd.framemaker', 'fsc' => 'application/vnd.fsc.weblaunch', 'fst' => 'image/vnd.fst', 'ftc' => 'application/vnd.fluxtime.clip', 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', 'fvt' => 'video/vnd.fvt', 'fxp' => 'application/vnd.adobe.fxp', 'fxpl' => 'application/vnd.adobe.fxp', 'fzs' => 'application/vnd.fuzzysheet', 'g2w' => 'application/vnd.geoplan', 'g3' => 'image/g3fax', 'g3w' => 'application/vnd.geospace', 'gac' => 'application/vnd.groove-account', 'gam' => 'application/x-tads', 'gbr' => 'application/rpki-ghostbusters', 'gca' => 'application/x-gca-compressed', 'gdl' => 'model/vnd.gdl', 'gdoc' => 'application/vnd.google-apps.document', 'ged' => 'text/vnd.familysearch.gedcom', 'geo' => 'application/vnd.dynageo', 'geojson' => 'application/geo+json', 'gex' => 'application/vnd.geometry-explorer', 'ggb' => 'application/vnd.geogebra.file', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', 'gim' => 'application/vnd.groove-identity-message', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', 'gml' => 'application/gml+xml', 'gmx' => 'application/vnd.gmx', 'gnumeric' => 'application/x-gnumeric', 'gpg' => 'application/gpg-keys', 'gph' => 'application/vnd.flographit', 'gpx' => 'application/gpx+xml', 'gqf' => 'application/vnd.grafeq', 'gqs' => 'application/vnd.grafeq', 'gram' => 'application/srgs', 'gramps' => 'application/x-gramps-xml', 'gre' => 'application/vnd.geometry-explorer', 'grv' => 'application/vnd.groove-injector', 'grxml' => 'application/srgs+xml', 'gsf' => 'application/x-font-ghostscript', 'gsheet' => 'application/vnd.google-apps.spreadsheet', 'gslides' => 'application/vnd.google-apps.presentation', 'gtar' => 'application/x-gtar', 'gtm' => 'application/vnd.groove-tool-message', 'gtw' => 'model/vnd.gtw', 'gv' => 'text/vnd.graphviz', 'gxf' => 'application/gxf', 'gxt' => 'application/vnd.geonext', 'gz' => 'application/gzip', 'gzip' => 'application/gzip', 'h' => 'text/x-c', 'h261' => 'video/h261', 'h263' => 'video/h263', 'h264' => 'video/h264', 'hal' => 'application/vnd.hal+xml', 'hbci' => 'application/vnd.hbci', 'hbs' => 'text/x-handlebars-template', 'hdd' => 'application/x-virtualbox-hdd', 'hdf' => 'application/x-hdf', 'heic' => 'image/heic', 'heics' => 'image/heic-sequence', 'heif' => 'image/heif', 'heifs' => 'image/heif-sequence', 'hej2' => 'image/hej2k', 'held' => 'application/atsc-held+xml', 'hh' => 'text/x-c', 'hjson' => 'application/hjson', 'hlp' => 'application/winhlp', 'hpgl' => 'application/vnd.hp-hpgl', 'hpid' => 'application/vnd.hp-hpid', 'hps' => 'application/vnd.hp-hps', 'hqx' => 'application/mac-binhex40', 'hsj2' => 'image/hsj2', 'htc' => 'text/x-component', 'htke' => 'application/vnd.kenameaapp', 'htm' => 'text/html', 'html' => 'text/html', 'hvd' => 'application/vnd.yamaha.hv-dic', 'hvp' => 'application/vnd.yamaha.hv-voice', 'hvs' => 'application/vnd.yamaha.hv-script', 'i2g' => 'application/vnd.intergeo', 'icc' => 'application/vnd.iccprofile', 'ice' => 'x-conference/x-cooltalk', 'icm' => 'application/vnd.iccprofile', 'ico' => 'image/x-icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', 'ifm' => 'application/vnd.shana.informed.formdata', 'iges' => 'model/iges', 'igl' => 'application/vnd.igloader', 'igm' => 'application/vnd.insors.igm', 'igs' => 'model/iges', 'igx' => 'application/vnd.micrografx.igx', 'iif' => 'application/vnd.shana.informed.interchange', 'img' => 'application/octet-stream', 'imp' => 'application/vnd.accpac.simply.imp', 'ims' => 'application/vnd.ms-ims', 'in' => 'text/plain', 'ini' => 'text/plain', 'ink' => 'application/inkml+xml', 'inkml' => 'application/inkml+xml', 'install' => 'application/x-install-instructions', 'iota' => 'application/vnd.astraea-software.iota', 'ipfix' => 'application/ipfix', 'ipk' => 'application/vnd.shana.informed.package', 'irm' => 'application/vnd.ibm.rights-management', 'irp' => 'application/vnd.irepository.package+xml', 'iso' => 'application/x-iso9660-image', 'itp' => 'application/vnd.shana.informed.formtemplate', 'its' => 'application/its+xml', 'ivp' => 'application/vnd.immervision-ivp', 'ivu' => 'application/vnd.immervision-ivu', 'jad' => 'text/vnd.sun.j2me.app-descriptor', 'jade' => 'text/jade', 'jam' => 'application/vnd.jam', 'jar' => 'application/java-archive', 'jardiff' => 'application/x-java-archive-diff', 'java' => 'text/x-java-source', 'jhc' => 'image/jphc', 'jisp' => 'application/vnd.jisp', 'jls' => 'image/jls', 'jlt' => 'application/vnd.hp-jlyt', 'jng' => 'image/x-jng', 'jnlp' => 'application/x-java-jnlp-file', 'joda' => 'application/vnd.joost.joda-archive', 'jp2' => 'image/jp2', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpf' => 'image/jpx', 'jpg' => 'image/jpeg', 'jpg2' => 'image/jp2', 'jpgm' => 'video/jpm', 'jpgv' => 'video/jpeg', 'jph' => 'image/jph', 'jpm' => 'video/jpm', 'jpx' => 'image/jpx', 'js' => 'application/javascript', 'json' => 'application/json', 'json5' => 'application/json5', 'jsonld' => 'application/ld+json', 'jsonml' => 'application/jsonml+json', 'jsx' => 'text/jsx', 'jt' => 'model/jt', 'jxr' => 'image/jxr', 'jxra' => 'image/jxra', 'jxrs' => 'image/jxrs', 'jxs' => 'image/jxs', 'jxsc' => 'image/jxsc', 'jxsi' => 'image/jxsi', 'jxss' => 'image/jxss', 'kar' => 'audio/midi', 'karbon' => 'application/vnd.kde.karbon', 'kdb' => 'application/octet-stream', 'kdbx' => 'application/x-keepass2', 'key' => 'application/x-iwork-keynote-sffkey', 'kfo' => 'application/vnd.kde.kformula', 'kia' => 'application/vnd.kidspiration', 'kml' => 'application/vnd.google-earth.kml+xml', 'kmz' => 'application/vnd.google-earth.kmz', 'kne' => 'application/vnd.kinar', 'knp' => 'application/vnd.kinar', 'kon' => 'application/vnd.kde.kontour', 'kpr' => 'application/vnd.kde.kpresenter', 'kpt' => 'application/vnd.kde.kpresenter', 'kpxx' => 'application/vnd.ds-keypoint', 'ksp' => 'application/vnd.kde.kspread', 'ktr' => 'application/vnd.kahootz', 'ktx' => 'image/ktx', 'ktx2' => 'image/ktx2', 'ktz' => 'application/vnd.kahootz', 'kwd' => 'application/vnd.kde.kword', 'kwt' => 'application/vnd.kde.kword', 'lasxml' => 'application/vnd.las.las+xml', 'latex' => 'application/x-latex', 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', 'les' => 'application/vnd.hhe.lesson-player', 'less' => 'text/less', 'lgr' => 'application/lgr+xml', 'lha' => 'application/octet-stream', 'link66' => 'application/vnd.route66.link66+xml', 'list' => 'text/plain', 'list3820' => 'application/vnd.ibm.modcap', 'listafp' => 'application/vnd.ibm.modcap', 'litcoffee' => 'text/coffeescript', 'lnk' => 'application/x-ms-shortcut', 'log' => 'text/plain', 'lostxml' => 'application/lost+xml', 'lrf' => 'application/octet-stream', 'lrm' => 'application/vnd.ms-lrm', 'ltf' => 'application/vnd.frogans.ltf', 'lua' => 'text/x-lua', 'luac' => 'application/x-lua-bytecode', 'lvp' => 'audio/vnd.lucent.voice', 'lwp' => 'application/vnd.lotus-wordpro', 'lzh' => 'application/octet-stream', 'm1v' => 'video/mpeg', 'm2a' => 'audio/mpeg', 'm2v' => 'video/mpeg', 'm3a' => 'audio/mpeg', 'm3u' => 'text/plain', 'm3u8' => 'application/vnd.apple.mpegurl', 'm4a' => 'audio/x-m4a', 'm4p' => 'application/mp4', 'm4s' => 'video/iso.segment', 'm4u' => 'application/vnd.mpegurl', 'm4v' => 'video/x-m4v', 'm13' => 'application/x-msmediaview', 'm14' => 'application/x-msmediaview', 'm21' => 'application/mp21', 'ma' => 'application/mathematica', 'mads' => 'application/mads+xml', 'maei' => 'application/mmt-aei+xml', 'mag' => 'application/vnd.ecowin.chart', 'maker' => 'application/vnd.framemaker', 'man' => 'text/troff', 'manifest' => 'text/cache-manifest', 'map' => 'application/json', 'mar' => 'application/octet-stream', 'markdown' => 'text/markdown', 'mathml' => 'application/mathml+xml', 'mb' => 'application/mathematica', 'mbk' => 'application/vnd.mobius.mbk', 'mbox' => 'application/mbox', 'mc1' => 'application/vnd.medcalcdata', 'mcd' => 'application/vnd.mcd', 'mcurl' => 'text/vnd.curl.mcurl', 'md' => 'text/markdown', 'mdb' => 'application/x-msaccess', 'mdi' => 'image/vnd.ms-modi', 'mdx' => 'text/mdx', 'me' => 'text/troff', 'mesh' => 'model/mesh', 'meta4' => 'application/metalink4+xml', 'metalink' => 'application/metalink+xml', 'mets' => 'application/mets+xml', 'mfm' => 'application/vnd.mfmp', 'mft' => 'application/rpki-manifest', 'mgp' => 'application/vnd.osgeo.mapguide.package', 'mgz' => 'application/vnd.proteus.magazine', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mie' => 'application/x-mie', 'mif' => 'application/vnd.mif', 'mime' => 'message/rfc822', 'mj2' => 'video/mj2', 'mjp2' => 'video/mj2', 'mjs' => 'text/javascript', 'mk3d' => 'video/x-matroska', 'mka' => 'audio/x-matroska', 'mkd' => 'text/x-markdown', 'mks' => 'video/x-matroska', 'mkv' => 'video/x-matroska', 'mlp' => 'application/vnd.dolby.mlp', 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', 'mmf' => 'application/vnd.smaf', 'mml' => 'text/mathml', 'mmr' => 'image/vnd.fujixerox.edmics-mmr', 'mng' => 'video/x-mng', 'mny' => 'application/x-msmoney', 'mobi' => 'application/x-mobipocket-ebook', 'mods' => 'application/mods+xml', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 'mp2a' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4s' => 'application/mp4', 'mp4v' => 'video/mp4', 'mp21' => 'application/mp21', 'mpc' => 'application/vnd.mophun.certificate', 'mpd' => 'application/dash+xml', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpf' => 'application/media-policy-dataset+xml', 'mpg' => 'video/mpeg', 'mpg4' => 'video/mp4', 'mpga' => 'audio/mpeg', 'mpkg' => 'application/vnd.apple.installer+xml', 'mpm' => 'application/vnd.blueice.multipass', 'mpn' => 'application/vnd.mophun.application', 'mpp' => 'application/vnd.ms-project', 'mpt' => 'application/vnd.ms-project', 'mpy' => 'application/vnd.ibm.minipay', 'mqy' => 'application/vnd.mobius.mqy', 'mrc' => 'application/marc', 'mrcx' => 'application/marcxml+xml', 'ms' => 'text/troff', 'mscml' => 'application/mediaservercontrol+xml', 'mseed' => 'application/vnd.fdsn.mseed', 'mseq' => 'application/vnd.mseq', 'msf' => 'application/vnd.epson.msf', 'msg' => 'application/vnd.ms-outlook', 'msh' => 'model/mesh', 'msi' => 'application/x-msdownload', 'msix' => 'application/msix', 'msixbundle' => 'application/msixbundle', 'msl' => 'application/vnd.mobius.msl', 'msm' => 'application/octet-stream', 'msp' => 'application/octet-stream', 'msty' => 'application/vnd.muvee.style', 'mtl' => 'model/mtl', 'mts' => 'model/vnd.mts', 'mus' => 'application/vnd.musician', 'musd' => 'application/mmt-usd+xml', 'musicxml' => 'application/vnd.recordare.musicxml+xml', 'mvb' => 'application/x-msmediaview', 'mvt' => 'application/vnd.mapbox-vector-tile', 'mwf' => 'application/vnd.mfer', 'mxf' => 'application/mxf', 'mxl' => 'application/vnd.recordare.musicxml', 'mxmf' => 'audio/mobile-xmf', 'mxml' => 'application/xv+xml', 'mxs' => 'application/vnd.triscape.mxs', 'mxu' => 'video/vnd.mpegurl', 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', 'n3' => 'text/n3', 'nb' => 'application/mathematica', 'nbp' => 'application/vnd.wolfram.player', 'nc' => 'application/x-netcdf', 'ncx' => 'application/x-dtbncx+xml', 'nfo' => 'text/x-nfo', 'ngdat' => 'application/vnd.nokia.n-gage.data', 'nitf' => 'application/vnd.nitf', 'nlu' => 'application/vnd.neurolanguage.nlu', 'nml' => 'application/vnd.enliven', 'nnd' => 'application/vnd.noblenet-directory', 'nns' => 'application/vnd.noblenet-sealer', 'nnw' => 'application/vnd.noblenet-web', 'npx' => 'image/vnd.net-fpx', 'nq' => 'application/n-quads', 'nsc' => 'application/x-conference', 'nsf' => 'application/vnd.lotus-notes', 'nt' => 'application/n-triples', 'ntf' => 'application/vnd.nitf', 'numbers' => 'application/x-iwork-numbers-sffnumbers', 'nzb' => 'application/x-nzb', 'oa2' => 'application/vnd.fujitsu.oasys2', 'oa3' => 'application/vnd.fujitsu.oasys3', 'oas' => 'application/vnd.fujitsu.oasys', 'obd' => 'application/x-msbinder', 'obgx' => 'application/vnd.openblox.game+xml', 'obj' => 'model/obj', 'oda' => 'application/oda', 'odb' => 'application/vnd.oasis.opendocument.database', 'odc' => 'application/vnd.oasis.opendocument.chart', 'odf' => 'application/vnd.oasis.opendocument.formula', 'odft' => 'application/vnd.oasis.opendocument.formula-template', 'odg' => 'application/vnd.oasis.opendocument.graphics', 'odi' => 'application/vnd.oasis.opendocument.image', 'odm' => 'application/vnd.oasis.opendocument.text-master', 'odp' => 'application/vnd.oasis.opendocument.presentation', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'odt' => 'application/vnd.oasis.opendocument.text', 'oga' => 'audio/ogg', 'ogex' => 'model/vnd.opengex', 'ogg' => 'audio/ogg', 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'omdoc' => 'application/omdoc+xml', 'onepkg' => 'application/onenote', 'onetmp' => 'application/onenote', 'onetoc' => 'application/onenote', 'onetoc2' => 'application/onenote', 'opf' => 'application/oebps-package+xml', 'opml' => 'text/x-opml', 'oprc' => 'application/vnd.palm', 'opus' => 'audio/ogg', 'org' => 'text/x-org', 'osf' => 'application/vnd.yamaha.openscoreformat', 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'osm' => 'application/vnd.openstreetmap.data+xml', 'otc' => 'application/vnd.oasis.opendocument.chart-template', 'otf' => 'font/otf', 'otg' => 'application/vnd.oasis.opendocument.graphics-template', 'oth' => 'application/vnd.oasis.opendocument.text-web', 'oti' => 'application/vnd.oasis.opendocument.image-template', 'otp' => 'application/vnd.oasis.opendocument.presentation-template', 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', 'ott' => 'application/vnd.oasis.opendocument.text-template', 'ova' => 'application/x-virtualbox-ova', 'ovf' => 'application/x-virtualbox-ovf', 'owl' => 'application/rdf+xml', 'oxps' => 'application/oxps', 'oxt' => 'application/vnd.openofficeorg.extension', 'p' => 'text/x-pascal', 'p7a' => 'application/x-pkcs7-signature', 'p7b' => 'application/x-pkcs7-certificates', 'p7c' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7r' => 'application/x-pkcs7-certreqresp', 'p7s' => 'application/pkcs7-signature', 'p8' => 'application/pkcs8', 'p10' => 'application/x-pkcs10', 'p12' => 'application/x-pkcs12', 'pac' => 'application/x-ns-proxy-autoconfig', 'pages' => 'application/x-iwork-pages-sffpages', 'pas' => 'text/x-pascal', 'paw' => 'application/vnd.pawaafile', 'pbd' => 'application/vnd.powerbuilder6', 'pbm' => 'image/x-portable-bitmap', 'pcap' => 'application/vnd.tcpdump.pcap', 'pcf' => 'application/x-font-pcf', 'pcl' => 'application/vnd.hp-pcl', 'pclxl' => 'application/vnd.hp-pclxl', 'pct' => 'image/x-pict', 'pcurl' => 'application/vnd.curl.pcurl', 'pcx' => 'image/x-pcx', 'pdb' => 'application/x-pilot', 'pde' => 'text/x-processing', 'pdf' => 'application/pdf', 'pem' => 'application/x-x509-user-cert', 'pfa' => 'application/x-font-type1', 'pfb' => 'application/x-font-type1', 'pfm' => 'application/x-font-type1', 'pfr' => 'application/font-tdpfr', 'pfx' => 'application/x-pkcs12', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', 'pgp' => 'application/pgp', 'phar' => 'application/octet-stream', 'php' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', 'php4' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'phtml' => 'application/x-httpd-php', 'pic' => 'image/x-pict', 'pkg' => 'application/octet-stream', 'pki' => 'application/pkixcmp', 'pkipath' => 'application/pkix-pkipath', 'pkpass' => 'application/vnd.apple.pkpass', 'pl' => 'application/x-perl', 'plb' => 'application/vnd.3gpp.pic-bw-large', 'plc' => 'application/vnd.mobius.plc', 'plf' => 'application/vnd.pocketlearn', 'pls' => 'application/pls+xml', 'pm' => 'application/x-perl', 'pml' => 'application/vnd.ctc-posml', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'portpkg' => 'application/vnd.macports.portpkg', 'pot' => 'application/vnd.ms-powerpoint', 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppa' => 'application/vnd.ms-powerpoint', 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'ppd' => 'application/vnd.cups-ppd', 'ppm' => 'image/x-portable-pixmap', 'pps' => 'application/vnd.ms-powerpoint', 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'ppt' => 'application/powerpoint', 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pqa' => 'application/vnd.palm', 'prc' => 'model/prc', 'pre' => 'application/vnd.lotus-freelance', 'prf' => 'application/pics-rules', 'provx' => 'application/provenance+xml', 'ps' => 'application/postscript', 'psb' => 'application/vnd.3gpp.pic-bw-small', 'psd' => 'application/x-photoshop', 'psf' => 'application/x-font-linux-psf', 'pskcxml' => 'application/pskc+xml', 'pti' => 'image/prs.pti', 'ptid' => 'application/vnd.pvi.ptid1', 'pub' => 'application/x-mspublisher', 'pvb' => 'application/vnd.3gpp.pic-bw-var', 'pwn' => 'application/vnd.3m.post-it-notes', 'pya' => 'audio/vnd.ms-playready.media.pya', 'pyo' => 'model/vnd.pytha.pyox', 'pyox' => 'model/vnd.pytha.pyox', 'pyv' => 'video/vnd.ms-playready.media.pyv', 'qam' => 'application/vnd.epson.quickanime', 'qbo' => 'application/vnd.intu.qbo', 'qfx' => 'application/vnd.intu.qfx', 'qps' => 'application/vnd.publishare-delta-tree', 'qt' => 'video/quicktime', 'qwd' => 'application/vnd.quark.quarkxpress', 'qwt' => 'application/vnd.quark.quarkxpress', 'qxb' => 'application/vnd.quark.quarkxpress', 'qxd' => 'application/vnd.quark.quarkxpress', 'qxl' => 'application/vnd.quark.quarkxpress', 'qxt' => 'application/vnd.quark.quarkxpress', 'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'raml' => 'application/raml+yaml', 'rapd' => 'application/route-apd+xml', 'rar' => 'application/x-rar', 'ras' => 'image/x-cmu-raster', 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', 'rdf' => 'application/rdf+xml', 'rdz' => 'application/vnd.data-vision.rdz', 'relo' => 'application/p2p-overlay+xml', 'rep' => 'application/vnd.businessobjects', 'res' => 'application/x-dtbresource+xml', 'rgb' => 'image/x-rgb', 'rif' => 'application/reginfo+xml', 'rip' => 'audio/vnd.rip', 'ris' => 'application/x-research-info-systems', 'rl' => 'application/resource-lists+xml', 'rlc' => 'image/vnd.fujixerox.edmics-rlc', 'rld' => 'application/resource-lists-diff+xml', 'rm' => 'audio/x-pn-realaudio', 'rmi' => 'audio/midi', 'rmp' => 'audio/x-pn-realaudio-plugin', 'rms' => 'application/vnd.jcp.javame.midlet-rms', 'rmvb' => 'application/vnd.rn-realmedia-vbr', 'rnc' => 'application/relax-ng-compact-syntax', 'rng' => 'application/xml', 'roa' => 'application/rpki-roa', 'roff' => 'text/troff', 'rp9' => 'application/vnd.cloanto.rp9', 'rpm' => 'audio/x-pn-realaudio-plugin', 'rpss' => 'application/vnd.nokia.radio-presets', 'rpst' => 'application/vnd.nokia.radio-preset', 'rq' => 'application/sparql-query', 'rs' => 'application/rls-services+xml', 'rsa' => 'application/x-pkcs7', 'rsat' => 'application/atsc-rsat+xml', 'rsd' => 'application/rsd+xml', 'rsheet' => 'application/urc-ressheet+xml', 'rss' => 'application/rss+xml', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'run' => 'application/x-makeself', 'rusd' => 'application/route-usd+xml', 'rv' => 'video/vnd.rn-realvideo', 's' => 'text/x-asm', 's3m' => 'audio/s3m', 'saf' => 'application/vnd.yamaha.smaf-audio', 'sass' => 'text/x-sass', 'sbml' => 'application/sbml+xml', 'sc' => 'application/vnd.ibm.secure-container', 'scd' => 'application/x-msschedule', 'scm' => 'application/vnd.lotus-screencam', 'scq' => 'application/scvp-cv-request', 'scs' => 'application/scvp-cv-response', 'scss' => 'text/x-scss', 'scurl' => 'text/vnd.curl.scurl', 'sda' => 'application/vnd.stardivision.draw', 'sdc' => 'application/vnd.stardivision.calc', 'sdd' => 'application/vnd.stardivision.impress', 'sdkd' => 'application/vnd.solent.sdkm+xml', 'sdkm' => 'application/vnd.solent.sdkm+xml', 'sdp' => 'application/sdp', 'sdw' => 'application/vnd.stardivision.writer', 'sea' => 'application/octet-stream', 'see' => 'application/vnd.seemail', 'seed' => 'application/vnd.fdsn.seed', 'sema' => 'application/vnd.sema', 'semd' => 'application/vnd.semd', 'semf' => 'application/vnd.semf', 'senmlx' => 'application/senml+xml', 'sensmlx' => 'application/sensml+xml', 'ser' => 'application/java-serialized-object', 'setpay' => 'application/set-payment-initiation', 'setreg' => 'application/set-registration-initiation', 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', 'sfs' => 'application/vnd.spotfire.sfs', 'sfv' => 'text/x-sfv', 'sgi' => 'image/sgi', 'sgl' => 'application/vnd.stardivision.writer-global', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'shex' => 'text/shex', 'shf' => 'application/shf+xml', 'shtml' => 'text/html', 'sid' => 'image/x-mrsid-image', 'sieve' => 'application/sieve', 'sig' => 'application/pgp-signature', 'sil' => 'audio/silk', 'silo' => 'model/mesh', 'sis' => 'application/vnd.symbian.install', 'sisx' => 'application/vnd.symbian.install', 'sit' => 'application/x-stuffit', 'sitx' => 'application/x-stuffitx', 'siv' => 'application/sieve', 'skd' => 'application/vnd.koan', 'skm' => 'application/vnd.koan', 'skp' => 'application/vnd.koan', 'skt' => 'application/vnd.koan', 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 'slim' => 'text/slim', 'slm' => 'text/slim', 'sls' => 'application/route-s-tsid+xml', 'slt' => 'application/vnd.epson.salt', 'sm' => 'application/vnd.stepmania.stepchart', 'smf' => 'application/vnd.stardivision.math', 'smi' => 'application/smil', 'smil' => 'application/smil', 'smv' => 'video/x-smv', 'smzip' => 'application/vnd.stepmania.package', 'snd' => 'audio/basic', 'snf' => 'application/x-font-snf', 'so' => 'application/octet-stream', 'spc' => 'application/x-pkcs7-certificates', 'spdx' => 'text/spdx', 'spf' => 'application/vnd.yamaha.smaf-phrase', 'spl' => 'application/x-futuresplash', 'spot' => 'text/vnd.in3d.spot', 'spp' => 'application/scvp-vp-response', 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'sql' => 'application/x-sql', 'src' => 'application/x-wais-source', 'srt' => 'application/x-subrip', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'ssdl' => 'application/ssdl+xml', 'sse' => 'application/vnd.kodak-descriptor', 'ssf' => 'application/vnd.epson.ssf', 'ssml' => 'application/ssml+xml', 'sst' => 'application/octet-stream', 'st' => 'application/vnd.sailingtracker.track', 'stc' => 'application/vnd.sun.xml.calc.template', 'std' => 'application/vnd.sun.xml.draw.template', 'step' => 'application/STEP', 'stf' => 'application/vnd.wt.stf', 'sti' => 'application/vnd.sun.xml.impress.template', 'stk' => 'application/hyperstudio', 'stl' => 'model/stl', 'stp' => 'application/STEP', 'stpx' => 'model/step+xml', 'stpxz' => 'model/step-xml+zip', 'stpz' => 'model/step+zip', 'str' => 'application/vnd.pg.format', 'stw' => 'application/vnd.sun.xml.writer.template', 'styl' => 'text/stylus', 'stylus' => 'text/stylus', 'sub' => 'text/vnd.dvb.subtitle', 'sus' => 'application/vnd.sus-calendar', 'susp' => 'application/vnd.sus-calendar', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svc' => 'application/vnd.dvb.service', 'svd' => 'application/vnd.svd', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', 'swa' => 'application/x-director', 'swf' => 'application/x-shockwave-flash', 'swi' => 'application/vnd.aristanetworks.swi', 'swidtag' => 'application/swid+xml', 'sxc' => 'application/vnd.sun.xml.calc', 'sxd' => 'application/vnd.sun.xml.draw', 'sxg' => 'application/vnd.sun.xml.writer.global', 'sxi' => 'application/vnd.sun.xml.impress', 'sxm' => 'application/vnd.sun.xml.math', 'sxw' => 'application/vnd.sun.xml.writer', 't' => 'text/troff', 't3' => 'application/x-t3vm-image', 't38' => 'image/t38', 'taglet' => 'application/vnd.mynfc', 'tao' => 'application/vnd.tao.intent-module-archive', 'tap' => 'image/vnd.tencent.tap', 'tar' => 'application/x-tar', 'tcap' => 'application/vnd.3gpp2.tcap', 'tcl' => 'application/x-tcl', 'td' => 'application/urc-targetdesc+xml', 'teacher' => 'application/vnd.smart.teacher', 'tei' => 'application/tei+xml', 'teicorpus' => 'application/tei+xml', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'text' => 'text/plain', 'tfi' => 'application/thraud+xml', 'tfm' => 'application/x-tex-tfm', 'tfx' => 'image/tiff-fx', 'tga' => 'image/x-tga', 'tgz' => 'application/x-tar', 'thmx' => 'application/vnd.ms-officetheme', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'tk' => 'application/x-tcl', 'tmo' => 'application/vnd.tmobile-livetv', 'toml' => 'application/toml', 'torrent' => 'application/x-bittorrent', 'tpl' => 'application/vnd.groove-tool-template', 'tpt' => 'application/vnd.trid.tpt', 'tr' => 'text/troff', 'tra' => 'application/vnd.trueapp', 'trig' => 'application/trig', 'trm' => 'application/x-msterminal', 'ts' => 'video/mp2t', 'tsd' => 'application/timestamped-data', 'tsv' => 'text/tab-separated-values', 'ttc' => 'font/collection', 'ttf' => 'font/ttf', 'ttl' => 'text/turtle', 'ttml' => 'application/ttml+xml', 'twd' => 'application/vnd.simtech-mindmapper', 'twds' => 'application/vnd.simtech-mindmapper', 'txd' => 'application/vnd.genomatix.tuxedo', 'txf' => 'application/vnd.mobius.txf', 'txt' => 'text/plain', 'u3d' => 'model/u3d', 'u8dsn' => 'message/global-delivery-status', 'u8hdr' => 'message/global-headers', 'u8mdn' => 'message/global-disposition-notification', 'u8msg' => 'message/global', 'u32' => 'application/x-authorware-bin', 'ubj' => 'application/ubjson', 'udeb' => 'application/x-debian-package', 'ufd' => 'application/vnd.ufdl', 'ufdl' => 'application/vnd.ufdl', 'ulx' => 'application/x-glulx', 'umj' => 'application/vnd.umajin', 'unityweb' => 'application/vnd.unity', 'uo' => 'application/vnd.uoml+xml', 'uoml' => 'application/vnd.uoml+xml', 'uri' => 'text/uri-list', 'uris' => 'text/uri-list', 'urls' => 'text/uri-list', 'usda' => 'model/vnd.usda', 'usdz' => 'model/vnd.usdz+zip', 'ustar' => 'application/x-ustar', 'utz' => 'application/vnd.uiq.theme', 'uu' => 'text/x-uuencode', 'uva' => 'audio/vnd.dece.audio', 'uvd' => 'application/vnd.dece.data', 'uvf' => 'application/vnd.dece.data', 'uvg' => 'image/vnd.dece.graphic', 'uvh' => 'video/vnd.dece.hd', 'uvi' => 'image/vnd.dece.graphic', 'uvm' => 'video/vnd.dece.mobile', 'uvp' => 'video/vnd.dece.pd', 'uvs' => 'video/vnd.dece.sd', 'uvt' => 'application/vnd.dece.ttml+xml', 'uvu' => 'video/vnd.uvvu.mp4', 'uvv' => 'video/vnd.dece.video', 'uvva' => 'audio/vnd.dece.audio', 'uvvd' => 'application/vnd.dece.data', 'uvvf' => 'application/vnd.dece.data', 'uvvg' => 'image/vnd.dece.graphic', 'uvvh' => 'video/vnd.dece.hd', 'uvvi' => 'image/vnd.dece.graphic', 'uvvm' => 'video/vnd.dece.mobile', 'uvvp' => 'video/vnd.dece.pd', 'uvvs' => 'video/vnd.dece.sd', 'uvvt' => 'application/vnd.dece.ttml+xml', 'uvvu' => 'video/vnd.uvvu.mp4', 'uvvv' => 'video/vnd.dece.video', 'uvvx' => 'application/vnd.dece.unspecified', 'uvvz' => 'application/vnd.dece.zip', 'uvx' => 'application/vnd.dece.unspecified', 'uvz' => 'application/vnd.dece.zip', 'vbox' => 'application/x-virtualbox-vbox', 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', 'vcard' => 'text/vcard', 'vcd' => 'application/x-cdlink', 'vcf' => 'text/x-vcard', 'vcg' => 'application/vnd.groove-vcard', 'vcs' => 'text/x-vcalendar', 'vcx' => 'application/vnd.vcx', 'vdi' => 'application/x-virtualbox-vdi', 'vds' => 'model/vnd.sap.vds', 'vhd' => 'application/x-virtualbox-vhd', 'vis' => 'application/vnd.visionary', 'viv' => 'video/vnd.vivo', 'vlc' => 'application/videolan', 'vmdk' => 'application/x-virtualbox-vmdk', 'vob' => 'video/x-ms-vob', 'vor' => 'application/vnd.stardivision.writer', 'vox' => 'application/x-authorware-bin', 'vrml' => 'model/vrml', 'vsd' => 'application/vnd.visio', 'vsf' => 'application/vnd.vsf', 'vss' => 'application/vnd.visio', 'vst' => 'application/vnd.visio', 'vsw' => 'application/vnd.visio', 'vtf' => 'image/vnd.valve.source.texture', 'vtt' => 'text/vtt', 'vtu' => 'model/vnd.vtu', 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', 'wadl' => 'application/vnd.sun.wadl+xml', 'war' => 'application/java-archive', 'wasm' => 'application/wasm', 'wav' => 'audio/x-wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', 'wbs' => 'application/vnd.criticaltools.wbs+xml', 'wbxml' => 'application/wbxml', 'wcm' => 'application/vnd.ms-works', 'wdb' => 'application/vnd.ms-works', 'wdp' => 'image/vnd.ms-photo', 'weba' => 'audio/webm', 'webapp' => 'application/x-web-app-manifest+json', 'webm' => 'video/webm', 'webmanifest' => 'application/manifest+json', 'webp' => 'image/webp', 'wg' => 'application/vnd.pmi.widget', 'wgsl' => 'text/wgsl', 'wgt' => 'application/widget', 'wif' => 'application/watcherinfo+xml', 'wks' => 'application/vnd.ms-works', 'wm' => 'video/x-ms-wm', 'wma' => 'audio/x-ms-wma', 'wmd' => 'application/x-ms-wmd', 'wmf' => 'image/wmf', 'wml' => 'text/vnd.wap.wml', 'wmlc' => 'application/wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wmx' => 'video/x-ms-wmx', 'wmz' => 'application/x-msmetafile', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'word' => 'application/msword', 'wpd' => 'application/vnd.wordperfect', 'wpl' => 'application/vnd.ms-wpl', 'wps' => 'application/vnd.ms-works', 'wqd' => 'application/vnd.wqd', 'wri' => 'application/x-mswrite', 'wrl' => 'model/vrml', 'wsc' => 'message/vnd.wfa.wsc', 'wsdl' => 'application/wsdl+xml', 'wspolicy' => 'application/wspolicy+xml', 'wtb' => 'application/vnd.webturbo', 'wvx' => 'video/x-ms-wvx', 'x3d' => 'model/x3d+xml', 'x3db' => 'model/x3d+fastinfoset', 'x3dbz' => 'model/x3d+binary', 'x3dv' => 'model/x3d-vrml', 'x3dvz' => 'model/x3d+vrml', 'x3dz' => 'model/x3d+xml', 'x32' => 'application/x-authorware-bin', 'x_b' => 'model/vnd.parasolid.transmit.binary', 'x_t' => 'model/vnd.parasolid.transmit.text', 'xaml' => 'application/xaml+xml', 'xap' => 'application/x-silverlight-app', 'xar' => 'application/vnd.xara', 'xav' => 'application/xcap-att+xml', 'xbap' => 'application/x-ms-xbap', 'xbd' => 'application/vnd.fujixerox.docuworks.binder', 'xbm' => 'image/x-xbitmap', 'xca' => 'application/xcap-caps+xml', 'xcs' => 'application/calendar+xml', 'xdf' => 'application/xcap-diff+xml', 'xdm' => 'application/vnd.syncml.dm+xml', 'xdp' => 'application/vnd.adobe.xdp+xml', 'xdssc' => 'application/dssc+xml', 'xdw' => 'application/vnd.fujixerox.docuworks', 'xel' => 'application/xcap-el+xml', 'xenc' => 'application/xenc+xml', 'xer' => 'application/patch-ops-error+xml', 'xfdf' => 'application/xfdf', 'xfdl' => 'application/vnd.xfdl', 'xht' => 'application/xhtml+xml', 'xhtm' => 'application/vnd.pwg-xhtml-print+xml', 'xhtml' => 'application/xhtml+xml', 'xhvml' => 'application/xv+xml', 'xif' => 'image/vnd.xiff', 'xl' => 'application/excel', 'xla' => 'application/vnd.ms-excel', 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'xlc' => 'application/vnd.ms-excel', 'xlf' => 'application/xliff+xml', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlt' => 'application/vnd.ms-excel', 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'xlw' => 'application/vnd.ms-excel', 'xm' => 'audio/xm', 'xml' => 'application/xml', 'xns' => 'application/xcap-ns+xml', 'xo' => 'application/vnd.olpc-sugar', 'xop' => 'application/xop+xml', 'xpi' => 'application/x-xpinstall', 'xpl' => 'application/xproc+xml', 'xpm' => 'image/x-xpixmap', 'xpr' => 'application/vnd.is-xpr', 'xps' => 'application/vnd.ms-xpsdocument', 'xpw' => 'application/vnd.intercon.formnet', 'xpx' => 'application/vnd.intercon.formnet', 'xsd' => 'application/xml', 'xsf' => 'application/prs.xsf+xml', 'xsl' => 'application/xml', 'xslt' => 'application/xslt+xml', 'xsm' => 'application/vnd.syncml+xml', 'xspf' => 'application/xspf+xml', 'xul' => 'application/vnd.mozilla.xul+xml', 'xvm' => 'application/xv+xml', 'xvml' => 'application/xv+xml', 'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', 'xz' => 'application/x-xz', 'yaml' => 'text/yaml', 'yang' => 'application/yang', 'yin' => 'application/yin+xml', 'yml' => 'text/yaml', 'ymp' => 'text/x-suse-ymp', 'z' => 'application/x-compress', 'z1' => 'application/x-zmachine', 'z2' => 'application/x-zmachine', 'z3' => 'application/x-zmachine', 'z4' => 'application/x-zmachine', 'z5' => 'application/x-zmachine', 'z6' => 'application/x-zmachine', 'z7' => 'application/x-zmachine', 'z8' => 'application/x-zmachine', 'zaz' => 'application/vnd.zzazz.deck+xml', 'zip' => 'application/zip', 'zir' => 'application/vnd.zul', 'zirz' => 'application/vnd.zul', 'zmm' => 'application/vnd.handheld-entertainment+xml', 'zsh' => 'text/x-scriptzsh'];
/**
* Determines the mimetype of a file by looking at its extension.
*
* @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json
*/
public static function fromFilename(string $filename) : ?string
{
return self::fromExtension(\pathinfo($filename, \PATHINFO_EXTENSION));
}
/**
* Maps a file extensions to a mimetype.
*
* @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json
*/
public static function fromExtension(string $extension) : ?string
{
return self::MIME_TYPES[\strtolower($extension)] ?? null;
}
}
vendor_prefixed/guzzlehttp/psr7/src/Stream.php 0000644 00000016466 14720660247 0015622 0 ustar 00 size = $options['size'];
}
$this->customMetadata = $options['metadata'] ?? [];
$this->stream = $stream;
$meta = \stream_get_meta_data($this->stream);
$this->seekable = $meta['seekable'];
$this->readable = (bool) \preg_match(self::READABLE_MODES, $meta['mode']);
$this->writable = (bool) \preg_match(self::WRITABLE_MODES, $meta['mode']);
$this->uri = $this->getMetadata('uri');
}
/**
* Closes the stream when the destructed
*/
public function __destruct()
{
$this->close();
}
public function __toString() : string
{
try {
if ($this->isSeekable()) {
$this->seek(0);
}
return $this->getContents();
} catch (\Throwable $e) {
if (\PHP_VERSION_ID >= 70400) {
throw $e;
}
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
return '';
}
}
public function getContents() : string
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
if (!$this->readable) {
throw new \RuntimeException('Cannot read from non-readable stream');
}
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryGetContents($this->stream);
}
public function close() : void
{
if (isset($this->stream)) {
if (\is_resource($this->stream)) {
\fclose($this->stream);
}
$this->detach();
}
}
public function detach()
{
if (!isset($this->stream)) {
return null;
}
$result = $this->stream;
unset($this->stream);
$this->size = $this->uri = null;
$this->readable = $this->writable = $this->seekable = \false;
return $result;
}
public function getSize() : ?int
{
if ($this->size !== null) {
return $this->size;
}
if (!isset($this->stream)) {
return null;
}
// Clear the stat cache if the stream has a URI
if ($this->uri) {
\clearstatcache(\true, $this->uri);
}
$stats = \fstat($this->stream);
if (\is_array($stats) && isset($stats['size'])) {
$this->size = $stats['size'];
return $this->size;
}
return null;
}
public function isReadable() : bool
{
return $this->readable;
}
public function isWritable() : bool
{
return $this->writable;
}
public function isSeekable() : bool
{
return $this->seekable;
}
public function eof() : bool
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
return \feof($this->stream);
}
public function tell() : int
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
$result = \ftell($this->stream);
if ($result === \false) {
throw new \RuntimeException('Unable to determine stream position');
}
return $result;
}
public function rewind() : void
{
$this->seek(0);
}
public function seek($offset, $whence = \SEEK_SET) : void
{
$whence = (int) $whence;
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
if (!$this->seekable) {
throw new \RuntimeException('Stream is not seekable');
}
if (\fseek($this->stream, $offset, $whence) === -1) {
throw new \RuntimeException('Unable to seek to stream position ' . $offset . ' with whence ' . \var_export($whence, \true));
}
}
public function read($length) : string
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
if (!$this->readable) {
throw new \RuntimeException('Cannot read from non-readable stream');
}
if ($length < 0) {
throw new \RuntimeException('Length parameter cannot be negative');
}
if (0 === $length) {
return '';
}
try {
$string = \fread($this->stream, $length);
} catch (\Exception $e) {
throw new \RuntimeException('Unable to read from stream', 0, $e);
}
if (\false === $string) {
throw new \RuntimeException('Unable to read from stream');
}
return $string;
}
public function write($string) : int
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
if (!$this->writable) {
throw new \RuntimeException('Cannot write to a non-writable stream');
}
// We can't know the size after writing anything
$this->size = null;
$result = \fwrite($this->stream, $string);
if ($result === \false) {
throw new \RuntimeException('Unable to write to stream');
}
return $result;
}
/**
* @return mixed
*/
public function getMetadata($key = null)
{
if (!isset($this->stream)) {
return $key ? null : [];
} elseif (!$key) {
return $this->customMetadata + \stream_get_meta_data($this->stream);
} elseif (isset($this->customMetadata[$key])) {
return $this->customMetadata[$key];
}
$meta = \stream_get_meta_data($this->stream);
return $meta[$key] ?? null;
}
}
vendor_prefixed/guzzlehttp/psr7/src/Uri.php 0000644 00000053363 14720660247 0015123 0 ustar 00 80, 'https' => 443, 'ftp' => 21, 'gopher' => 70, 'nntp' => 119, 'news' => 119, 'telnet' => 23, 'tn3270' => 23, 'imap' => 143, 'pop' => 110, 'ldap' => 389];
/**
* Unreserved characters for use in a regex.
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
*/
private const CHAR_UNRESERVED = 'a-zA-Z0-9_\\-\\.~';
/**
* Sub-delims for use in a regex.
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.2
*/
private const CHAR_SUB_DELIMS = '!\\$&\'\\(\\)\\*\\+,;=';
private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26'];
/** @var string Uri scheme. */
private $scheme = '';
/** @var string Uri user info. */
private $userInfo = '';
/** @var string Uri host. */
private $host = '';
/** @var int|null Uri port. */
private $port;
/** @var string Uri path. */
private $path = '';
/** @var string Uri query string. */
private $query = '';
/** @var string Uri fragment. */
private $fragment = '';
/** @var string|null String representation */
private $composedComponents;
public function __construct(string $uri = '')
{
if ($uri !== '') {
$parts = self::parse($uri);
if ($parts === \false) {
throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException("Unable to parse URI: {$uri}");
}
$this->applyParts($parts);
}
}
/**
* UTF-8 aware \parse_url() replacement.
*
* The internal function produces broken output for non ASCII domain names
* (IDN) when used with locales other than "C".
*
* On the other hand, cURL understands IDN correctly only when UTF-8 locale
* is configured ("C.UTF-8", "en_US.UTF-8", etc.).
*
* @see https://bugs.php.net/bug.php?id=52923
* @see https://www.php.net/manual/en/function.parse-url.php#114817
* @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING
*
* @return array|false
*/
private static function parse(string $url)
{
// If IPv6
$prefix = '';
if (\preg_match('%^(.*://\\[[0-9:a-f]+\\])(.*?)$%', $url, $matches)) {
/** @var array{0:string, 1:string, 2:string} $matches */
$prefix = $matches[1];
$url = $matches[2];
}
/** @var string */
$encodedUrl = \preg_replace_callback('%[^:/@?&=#]+%usD', static function ($matches) {
return \urlencode($matches[0]);
}, $url);
$result = \parse_url($prefix . $encodedUrl);
if ($result === \false) {
return \false;
}
return \array_map('urldecode', $result);
}
public function __toString() : string
{
if ($this->composedComponents === null) {
$this->composedComponents = self::composeComponents($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment);
}
return $this->composedComponents;
}
/**
* Composes a URI reference string from its various components.
*
* Usually this method does not need to be called manually but instead is used indirectly via
* `Psr\Http\Message\UriInterface::__toString`.
*
* PSR-7 UriInterface treats an empty component the same as a missing component as
* getQuery(), getFragment() etc. always return a string. This explains the slight
* difference to RFC 3986 Section 5.3.
*
* Another adjustment is that the authority separator is added even when the authority is missing/empty
* for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with
* `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But
* `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to
* that format).
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.3
*/
public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment) : string
{
$uri = '';
// weak type checks to also accept null until we can add scalar type hints
if ($scheme != '') {
$uri .= $scheme . ':';
}
if ($authority != '' || $scheme === 'file') {
$uri .= '//' . $authority;
}
if ($authority != '' && $path != '' && $path[0] != '/') {
$path = '/' . $path;
}
$uri .= $path;
if ($query != '') {
$uri .= '?' . $query;
}
if ($fragment != '') {
$uri .= '#' . $fragment;
}
return $uri;
}
/**
* Whether the URI has the default port of the current scheme.
*
* `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used
* independently of the implementation.
*/
public static function isDefaultPort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
{
return $uri->getPort() === null || isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()];
}
/**
* Whether the URI is absolute, i.e. it has a scheme.
*
* An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
* if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
* to another URI, the base URI. Relative references can be divided into several forms:
* - network-path references, e.g. '//example.com/path'
* - absolute-path references, e.g. '/path'
* - relative-path references, e.g. 'subpath'
*
* @see Uri::isNetworkPathReference
* @see Uri::isAbsolutePathReference
* @see Uri::isRelativePathReference
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-4
*/
public static function isAbsolute(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
{
return $uri->getScheme() !== '';
}
/**
* Whether the URI is a network-path reference.
*
* A relative reference that begins with two slash characters is termed an network-path reference.
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2
*/
public static function isNetworkPathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
{
return $uri->getScheme() === '' && $uri->getAuthority() !== '';
}
/**
* Whether the URI is a absolute-path reference.
*
* A relative reference that begins with a single slash character is termed an absolute-path reference.
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2
*/
public static function isAbsolutePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
{
return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/';
}
/**
* Whether the URI is a relative-path reference.
*
* A relative reference that does not begin with a slash character is termed a relative-path reference.
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2
*/
public static function isRelativePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
{
return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
}
/**
* Whether the URI is a same-document reference.
*
* A same-document reference refers to a URI that is, aside from its fragment
* component, identical to the base URI. When no base URI is given, only an empty
* URI reference (apart from its fragment) is considered a same-document reference.
*
* @param UriInterface $uri The URI to check
* @param UriInterface|null $base An optional base URI to compare against
*
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.4
*/
public static function isSameDocumentReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $base = null) : bool
{
if ($base !== null) {
$uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($base, $uri);
return $uri->getScheme() === $base->getScheme() && $uri->getAuthority() === $base->getAuthority() && $uri->getPath() === $base->getPath() && $uri->getQuery() === $base->getQuery();
}
return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
}
/**
* Creates a new URI with a specific query string value removed.
*
* Any existing query string values that exactly match the provided key are
* removed.
*
* @param UriInterface $uri URI to use as a base.
* @param string $key Query string key to remove.
*/
public static function withoutQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, string $key) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$result = self::getFilteredQueryString($uri, [$key]);
return $uri->withQuery(\implode('&', $result));
}
/**
* Creates a new URI with a specific query string value.
*
* Any existing query string values that exactly match the provided key are
* removed and replaced with the given key value pair.
*
* A value of null will set the query string key without a value, e.g. "key"
* instead of "key=value".
*
* @param UriInterface $uri URI to use as a base.
* @param string $key Key to set.
* @param string|null $value Value to set
*/
public static function withQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, string $key, ?string $value) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$result = self::getFilteredQueryString($uri, [$key]);
$result[] = self::generateQueryString($key, $value);
return $uri->withQuery(\implode('&', $result));
}
/**
* Creates a new URI with multiple specific query string values.
*
* It has the same behavior as withQueryValue() but for an associative array of key => value.
*
* @param UriInterface $uri URI to use as a base.
* @param (string|null)[] $keyValueArray Associative array of key and values
*/
public static function withQueryValues(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keyValueArray) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$result = self::getFilteredQueryString($uri, \array_keys($keyValueArray));
foreach ($keyValueArray as $key => $value) {
$result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null);
}
return $uri->withQuery(\implode('&', $result));
}
/**
* Creates a URI from a hash of `parse_url` components.
*
* @see https://www.php.net/manual/en/function.parse-url.php
*
* @throws MalformedUriException If the components do not form a valid URI.
*/
public static function fromParts(array $parts) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$uri = new self();
$uri->applyParts($parts);
$uri->validateState();
return $uri;
}
public function getScheme() : string
{
return $this->scheme;
}
public function getAuthority() : string
{
$authority = $this->host;
if ($this->userInfo !== '') {
$authority = $this->userInfo . '@' . $authority;
}
if ($this->port !== null) {
$authority .= ':' . $this->port;
}
return $authority;
}
public function getUserInfo() : string
{
return $this->userInfo;
}
public function getHost() : string
{
return $this->host;
}
public function getPort() : ?int
{
return $this->port;
}
public function getPath() : string
{
return $this->path;
}
public function getQuery() : string
{
return $this->query;
}
public function getFragment() : string
{
return $this->fragment;
}
public function withScheme($scheme) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$scheme = $this->filterScheme($scheme);
if ($this->scheme === $scheme) {
return $this;
}
$new = clone $this;
$new->scheme = $scheme;
$new->composedComponents = null;
$new->removeDefaultPort();
$new->validateState();
return $new;
}
public function withUserInfo($user, $password = null) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$info = $this->filterUserInfoComponent($user);
if ($password !== null) {
$info .= ':' . $this->filterUserInfoComponent($password);
}
if ($this->userInfo === $info) {
return $this;
}
$new = clone $this;
$new->userInfo = $info;
$new->composedComponents = null;
$new->validateState();
return $new;
}
public function withHost($host) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$host = $this->filterHost($host);
if ($this->host === $host) {
return $this;
}
$new = clone $this;
$new->host = $host;
$new->composedComponents = null;
$new->validateState();
return $new;
}
public function withPort($port) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$port = $this->filterPort($port);
if ($this->port === $port) {
return $this;
}
$new = clone $this;
$new->port = $port;
$new->composedComponents = null;
$new->removeDefaultPort();
$new->validateState();
return $new;
}
public function withPath($path) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$path = $this->filterPath($path);
if ($this->path === $path) {
return $this;
}
$new = clone $this;
$new->path = $path;
$new->composedComponents = null;
$new->validateState();
return $new;
}
public function withQuery($query) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$query = $this->filterQueryAndFragment($query);
if ($this->query === $query) {
return $this;
}
$new = clone $this;
$new->query = $query;
$new->composedComponents = null;
return $new;
}
public function withFragment($fragment) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$fragment = $this->filterQueryAndFragment($fragment);
if ($this->fragment === $fragment) {
return $this;
}
$new = clone $this;
$new->fragment = $fragment;
$new->composedComponents = null;
return $new;
}
public function jsonSerialize() : string
{
return $this->__toString();
}
/**
* Apply parse_url parts to a URI.
*
* @param array $parts Array of parse_url parts to apply.
*/
private function applyParts(array $parts) : void
{
$this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : '';
$this->userInfo = isset($parts['user']) ? $this->filterUserInfoComponent($parts['user']) : '';
$this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : '';
$this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null;
$this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : '';
$this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : '';
$this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : '';
if (isset($parts['pass'])) {
$this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']);
}
$this->removeDefaultPort();
}
/**
* @param mixed $scheme
*
* @throws \InvalidArgumentException If the scheme is invalid.
*/
private function filterScheme($scheme) : string
{
if (!\is_string($scheme)) {
throw new \InvalidArgumentException('Scheme must be a string');
}
return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
}
/**
* @param mixed $component
*
* @throws \InvalidArgumentException If the user info is invalid.
*/
private function filterUserInfoComponent($component) : string
{
if (!\is_string($component)) {
throw new \InvalidArgumentException('User info must be a string');
}
return \preg_replace_callback('/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $component);
}
/**
* @param mixed $host
*
* @throws \InvalidArgumentException If the host is invalid.
*/
private function filterHost($host) : string
{
if (!\is_string($host)) {
throw new \InvalidArgumentException('Host must be a string');
}
return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
}
/**
* @param mixed $port
*
* @throws \InvalidArgumentException If the port is invalid.
*/
private function filterPort($port) : ?int
{
if ($port === null) {
return null;
}
$port = (int) $port;
if (0 > $port || 0xffff < $port) {
throw new \InvalidArgumentException(\sprintf('Invalid port: %d. Must be between 0 and 65535', $port));
}
return $port;
}
/**
* @param (string|int)[] $keys
*
* @return string[]
*/
private static function getFilteredQueryString(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keys) : array
{
$current = $uri->getQuery();
if ($current === '') {
return [];
}
$decodedKeys = \array_map(function ($k) : string {
return \rawurldecode((string) $k);
}, $keys);
return \array_filter(\explode('&', $current), function ($part) use($decodedKeys) {
return !\in_array(\rawurldecode(\explode('=', $part)[0]), $decodedKeys, \true);
});
}
private static function generateQueryString(string $key, ?string $value) : string
{
// Query string separators ("=", "&") within the key or value need to be encoded
// (while preventing double-encoding) before setting the query string. All other
// chars that need percent-encoding will be encoded by withQuery().
$queryString = \strtr($key, self::QUERY_SEPARATORS_REPLACEMENT);
if ($value !== null) {
$queryString .= '=' . \strtr($value, self::QUERY_SEPARATORS_REPLACEMENT);
}
return $queryString;
}
private function removeDefaultPort() : void
{
if ($this->port !== null && self::isDefaultPort($this)) {
$this->port = null;
}
}
/**
* Filters the path of a URI
*
* @param mixed $path
*
* @throws \InvalidArgumentException If the path is invalid.
*/
private function filterPath($path) : string
{
if (!\is_string($path)) {
throw new \InvalidArgumentException('Path must be a string');
}
return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path);
}
/**
* Filters the query string or fragment of a URI.
*
* @param mixed $str
*
* @throws \InvalidArgumentException If the query or fragment is invalid.
*/
private function filterQueryAndFragment($str) : string
{
if (!\is_string($str)) {
throw new \InvalidArgumentException('Query and fragment must be a string');
}
return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str);
}
private function rawurlencodeMatchZero(array $match) : string
{
return \rawurlencode($match[0]);
}
private function validateState() : void
{
if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
$this->host = self::HTTP_DEFAULT_HOST;
}
if ($this->getAuthority() === '') {
if (0 === \strpos($this->path, '//')) {
throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException('The path of a URI without an authority must not start with two slashes "//"');
}
if ($this->scheme === '' && \false !== \strpos(\explode('/', $this->path, 2)[0], ':')) {
throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon');
}
}
}
}
vendor_prefixed/guzzlehttp/psr7/src/InflateStream.php 0000644 00000003156 14720660247 0017115 0 ustar 00 15 + 32]);
$this->stream = $stream->isSeekable() ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource) : new \YoastSEO_Vendor\GuzzleHttp\Psr7\NoSeekStream(new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource));
}
}
vendor_prefixed/guzzlehttp/psr7/src/UriResolver.php 0000644 00000021311 14720660247 0016631 0 ustar 00 getScheme() != '') {
return $rel->withPath(self::removeDotSegments($rel->getPath()));
}
if ($rel->getAuthority() != '') {
$targetAuthority = $rel->getAuthority();
$targetPath = self::removeDotSegments($rel->getPath());
$targetQuery = $rel->getQuery();
} else {
$targetAuthority = $base->getAuthority();
if ($rel->getPath() === '') {
$targetPath = $base->getPath();
$targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();
} else {
if ($rel->getPath()[0] === '/') {
$targetPath = $rel->getPath();
} else {
if ($targetAuthority != '' && $base->getPath() === '') {
$targetPath = '/' . $rel->getPath();
} else {
$lastSlashPos = \strrpos($base->getPath(), '/');
if ($lastSlashPos === \false) {
$targetPath = $rel->getPath();
} else {
$targetPath = \substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();
}
}
}
$targetPath = self::removeDotSegments($targetPath);
$targetQuery = $rel->getQuery();
}
}
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri(\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::composeComponents($base->getScheme(), $targetAuthority, $targetPath, $targetQuery, $rel->getFragment()));
}
/**
* Returns the target URI as a relative reference from the base URI.
*
* This method is the counterpart to resolve():
*
* (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
*
* One use-case is to use the current request URI as base URI and then generate relative links in your documents
* to reduce the document size or offer self-contained downloadable document archives.
*
* $base = new Uri('http://example.com/a/b/');
* echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
* echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
* echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
* echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.
*
* This method also accepts a target that is already relative and will try to relativize it further. Only a
* relative-path reference will be returned as-is.
*
* echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well
*/
public static function relativize(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')) {
return $target;
}
if (\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isRelativePathReference($target)) {
// As the target is already highly relative we return it as-is. It would be possible to resolve
// the target with `$target = self::resolve($base, $target);` and then try make it more relative
// by removing a duplicate query. But let's not do that automatically.
return $target;
}
if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
return $target->withScheme('');
}
// We must remove the path before removing the authority because if the path starts with two slashes, the URI
// would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
// invalid.
$emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
if ($base->getPath() !== $target->getPath()) {
return $emptyPathUri->withPath(self::getRelativePath($base, $target));
}
if ($base->getQuery() === $target->getQuery()) {
// Only the target fragment is left. And it must be returned even if base and target fragment are the same.
return $emptyPathUri->withQuery('');
}
// If the base URI has a query but the target has none, we cannot return an empty path reference as it would
// inherit the base query component when resolving.
if ($target->getQuery() === '') {
$segments = \explode('/', $target->getPath());
/** @var string $lastSegment */
$lastSegment = \end($segments);
return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
}
return $emptyPathUri;
}
private static function getRelativePath(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) : string
{
$sourceSegments = \explode('/', $base->getPath());
$targetSegments = \explode('/', $target->getPath());
\array_pop($sourceSegments);
$targetLastSegment = \array_pop($targetSegments);
foreach ($sourceSegments as $i => $segment) {
if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
unset($sourceSegments[$i], $targetSegments[$i]);
} else {
break;
}
}
$targetSegments[] = $targetLastSegment;
$relativePath = \str_repeat('../', \count($sourceSegments)) . \implode('/', $targetSegments);
// A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
// This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
// as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
if ('' === $relativePath || \false !== \strpos(\explode('/', $relativePath, 2)[0], ':')) {
$relativePath = "./{$relativePath}";
} elseif ('/' === $relativePath[0]) {
if ($base->getAuthority() != '' && $base->getPath() === '') {
// In this case an extra slash is added by resolve() automatically. So we must not add one here.
$relativePath = ".{$relativePath}";
} else {
$relativePath = "./{$relativePath}";
}
}
return $relativePath;
}
private function __construct()
{
// cannot be instantiated
}
}
vendor_prefixed/guzzlehttp/psr7/src/AppendStream.php 0000644 00000013614 14720660247 0016742 0 ustar 00 addStream($stream);
}
}
public function __toString() : string
{
try {
$this->rewind();
return $this->getContents();
} catch (\Throwable $e) {
if (\PHP_VERSION_ID >= 70400) {
throw $e;
}
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
return '';
}
}
/**
* Add a stream to the AppendStream
*
* @param StreamInterface $stream Stream to append. Must be readable.
*
* @throws \InvalidArgumentException if the stream is not readable
*/
public function addStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream) : void
{
if (!$stream->isReadable()) {
throw new \InvalidArgumentException('Each stream must be readable');
}
// The stream is only seekable if all streams are seekable
if (!$stream->isSeekable()) {
$this->seekable = \false;
}
$this->streams[] = $stream;
}
public function getContents() : string
{
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this);
}
/**
* Closes each attached stream.
*/
public function close() : void
{
$this->pos = $this->current = 0;
$this->seekable = \true;
foreach ($this->streams as $stream) {
$stream->close();
}
$this->streams = [];
}
/**
* Detaches each attached stream.
*
* Returns null as it's not clear which underlying stream resource to return.
*/
public function detach()
{
$this->pos = $this->current = 0;
$this->seekable = \true;
foreach ($this->streams as $stream) {
$stream->detach();
}
$this->streams = [];
return null;
}
public function tell() : int
{
return $this->pos;
}
/**
* Tries to calculate the size by adding the size of each stream.
*
* If any of the streams do not return a valid number, then the size of the
* append stream cannot be determined and null is returned.
*/
public function getSize() : ?int
{
$size = 0;
foreach ($this->streams as $stream) {
$s = $stream->getSize();
if ($s === null) {
return null;
}
$size += $s;
}
return $size;
}
public function eof() : bool
{
return !$this->streams || $this->current >= \count($this->streams) - 1 && $this->streams[$this->current]->eof();
}
public function rewind() : void
{
$this->seek(0);
}
/**
* Attempts to seek to the given position. Only supports SEEK_SET.
*/
public function seek($offset, $whence = \SEEK_SET) : void
{
if (!$this->seekable) {
throw new \RuntimeException('This AppendStream is not seekable');
} elseif ($whence !== \SEEK_SET) {
throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
}
$this->pos = $this->current = 0;
// Rewind each stream
foreach ($this->streams as $i => $stream) {
try {
$stream->rewind();
} catch (\Exception $e) {
throw new \RuntimeException('Unable to seek stream ' . $i . ' of the AppendStream', 0, $e);
}
}
// Seek to the actual position by reading from each stream
while ($this->pos < $offset && !$this->eof()) {
$result = $this->read(\min(8096, $offset - $this->pos));
if ($result === '') {
break;
}
}
}
/**
* Reads from all of the appended streams until the length is met or EOF.
*/
public function read($length) : string
{
$buffer = '';
$total = \count($this->streams) - 1;
$remaining = $length;
$progressToNext = \false;
while ($remaining > 0) {
// Progress to the next stream if needed.
if ($progressToNext || $this->streams[$this->current]->eof()) {
$progressToNext = \false;
if ($this->current === $total) {
break;
}
++$this->current;
}
$result = $this->streams[$this->current]->read($remaining);
if ($result === '') {
$progressToNext = \true;
continue;
}
$buffer .= $result;
$remaining = $length - \strlen($buffer);
}
$this->pos += \strlen($buffer);
return $buffer;
}
public function isReadable() : bool
{
return \true;
}
public function isWritable() : bool
{
return \false;
}
public function isSeekable() : bool
{
return $this->seekable;
}
public function write($string) : int
{
throw new \RuntimeException('Cannot write to an AppendStream');
}
/**
* @return mixed
*/
public function getMetadata($key = null)
{
return $key ? null : [];
}
}
vendor_prefixed/guzzlehttp/psr7/src/LazyOpenStream.php 0000644 00000002340 14720660247 0017266 0 ustar 00 filename = $filename;
$this->mode = $mode;
// unsetting the property forces the first access to go through
// __get().
unset($this->stream);
}
/**
* Creates the underlying stream lazily when required.
*/
protected function createStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen($this->filename, $this->mode));
}
}
vendor_prefixed/guzzlehttp/psr7/src/PumpStream.php 0000644 00000011166 14720660247 0016454 0 ustar 00 source = $source;
$this->size = $options['size'] ?? null;
$this->metadata = $options['metadata'] ?? [];
$this->buffer = new \YoastSEO_Vendor\GuzzleHttp\Psr7\BufferStream();
}
public function __toString() : string
{
try {
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this);
} catch (\Throwable $e) {
if (\PHP_VERSION_ID >= 70400) {
throw $e;
}
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
return '';
}
}
public function close() : void
{
$this->detach();
}
public function detach()
{
$this->tellPos = 0;
$this->source = null;
return null;
}
public function getSize() : ?int
{
return $this->size;
}
public function tell() : int
{
return $this->tellPos;
}
public function eof() : bool
{
return $this->source === null;
}
public function isSeekable() : bool
{
return \false;
}
public function rewind() : void
{
$this->seek(0);
}
public function seek($offset, $whence = \SEEK_SET) : void
{
throw new \RuntimeException('Cannot seek a PumpStream');
}
public function isWritable() : bool
{
return \false;
}
public function write($string) : int
{
throw new \RuntimeException('Cannot write to a PumpStream');
}
public function isReadable() : bool
{
return \true;
}
public function read($length) : string
{
$data = $this->buffer->read($length);
$readLen = \strlen($data);
$this->tellPos += $readLen;
$remaining = $length - $readLen;
if ($remaining) {
$this->pump($remaining);
$data .= $this->buffer->read($remaining);
$this->tellPos += \strlen($data) - $readLen;
}
return $data;
}
public function getContents() : string
{
$result = '';
while (!$this->eof()) {
$result .= $this->read(1000000);
}
return $result;
}
/**
* @return mixed
*/
public function getMetadata($key = null)
{
if (!$key) {
return $this->metadata;
}
return $this->metadata[$key] ?? null;
}
private function pump(int $length) : void
{
if ($this->source !== null) {
do {
$data = ($this->source)($length);
if ($data === \false || $data === null) {
$this->source = null;
return;
}
$this->buffer->write($data);
$length -= \strlen($data);
} while ($length > 0);
}
}
}
vendor_prefixed/guzzlehttp/psr7/src/Response.php 0000644 00000010646 14720660247 0016157 0 ustar 00 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required'];
/** @var string */
private $reasonPhrase;
/** @var int */
private $statusCode;
/**
* @param int $status Status code
* @param (string|string[])[] $headers Response headers
* @param string|resource|StreamInterface|null $body Response body
* @param string $version Protocol version
* @param string|null $reason Reason phrase (when empty a default will be used based on the status code)
*/
public function __construct(int $status = 200, array $headers = [], $body = null, string $version = '1.1', string $reason = null)
{
$this->assertStatusCodeRange($status);
$this->statusCode = $status;
if ($body !== '' && $body !== null) {
$this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($body);
}
$this->setHeaders($headers);
if ($reason == '' && isset(self::PHRASES[$this->statusCode])) {
$this->reasonPhrase = self::PHRASES[$this->statusCode];
} else {
$this->reasonPhrase = (string) $reason;
}
$this->protocol = $version;
}
public function getStatusCode() : int
{
return $this->statusCode;
}
public function getReasonPhrase() : string
{
return $this->reasonPhrase;
}
public function withStatus($code, $reasonPhrase = '') : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
$this->assertStatusCodeIsInteger($code);
$code = (int) $code;
$this->assertStatusCodeRange($code);
$new = clone $this;
$new->statusCode = $code;
if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) {
$reasonPhrase = self::PHRASES[$new->statusCode];
}
$new->reasonPhrase = (string) $reasonPhrase;
return $new;
}
/**
* @param mixed $statusCode
*/
private function assertStatusCodeIsInteger($statusCode) : void
{
if (\filter_var($statusCode, \FILTER_VALIDATE_INT) === \false) {
throw new \InvalidArgumentException('Status code must be an integer value.');
}
}
private function assertStatusCodeRange(int $statusCode) : void
{
if ($statusCode < 100 || $statusCode >= 600) {
throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.');
}
}
}
vendor_prefixed/guzzlehttp/psr7/src/CachingStream.php 0000644 00000011303 14720660247 0017060 0 ustar 00 remoteStream = $stream;
$this->stream = $target ?: new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'r+'));
}
public function getSize() : ?int
{
$remoteSize = $this->remoteStream->getSize();
if (null === $remoteSize) {
return null;
}
return \max($this->stream->getSize(), $remoteSize);
}
public function rewind() : void
{
$this->seek(0);
}
public function seek($offset, $whence = \SEEK_SET) : void
{
if ($whence === \SEEK_SET) {
$byte = $offset;
} elseif ($whence === \SEEK_CUR) {
$byte = $offset + $this->tell();
} elseif ($whence === \SEEK_END) {
$size = $this->remoteStream->getSize();
if ($size === null) {
$size = $this->cacheEntireStream();
}
$byte = $size + $offset;
} else {
throw new \InvalidArgumentException('Invalid whence');
}
$diff = $byte - $this->stream->getSize();
if ($diff > 0) {
// Read the remoteStream until we have read in at least the amount
// of bytes requested, or we reach the end of the file.
while ($diff > 0 && !$this->remoteStream->eof()) {
$this->read($diff);
$diff = $byte - $this->stream->getSize();
}
} else {
// We can just do a normal seek since we've already seen this byte.
$this->stream->seek($byte);
}
}
public function read($length) : string
{
// Perform a regular read on any previously read data from the buffer
$data = $this->stream->read($length);
$remaining = $length - \strlen($data);
// More data was requested so read from the remote stream
if ($remaining) {
// If data was written to the buffer in a position that would have
// been filled from the remote stream, then we must skip bytes on
// the remote stream to emulate overwriting bytes from that
// position. This mimics the behavior of other PHP stream wrappers.
$remoteData = $this->remoteStream->read($remaining + $this->skipReadBytes);
if ($this->skipReadBytes) {
$len = \strlen($remoteData);
$remoteData = \substr($remoteData, $this->skipReadBytes);
$this->skipReadBytes = \max(0, $this->skipReadBytes - $len);
}
$data .= $remoteData;
$this->stream->write($remoteData);
}
return $data;
}
public function write($string) : int
{
// When appending to the end of the currently read stream, you'll want
// to skip bytes from being read from the remote stream to emulate
// other stream wrappers. Basically replacing bytes of data of a fixed
// length.
$overflow = \strlen($string) + $this->tell() - $this->remoteStream->tell();
if ($overflow > 0) {
$this->skipReadBytes += $overflow;
}
return $this->stream->write($string);
}
public function eof() : bool
{
return $this->stream->eof() && $this->remoteStream->eof();
}
/**
* Close both the remote stream and buffer stream
*/
public function close() : void
{
$this->remoteStream->close();
$this->stream->close();
}
private function cacheEntireStream() : int
{
$target = new \YoastSEO_Vendor\GuzzleHttp\Psr7\FnStream(['write' => 'strlen']);
\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($this, $target);
return $this->tell();
}
}
vendor_prefixed/guzzlehttp/psr7/src/StreamDecoratorTrait.php 0000644 00000006565 14720660247 0020470 0 ustar 00 stream = $stream;
}
/**
* Magic method used to create a new stream if streams are not added in
* the constructor of a decorator (e.g., LazyOpenStream).
*
* @return StreamInterface
*/
public function __get(string $name)
{
if ($name === 'stream') {
$this->stream = $this->createStream();
return $this->stream;
}
throw new \UnexpectedValueException("{$name} not found on class");
}
public function __toString() : string
{
try {
if ($this->isSeekable()) {
$this->seek(0);
}
return $this->getContents();
} catch (\Throwable $e) {
if (\PHP_VERSION_ID >= 70400) {
throw $e;
}
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
return '';
}
}
public function getContents() : string
{
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this);
}
/**
* Allow decorators to implement custom methods
*
* @return mixed
*/
public function __call(string $method, array $args)
{
/** @var callable $callable */
$callable = [$this->stream, $method];
$result = $callable(...$args);
// Always return the wrapped object if the result is a return $this
return $result === $this->stream ? $this : $result;
}
public function close() : void
{
$this->stream->close();
}
/**
* @return mixed
*/
public function getMetadata($key = null)
{
return $this->stream->getMetadata($key);
}
public function detach()
{
return $this->stream->detach();
}
public function getSize() : ?int
{
return $this->stream->getSize();
}
public function eof() : bool
{
return $this->stream->eof();
}
public function tell() : int
{
return $this->stream->tell();
}
public function isReadable() : bool
{
return $this->stream->isReadable();
}
public function isWritable() : bool
{
return $this->stream->isWritable();
}
public function isSeekable() : bool
{
return $this->stream->isSeekable();
}
public function rewind() : void
{
$this->seek(0);
}
public function seek($offset, $whence = \SEEK_SET) : void
{
$this->stream->seek($offset, $whence);
}
public function read($length) : string
{
return $this->stream->read($length);
}
public function write($string) : int
{
return $this->stream->write($string);
}
/**
* Implement in subclasses to dynamically create streams when requested.
*
* @throws \BadMethodCallException
*/
protected function createStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
throw new \BadMethodCallException('Not implemented');
}
}
vendor_prefixed/guzzlehttp/psr7/src/BufferStream.php 0000644 00000006321 14720660247 0016741 0 ustar 00 hwm = $hwm;
}
public function __toString() : string
{
return $this->getContents();
}
public function getContents() : string
{
$buffer = $this->buffer;
$this->buffer = '';
return $buffer;
}
public function close() : void
{
$this->buffer = '';
}
public function detach()
{
$this->close();
return null;
}
public function getSize() : ?int
{
return \strlen($this->buffer);
}
public function isReadable() : bool
{
return \true;
}
public function isWritable() : bool
{
return \true;
}
public function isSeekable() : bool
{
return \false;
}
public function rewind() : void
{
$this->seek(0);
}
public function seek($offset, $whence = \SEEK_SET) : void
{
throw new \RuntimeException('Cannot seek a BufferStream');
}
public function eof() : bool
{
return \strlen($this->buffer) === 0;
}
public function tell() : int
{
throw new \RuntimeException('Cannot determine the position of a BufferStream');
}
/**
* Reads data from the buffer.
*/
public function read($length) : string
{
$currentLength = \strlen($this->buffer);
if ($length >= $currentLength) {
// No need to slice the buffer because we don't have enough data.
$result = $this->buffer;
$this->buffer = '';
} else {
// Slice up the result to provide a subset of the buffer.
$result = \substr($this->buffer, 0, $length);
$this->buffer = \substr($this->buffer, $length);
}
return $result;
}
/**
* Writes data to the buffer.
*/
public function write($string) : int
{
$this->buffer .= $string;
if (\strlen($this->buffer) >= $this->hwm) {
return 0;
}
return \strlen($string);
}
/**
* @return mixed
*/
public function getMetadata($key = null)
{
if ($key === 'hwm') {
return $this->hwm;
}
return $key ? null : [];
}
}
vendor_prefixed/guzzlehttp/psr7/src/HttpFactory.php 0000644 00000007714 14720660247 0016632 0 ustar 00 getSize();
}
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType);
}
public function createStream(string $content = '') : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($content);
}
public function createStreamFromFile(string $file, string $mode = 'r') : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
try {
$resource = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen($file, $mode);
} catch (\RuntimeException $e) {
if ('' === $mode || \false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], \true)) {
throw new \InvalidArgumentException(\sprintf('Invalid file opening mode "%s"', $mode), 0, $e);
}
throw $e;
}
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($resource);
}
public function createStreamFromResource($resource) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($resource);
}
public function createServerRequest(string $method, $uri, array $serverParams = []) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
if (empty($method)) {
if (!empty($serverParams['REQUEST_METHOD'])) {
$method = $serverParams['REQUEST_METHOD'];
} else {
throw new \InvalidArgumentException('Cannot determine HTTP method');
}
}
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($method, $uri, [], null, '1.1', $serverParams);
}
public function createResponse(int $code = 200, string $reasonPhrase = '') : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
{
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($code, [], null, '1.1', $reasonPhrase);
}
public function createRequest(string $method, $uri) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
{
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri);
}
public function createUri(string $uri = '') : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri);
}
}
vendor_prefixed/guzzlehttp/psr7/src/ServerRequest.php 0000644 00000023235 14720660247 0017176 0 ustar 00 serverParams = $serverParams;
parent::__construct($method, $uri, $headers, $body, $version);
}
/**
* Return an UploadedFile instance array.
*
* @param array $files An array which respect $_FILES structure
*
* @throws InvalidArgumentException for unrecognized values
*/
public static function normalizeFiles(array $files) : array
{
$normalized = [];
foreach ($files as $key => $value) {
if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInterface) {
$normalized[$key] = $value;
} elseif (\is_array($value) && isset($value['tmp_name'])) {
$normalized[$key] = self::createUploadedFileFromSpec($value);
} elseif (\is_array($value)) {
$normalized[$key] = self::normalizeFiles($value);
continue;
} else {
throw new \InvalidArgumentException('Invalid value in files specification');
}
}
return $normalized;
}
/**
* Create and return an UploadedFile instance from a $_FILES specification.
*
* If the specification represents an array of values, this method will
* delegate to normalizeNestedFileSpec() and return that return value.
*
* @param array $value $_FILES struct
*
* @return UploadedFileInterface|UploadedFileInterface[]
*/
private static function createUploadedFileFromSpec(array $value)
{
if (\is_array($value['tmp_name'])) {
return self::normalizeNestedFileSpec($value);
}
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile($value['tmp_name'], (int) $value['size'], (int) $value['error'], $value['name'], $value['type']);
}
/**
* Normalize an array of file specifications.
*
* Loops through all nested files and returns a normalized array of
* UploadedFileInterface instances.
*
* @return UploadedFileInterface[]
*/
private static function normalizeNestedFileSpec(array $files = []) : array
{
$normalizedFiles = [];
foreach (\array_keys($files['tmp_name']) as $key) {
$spec = ['tmp_name' => $files['tmp_name'][$key], 'size' => $files['size'][$key] ?? null, 'error' => $files['error'][$key] ?? null, 'name' => $files['name'][$key] ?? null, 'type' => $files['type'][$key] ?? null];
$normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
}
return $normalizedFiles;
}
/**
* Return a ServerRequest populated with superglobals:
* $_GET
* $_POST
* $_COOKIE
* $_FILES
* $_SERVER
*/
public static function fromGlobals() : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$headers = \getallheaders();
$uri = self::getUriFromGlobals();
$body = new \YoastSEO_Vendor\GuzzleHttp\Psr7\CachingStream(new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream('php://input', 'r+'));
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? \str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
$serverRequest = new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
return $serverRequest->withCookieParams($_COOKIE)->withQueryParams($_GET)->withParsedBody($_POST)->withUploadedFiles(self::normalizeFiles($_FILES));
}
private static function extractHostAndPortFromAuthority(string $authority) : array
{
$uri = 'http://' . $authority;
$parts = \parse_url($uri);
if (\false === $parts) {
return [null, null];
}
$host = $parts['host'] ?? null;
$port = $parts['port'] ?? null;
return [$host, $port];
}
/**
* Get a Uri populated with values from $_SERVER.
*/
public static function getUriFromGlobals() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
{
$uri = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri('');
$uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
$hasPort = \false;
if (isset($_SERVER['HTTP_HOST'])) {
[$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
if ($host !== null) {
$uri = $uri->withHost($host);
}
if ($port !== null) {
$hasPort = \true;
$uri = $uri->withPort($port);
}
} elseif (isset($_SERVER['SERVER_NAME'])) {
$uri = $uri->withHost($_SERVER['SERVER_NAME']);
} elseif (isset($_SERVER['SERVER_ADDR'])) {
$uri = $uri->withHost($_SERVER['SERVER_ADDR']);
}
if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
$uri = $uri->withPort($_SERVER['SERVER_PORT']);
}
$hasQuery = \false;
if (isset($_SERVER['REQUEST_URI'])) {
$requestUriParts = \explode('?', $_SERVER['REQUEST_URI'], 2);
$uri = $uri->withPath($requestUriParts[0]);
if (isset($requestUriParts[1])) {
$hasQuery = \true;
$uri = $uri->withQuery($requestUriParts[1]);
}
}
if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
$uri = $uri->withQuery($_SERVER['QUERY_STRING']);
}
return $uri;
}
public function getServerParams() : array
{
return $this->serverParams;
}
public function getUploadedFiles() : array
{
return $this->uploadedFiles;
}
public function withUploadedFiles(array $uploadedFiles) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
$new = clone $this;
$new->uploadedFiles = $uploadedFiles;
return $new;
}
public function getCookieParams() : array
{
return $this->cookieParams;
}
public function withCookieParams(array $cookies) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
$new = clone $this;
$new->cookieParams = $cookies;
return $new;
}
public function getQueryParams() : array
{
return $this->queryParams;
}
public function withQueryParams(array $query) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
$new = clone $this;
$new->queryParams = $query;
return $new;
}
/**
* @return array|object|null
*/
public function getParsedBody()
{
return $this->parsedBody;
}
public function withParsedBody($data) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
$new = clone $this;
$new->parsedBody = $data;
return $new;
}
public function getAttributes() : array
{
return $this->attributes;
}
/**
* @return mixed
*/
public function getAttribute($attribute, $default = null)
{
if (\false === \array_key_exists($attribute, $this->attributes)) {
return $default;
}
return $this->attributes[$attribute];
}
public function withAttribute($attribute, $value) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
$new = clone $this;
$new->attributes[$attribute] = $value;
return $new;
}
public function withoutAttribute($attribute) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
{
if (\false === \array_key_exists($attribute, $this->attributes)) {
return $this;
}
$new = clone $this;
unset($new->attributes[$attribute]);
return $new;
}
}
vendor_prefixed/guzzlehttp/psr7/src/UploadedFile.php 0000644 00000011463 14720660247 0016714 0 ustar 00 setError($errorStatus);
$this->size = $size;
$this->clientFilename = $clientFilename;
$this->clientMediaType = $clientMediaType;
if ($this->isOk()) {
$this->setStreamOrFile($streamOrFile);
}
}
/**
* Depending on the value set file or stream variable
*
* @param StreamInterface|string|resource $streamOrFile
*
* @throws InvalidArgumentException
*/
private function setStreamOrFile($streamOrFile) : void
{
if (\is_string($streamOrFile)) {
$this->file = $streamOrFile;
} elseif (\is_resource($streamOrFile)) {
$this->stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($streamOrFile);
} elseif ($streamOrFile instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) {
$this->stream = $streamOrFile;
} else {
throw new \InvalidArgumentException('Invalid stream or file provided for UploadedFile');
}
}
/**
* @throws InvalidArgumentException
*/
private function setError(int $error) : void
{
if (\false === \in_array($error, \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile::ERRORS, \true)) {
throw new \InvalidArgumentException('Invalid error status for UploadedFile');
}
$this->error = $error;
}
private static function isStringNotEmpty($param) : bool
{
return \is_string($param) && \false === empty($param);
}
/**
* Return true if there is no upload error
*/
private function isOk() : bool
{
return $this->error === \UPLOAD_ERR_OK;
}
public function isMoved() : bool
{
return $this->moved;
}
/**
* @throws RuntimeException if is moved or not ok
*/
private function validateActive() : void
{
if (\false === $this->isOk()) {
throw new \RuntimeException('Cannot retrieve stream due to upload error');
}
if ($this->isMoved()) {
throw new \RuntimeException('Cannot retrieve stream after it has already been moved');
}
}
public function getStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
{
$this->validateActive();
if ($this->stream instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) {
return $this->stream;
}
/** @var string $file */
$file = $this->file;
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($file, 'r+');
}
public function moveTo($targetPath) : void
{
$this->validateActive();
if (\false === self::isStringNotEmpty($targetPath)) {
throw new \InvalidArgumentException('Invalid path provided for move operation; must be a non-empty string');
}
if ($this->file) {
$this->moved = \PHP_SAPI === 'cli' ? \rename($this->file, $targetPath) : \move_uploaded_file($this->file, $targetPath);
} else {
\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($this->getStream(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($targetPath, 'w'));
$this->moved = \true;
}
if (\false === $this->moved) {
throw new \RuntimeException(\sprintf('Uploaded file could not be moved to %s', $targetPath));
}
}
public function getSize() : ?int
{
return $this->size;
}
public function getError() : int
{
return $this->error;
}
public function getClientFilename() : ?string
{
return $this->clientFilename;
}
public function getClientMediaType() : ?string
{
return $this->clientMediaType;
}
}
vendor_prefixed/guzzlehttp/psr7/src/UriComparator.php 0000644 00000002402 14720660247 0017137 0 ustar 00 getHost(), $modified->getHost()) !== 0) {
return \true;
}
if ($original->getScheme() !== $modified->getScheme()) {
return \true;
}
if (self::computePort($original) !== self::computePort($modified)) {
return \true;
}
return \false;
}
private static function computePort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : int
{
$port = $uri->getPort();
if (null !== $port) {
return $port;
}
return 'https' === $uri->getScheme() ? 443 : 80;
}
private function __construct()
{
// cannot be instantiated
}
}
vendor_prefixed/guzzlehttp/psr7/src/StreamWrapper.php 0000644 00000010161 14720660247 0017145 0 ustar 00 isReadable()) {
$mode = $stream->isWritable() ? 'r+' : 'r';
} elseif ($stream->isWritable()) {
$mode = 'w';
} else {
throw new \InvalidArgumentException('The stream must be readable, ' . 'writable, or both.');
}
return \fopen('guzzle://stream', $mode, \false, self::createStreamContext($stream));
}
/**
* Creates a stream context that can be used to open a stream as a php stream resource.
*
* @return resource
*/
public static function createStreamContext(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream)
{
return \stream_context_create(['guzzle' => ['stream' => $stream]]);
}
/**
* Registers the stream wrapper if needed
*/
public static function register() : void
{
if (!\in_array('guzzle', \stream_get_wrappers())) {
\stream_wrapper_register('guzzle', __CLASS__);
}
}
public function stream_open(string $path, string $mode, int $options, string &$opened_path = null) : bool
{
$options = \stream_context_get_options($this->context);
if (!isset($options['guzzle']['stream'])) {
return \false;
}
$this->mode = $mode;
$this->stream = $options['guzzle']['stream'];
return \true;
}
public function stream_read(int $count) : string
{
return $this->stream->read($count);
}
public function stream_write(string $data) : int
{
return $this->stream->write($data);
}
public function stream_tell() : int
{
return $this->stream->tell();
}
public function stream_eof() : bool
{
return $this->stream->eof();
}
public function stream_seek(int $offset, int $whence) : bool
{
$this->stream->seek($offset, $whence);
return \true;
}
/**
* @return resource|false
*/
public function stream_cast(int $cast_as)
{
$stream = clone $this->stream;
$resource = $stream->detach();
return $resource ?? \false;
}
/**
* @return array{
* dev: int,
* ino: int,
* mode: int,
* nlink: int,
* uid: int,
* gid: int,
* rdev: int,
* size: int,
* atime: int,
* mtime: int,
* ctime: int,
* blksize: int,
* blocks: int
* }
*/
public function stream_stat() : array
{
static $modeMap = ['r' => 33060, 'rb' => 33060, 'r+' => 33206, 'w' => 33188, 'wb' => 33188];
return ['dev' => 0, 'ino' => 0, 'mode' => $modeMap[$this->mode], 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => $this->stream->getSize() ?: 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0];
}
/**
* @return array{
* dev: int,
* ino: int,
* mode: int,
* nlink: int,
* uid: int,
* gid: int,
* rdev: int,
* size: int,
* atime: int,
* mtime: int,
* ctime: int,
* blksize: int,
* blocks: int
* }
*/
public function url_stat(string $path, int $flags) : array
{
return ['dev' => 0, 'ino' => 0, 'mode' => 0, 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0];
}
}
vendor_prefixed/psr/log/Psr/Log/NullLogger.php 0000644 00000001354 14720660247 0015377 0 ustar 00 logger) { }`
* blocks.
*/
class NullLogger extends \YoastSEO_Vendor\Psr\Log\AbstractLogger
{
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param array $context
*
* @return void
*
* @throws \Psr\Log\InvalidArgumentException
*/
public function log($level, $message, array $context = array())
{
// noop
}
}
vendor_prefixed/psr/log/Psr/Log/InvalidArgumentException.php 0000644 00000000160 14720660247 0020267 0 ustar 00 log(\YoastSEO_Vendor\Psr\Log\LogLevel::EMERGENCY, $message, $context);
}
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function alert($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ALERT, $message, $context);
}
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function critical($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::CRITICAL, $message, $context);
}
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function error($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ERROR, $message, $context);
}
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function warning($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::WARNING, $message, $context);
}
/**
* Normal but significant events.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function notice($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::NOTICE, $message, $context);
}
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function info($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::INFO, $message, $context);
}
/**
* Detailed debug information.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function debug($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::DEBUG, $message, $context);
}
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param array $context
*
* @return void
*
* @throws \Psr\Log\InvalidArgumentException
*/
public abstract function log($level, $message, array $context = array());
}
vendor_prefixed/psr/log/Psr/Log/LoggerInterface.php 0000644 00000006062 14720660247 0016366 0 ustar 00 logger = $logger;
}
}
vendor_prefixed/psr/log/Psr/Log/LoggerAwareInterface.php 0000644 00000000522 14720660247 0017341 0 ustar 00 log(\YoastSEO_Vendor\Psr\Log\LogLevel::EMERGENCY, $message, $context);
}
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function alert($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ALERT, $message, $context);
}
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function critical($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::CRITICAL, $message, $context);
}
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function error($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ERROR, $message, $context);
}
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function warning($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::WARNING, $message, $context);
}
/**
* Normal but significant events.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function notice($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::NOTICE, $message, $context);
}
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function info($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::INFO, $message, $context);
}
/**
* Detailed debug information.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function debug($message, array $context = array())
{
$this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::DEBUG, $message, $context);
}
}
vendor_prefixed/psr/log/Psr/Log/LogLevel.php 0000644 00000000511 14720660247 0015030 0 ustar 00
* [user-info@]host[:port]
*
*
* If the port component is not set or is the standard port for the current
* scheme, it SHOULD NOT be included.
*
* @see https://tools.ietf.org/html/rfc3986#section-3.2
* @return string The URI authority, in "[user-info@]host[:port]" format.
*/
public function getAuthority() : string;
/**
* Retrieve the user information component of the URI.
*
* If no user information is present, this method MUST return an empty
* string.
*
* If a user is present in the URI, this will return that value;
* additionally, if the password is also present, it will be appended to the
* user value, with a colon (":") separating the values.
*
* The trailing "@" character is not part of the user information and MUST
* NOT be added.
*
* @return string The URI user information, in "username[:password]" format.
*/
public function getUserInfo() : string;
/**
* Retrieve the host component of the URI.
*
* If no host is present, this method MUST return an empty string.
*
* The value returned MUST be normalized to lowercase, per RFC 3986
* Section 3.2.2.
*
* @see http://tools.ietf.org/html/rfc3986#section-3.2.2
* @return string The URI host.
*/
public function getHost() : string;
/**
* Retrieve the port component of the URI.
*
* If a port is present, and it is non-standard for the current scheme,
* this method MUST return it as an integer. If the port is the standard port
* used with the current scheme, this method SHOULD return null.
*
* If no port is present, and no scheme is present, this method MUST return
* a null value.
*
* If no port is present, but a scheme is present, this method MAY return
* the standard port for that scheme, but SHOULD return null.
*
* @return null|int The URI port.
*/
public function getPort() : ?int;
/**
* Retrieve the path component of the URI.
*
* The path can either be empty or absolute (starting with a slash) or
* rootless (not starting with a slash). Implementations MUST support all
* three syntaxes.
*
* Normally, the empty path "" and absolute path "/" are considered equal as
* defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
* do this normalization because in contexts with a trimmed base path, e.g.
* the front controller, this difference becomes significant. It's the task
* of the user to handle both "" and "/".
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.3.
*
* As an example, if the value should include a slash ("/") not intended as
* delimiter between path segments, that value MUST be passed in encoded
* form (e.g., "%2F") to the instance.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.3
* @return string The URI path.
*/
public function getPath() : string;
/**
* Retrieve the query string of the URI.
*
* If no query string is present, this method MUST return an empty string.
*
* The leading "?" character is not part of the query and MUST NOT be
* added.
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.4.
*
* As an example, if a value in a key/value pair of the query string should
* include an ampersand ("&") not intended as a delimiter between values,
* that value MUST be passed in encoded form (e.g., "%26") to the instance.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.4
* @return string The URI query string.
*/
public function getQuery() : string;
/**
* Retrieve the fragment component of the URI.
*
* If no fragment is present, this method MUST return an empty string.
*
* The leading "#" character is not part of the fragment and MUST NOT be
* added.
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.5.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.5
* @return string The URI fragment.
*/
public function getFragment() : string;
/**
* Return an instance with the specified scheme.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified scheme.
*
* Implementations MUST support the schemes "http" and "https" case
* insensitively, and MAY accommodate other schemes if required.
*
* An empty scheme is equivalent to removing the scheme.
*
* @param string $scheme The scheme to use with the new instance.
* @return static A new instance with the specified scheme.
* @throws \InvalidArgumentException for invalid or unsupported schemes.
*/
public function withScheme(string $scheme) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface;
/**
* Return an instance with the specified user information.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified user information.
*
* Password is optional, but the user information MUST include the
* user; an empty string for the user is equivalent to removing user
* information.
*
* @param string $user The user name to use for authority.
* @param null|string $password The password associated with $user.
* @return static A new instance with the specified user information.
*/
public function withUserInfo(string $user, ?string $password = null) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface;
/**
* Return an instance with the specified host.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified host.
*
* An empty host value is equivalent to removing the host.
*
* @param string $host The hostname to use with the new instance.
* @return static A new instance with the specified host.
* @throws \InvalidArgumentException for invalid hostnames.
*/
public function withHost(string $host) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface;
/**
* Return an instance with the specified port.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified port.
*
* Implementations MUST raise an exception for ports outside the
* established TCP and UDP port ranges.
*
* A null value provided for the port is equivalent to removing the port
* information.
*
* @param null|int $port The port to use with the new instance; a null value
* removes the port information.
* @return static A new instance with the specified port.
* @throws \InvalidArgumentException for invalid ports.
*/
public function withPort(?int $port) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface;
/**
* Return an instance with the specified path.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified path.
*
* The path can either be empty or absolute (starting with a slash) or
* rootless (not starting with a slash). Implementations MUST support all
* three syntaxes.
*
* If the path is intended to be domain-relative rather than path relative then
* it must begin with a slash ("/"). Paths not starting with a slash ("/")
* are assumed to be relative to some base path known to the application or
* consumer.
*
* Users can provide both encoded and decoded path characters.
* Implementations ensure the correct encoding as outlined in getPath().
*
* @param string $path The path to use with the new instance.
* @return static A new instance with the specified path.
* @throws \InvalidArgumentException for invalid paths.
*/
public function withPath(string $path) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface;
/**
* Return an instance with the specified query string.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified query string.
*
* Users can provide both encoded and decoded query characters.
* Implementations ensure the correct encoding as outlined in getQuery().
*
* An empty query string value is equivalent to removing the query string.
*
* @param string $query The query string to use with the new instance.
* @return static A new instance with the specified query string.
* @throws \InvalidArgumentException for invalid query strings.
*/
public function withQuery(string $query) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface;
/**
* Return an instance with the specified URI fragment.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified URI fragment.
*
* Users can provide both encoded and decoded fragment characters.
* Implementations ensure the correct encoding as outlined in getFragment().
*
* An empty fragment value is equivalent to removing the fragment.
*
* @param string $fragment The fragment to use with the new instance.
* @return static A new instance with the specified fragment.
*/
public function withFragment(string $fragment) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface;
/**
* Return the string representation as a URI reference.
*
* Depending on which components of the URI are present, the resulting
* string is either a full URI or relative reference according to RFC 3986,
* Section 4.1. The method concatenates the various components of the URI,
* using the appropriate delimiters:
*
* - If a scheme is present, it MUST be suffixed by ":".
* - If an authority is present, it MUST be prefixed by "//".
* - The path can be concatenated without delimiters. But there are two
* cases where the path has to be adjusted to make the URI reference
* valid as PHP does not allow to throw an exception in __toString():
* - If the path is rootless and an authority is present, the path MUST
* be prefixed by "/".
* - If the path is starting with more than one "/" and no authority is
* present, the starting slashes MUST be reduced to one.
* - If a query is present, it MUST be prefixed by "?".
* - If a fragment is present, it MUST be prefixed by "#".
*
* @see http://tools.ietf.org/html/rfc3986#section-4.1
* @return string
*/
public function __toString() : string;
}
vendor_prefixed/psr/http-message/src/StreamInterface.php 0000644 00000011414 14720660247 0017521 0 ustar 00 getQuery()`
* or from the `QUERY_STRING` server param.
*
* @return array
*/
public function getQueryParams() : array;
/**
* Return an instance with the specified query string arguments.
*
* These values SHOULD remain immutable over the course of the incoming
* request. They MAY be injected during instantiation, such as from PHP's
* $_GET superglobal, or MAY be derived from some other value such as the
* URI. In cases where the arguments are parsed from the URI, the data
* MUST be compatible with what PHP's parse_str() would return for
* purposes of how duplicate query parameters are handled, and how nested
* sets are handled.
*
* Setting query string arguments MUST NOT change the URI stored by the
* request, nor the values in the server params.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* updated query string arguments.
*
* @param array $query Array of query string arguments, typically from
* $_GET.
* @return static
*/
public function withQueryParams(array $query) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface;
/**
* Retrieve normalized file upload data.
*
* This method returns upload metadata in a normalized tree, with each leaf
* an instance of Psr\Http\Message\UploadedFileInterface.
*
* These values MAY be prepared from $_FILES or the message body during
* instantiation, or MAY be injected via withUploadedFiles().
*
* @return array An array tree of UploadedFileInterface instances; an empty
* array MUST be returned if no data is present.
*/
public function getUploadedFiles() : array;
/**
* Create a new instance with the specified uploaded files.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* updated body parameters.
*
* @param array $uploadedFiles An array tree of UploadedFileInterface instances.
* @return static
* @throws \InvalidArgumentException if an invalid structure is provided.
*/
public function withUploadedFiles(array $uploadedFiles) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface;
/**
* Retrieve any parameters provided in the request body.
*
* If the request Content-Type is either application/x-www-form-urlencoded
* or multipart/form-data, and the request method is POST, this method MUST
* return the contents of $_POST.
*
* Otherwise, this method may return any results of deserializing
* the request body content; as parsing returns structured content, the
* potential types MUST be arrays or objects only. A null value indicates
* the absence of body content.
*
* @return null|array|object The deserialized body parameters, if any.
* These will typically be an array or object.
*/
public function getParsedBody();
/**
* Return an instance with the specified body parameters.
*
* These MAY be injected during instantiation.
*
* If the request Content-Type is either application/x-www-form-urlencoded
* or multipart/form-data, and the request method is POST, use this method
* ONLY to inject the contents of $_POST.
*
* The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
* deserializing the request body content. Deserialization/parsing returns
* structured data, and, as such, this method ONLY accepts arrays or objects,
* or a null value if nothing was available to parse.
*
* As an example, if content negotiation determines that the request data
* is a JSON payload, this method could be used to create a request
* instance with the deserialized parameters.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* updated body parameters.
*
* @param null|array|object $data The deserialized body data. This will
* typically be in an array or object.
* @return static
* @throws \InvalidArgumentException if an unsupported argument type is
* provided.
*/
public function withParsedBody($data) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface;
/**
* Retrieve attributes derived from the request.
*
* The request "attributes" may be used to allow injection of any
* parameters derived from the request: e.g., the results of path
* match operations; the results of decrypting cookies; the results of
* deserializing non-form-encoded message bodies; etc. Attributes
* will be application and request specific, and CAN be mutable.
*
* @return array Attributes derived from the request.
*/
public function getAttributes() : array;
/**
* Retrieve a single derived request attribute.
*
* Retrieves a single derived request attribute as described in
* getAttributes(). If the attribute has not been previously set, returns
* the default value as provided.
*
* This method obviates the need for a hasAttribute() method, as it allows
* specifying a default value to return if the attribute is not found.
*
* @see getAttributes()
* @param string $name The attribute name.
* @param mixed $default Default value to return if the attribute does not exist.
* @return mixed
*/
public function getAttribute(string $name, $default = null);
/**
* Return an instance with the specified derived request attribute.
*
* This method allows setting a single derived request attribute as
* described in getAttributes().
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* updated attribute.
*
* @see getAttributes()
* @param string $name The attribute name.
* @param mixed $value The value of the attribute.
* @return static
*/
public function withAttribute(string $name, $value) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface;
/**
* Return an instance that removes the specified derived request attribute.
*
* This method allows removing a single derived request attribute as
* described in getAttributes().
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that removes
* the attribute.
*
* @see getAttributes()
* @param string $name The attribute name.
* @return static
*/
public function withoutAttribute(string $name) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface;
}
vendor_prefixed/psr/http-message/src/MessageInterface.php 0000644 00000016275 14720660247 0017664 0 ustar 00 getHeaders() as $name => $values) {
* echo $name . ": " . implode(", ", $values);
* }
*
* // Emit headers iteratively:
* foreach ($message->getHeaders() as $name => $values) {
* foreach ($values as $value) {
* header(sprintf('%s: %s', $name, $value), false);
* }
* }
*
* While header names are not case-sensitive, getHeaders() will preserve the
* exact case in which headers were originally specified.
*
* @return string[][] Returns an associative array of the message's headers. Each
* key MUST be a header name, and each value MUST be an array of strings
* for that header.
*/
public function getHeaders() : array;
/**
* Checks if a header exists by the given case-insensitive name.
*
* @param string $name Case-insensitive header field name.
* @return bool Returns true if any header names match the given header
* name using a case-insensitive string comparison. Returns false if
* no matching header name is found in the message.
*/
public function hasHeader(string $name) : bool;
/**
* Retrieves a message header value by the given case-insensitive name.
*
* This method returns an array of all the header values of the given
* case-insensitive header name.
*
* If the header does not appear in the message, this method MUST return an
* empty array.
*
* @param string $name Case-insensitive header field name.
* @return string[] An array of string values as provided for the given
* header. If the header does not appear in the message, this method MUST
* return an empty array.
*/
public function getHeader(string $name) : array;
/**
* Retrieves a comma-separated string of the values for a single header.
*
* This method returns all of the header values of the given
* case-insensitive header name as a string concatenated together using
* a comma.
*
* NOTE: Not all header values may be appropriately represented using
* comma concatenation. For such headers, use getHeader() instead
* and supply your own delimiter when concatenating.
*
* If the header does not appear in the message, this method MUST return
* an empty string.
*
* @param string $name Case-insensitive header field name.
* @return string A string of values as provided for the given header
* concatenated together using a comma. If the header does not appear in
* the message, this method MUST return an empty string.
*/
public function getHeaderLine(string $name) : string;
/**
* Return an instance with the provided value replacing the specified header.
*
* While header names are case-insensitive, the casing of the header will
* be preserved by this function, and returned from getHeaders().
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new and/or updated header and value.
*
* @param string $name Case-insensitive header field name.
* @param string|string[] $value Header value(s).
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withHeader(string $name, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
/**
* Return an instance with the specified header appended with the given value.
*
* Existing values for the specified header will be maintained. The new
* value(s) will be appended to the existing list. If the header did not
* exist previously, it will be added.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new header and/or value.
*
* @param string $name Case-insensitive header field name to add.
* @param string|string[] $value Header value(s).
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withAddedHeader(string $name, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
/**
* Return an instance without the specified header.
*
* Header resolution MUST be done without case-sensitivity.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that removes
* the named header.
*
* @param string $name Case-insensitive header field name to remove.
* @return static
*/
public function withoutHeader(string $name) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
/**
* Gets the body of the message.
*
* @return StreamInterface Returns the body as a stream.
*/
public function getBody() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
/**
* Return an instance with the specified message body.
*
* The body MUST be a StreamInterface object.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return a new instance that has the
* new body stream.
*
* @param StreamInterface $body Body.
* @return static
* @throws \InvalidArgumentException When the body is not valid.
*/
public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
}
vendor_prefixed/psr/http-client/src/ClientInterface.php 0000644 00000001150 14720660247 0017332 0 ustar 00