Fixed Broken Shit
This commit is contained in:
100
includes/vendor/aura/sql/README.md
vendored
Normal file
100
includes/vendor/aura/sql/README.md
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
# Aura.Sql
|
||||
|
||||
Provides an extension to the native [PDO](http://php.net/PDO) along with a
|
||||
profiler and connection locator. Because _ExtendedPdo_ is an extension of the
|
||||
native _PDO_, code already using the native _PDO_ or typehinted to the native
|
||||
_PDO_ can use _ExtendedPdo_ without any changes.
|
||||
|
||||
Added functionality in _Aura.Sql_ over the native _PDO_ includes:
|
||||
|
||||
- **Lazy connection.** _ExtendedPdo_ connects to the database only on
|
||||
method calls that require a connection. This means you can create an
|
||||
instance and not incur the cost of a connection if you never make a query.
|
||||
|
||||
- **Decoration.** _DecoratedPdo_ can be used to decorate an existing PDO
|
||||
instance. This means that a PDO instance can be "extended" **at runtime** to
|
||||
provide the _ExtendedPdo_ behaviors.
|
||||
|
||||
- **Array quoting.** The `quote()` method will accept an array as input, and
|
||||
return a string of comma-separated quoted values.
|
||||
|
||||
- **New `perform()` method.** The `perform()` method acts just like `query()`,
|
||||
but binds values to a prepared statement as part of the call. In addition,
|
||||
placeholders that represent array values will be replaced with comma-
|
||||
separated quoted values. This means you can bind an array of values to a
|
||||
placeholder used with an `IN (...)` condition when using `perform()`.
|
||||
|
||||
- **New `fetch*()` methods.** The new `fetch*()` methods provide for
|
||||
commonly-used fetch actions. For example, you can call `fetchAll()` directly
|
||||
on the instance instead of having to prepare a statement, bind values,
|
||||
execute, and then fetch from the prepared statement. All of the `fetch*()`
|
||||
methods take an array of values to bind to to the query statement, and use
|
||||
the new `perform()` method internally.
|
||||
|
||||
- **New `yield*()` methods.** These are complements to the `fetch*()` methods
|
||||
that `yield` results instead of `return`ing them.
|
||||
|
||||
- **Exceptions by default.** _ExtendedPdo_ starts in the `ERRMODE_EXCEPTION`
|
||||
mode for error reporting instead of the `ERRMODE_SILENT` mode.
|
||||
|
||||
- **Profiler.** An optional query profiler is provided, along with an
|
||||
interface for other implementations, that logs to any PSR-3 interface.
|
||||
|
||||
- **Connection locator.** A optional lazy-loading service locator is provided
|
||||
for picking different database connections (default, read, and write).
|
||||
|
||||
|
||||
## Installation and Autoloading
|
||||
|
||||
This package is installable and PSR-4 autoloadable via Composer as
|
||||
[aura/sql][].
|
||||
|
||||
Alternatively, [download a release][], or clone this repository, then map the
|
||||
`Aura\Sql\` namespace to the package `src/` directory.
|
||||
|
||||
## Dependencies
|
||||
|
||||
This package requires PHP 5.6 or later; it has also been tested on PHP 7 and
|
||||
HHVM. We recommend using the latest available version of PHP as a matter of
|
||||
principle.
|
||||
|
||||
Aura library packages may sometimes depend on external interfaces, but never on
|
||||
external implementations. This allows compliance with community standards
|
||||
without compromising flexibility. For specifics, please examine the package
|
||||
[composer.json][] file.
|
||||
|
||||
## Quality
|
||||
|
||||
[](https://scrutinizer-ci.com/g/auraphp/Aura.Sql/)
|
||||
[](https://scrutinizer-ci.com/g/auraphp/Aura.Sql/)
|
||||
[](https://travis-ci.org/auraphp/Aura.Sql)
|
||||
[](https://github.com/php-pds/skeleton)
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
To run the unit tests at the command line, issue `composer install` and then
|
||||
`./vendor/bin/phpunit` at the package root. (This requires [Composer][] to be
|
||||
available as `composer`.)
|
||||
|
||||
This package attempts to comply with [PSR-1][], [PSR-2][], and [PSR-4][]. If
|
||||
you notice compliance oversights, please send a patch via pull request.
|
||||
|
||||
## Community
|
||||
|
||||
To ask questions, provide feedback, or otherwise communicate with other Aura
|
||||
users, please join our [Google Group][], follow [@auraphp][], or chat with us
|
||||
on Freenode in the #auraphp channel.
|
||||
|
||||
## Documentation
|
||||
|
||||
This package is fully documented [here](./docs/index.md).
|
||||
|
||||
[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
|
||||
[PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
|
||||
[PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
|
||||
[Composer]: http://getcomposer.org/
|
||||
[Google Group]: http://groups.google.com/group/auraphp
|
||||
[@auraphp]: http://twitter.com/auraphp
|
||||
[download a release]: https://github.com/auraphp/Aura.Sql/releases
|
||||
[aura/sql]: https://packagist.org/packages/aura/sql
|
||||
[composer.json]: ./composer.json
|
1022
includes/vendor/aura/sql/src/AbstractExtendedPdo.php
vendored
Normal file
1022
includes/vendor/aura/sql/src/AbstractExtendedPdo.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
203
includes/vendor/aura/sql/src/ConnectionLocator.php
vendored
Normal file
203
includes/vendor/aura/sql/src/ConnectionLocator.php
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql;
|
||||
|
||||
/**
|
||||
*
|
||||
* Manages ExtendedPdo instances for default, read, and write connections.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class ConnectionLocator implements ConnectionLocatorInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* A default ExtendedPdo connection factory/instance.
|
||||
*
|
||||
* @var callable
|
||||
*
|
||||
*/
|
||||
protected $default;
|
||||
|
||||
/**
|
||||
*
|
||||
* A registry of ExtendedPdo "read" factories/instances.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $read = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* A registry of ExtendedPdo "write" factories/instances.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $write = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructor.
|
||||
*
|
||||
* @param callable $default A callable to create a default connection.
|
||||
*
|
||||
* @param array $read An array of callables to create read connections.
|
||||
*
|
||||
* @param array $write An array of callables to create write connections.
|
||||
*
|
||||
*/
|
||||
public function __construct(
|
||||
$default = null,
|
||||
array $read = [],
|
||||
array $write = []
|
||||
) {
|
||||
if ($default) {
|
||||
$this->setDefault($default);
|
||||
}
|
||||
foreach ($read as $name => $callable) {
|
||||
$this->setRead($name, $callable);
|
||||
}
|
||||
foreach ($write as $name => $callable) {
|
||||
$this->setWrite($name, $callable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets the default connection factory.
|
||||
*
|
||||
* @param callable $callable The factory for the connection.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setDefault(callable $callable)
|
||||
{
|
||||
$this->default = $callable;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the default connection object.
|
||||
*
|
||||
* @return ExtendedPdoInterface
|
||||
*
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
if (! $this->default instanceof ExtendedPdo) {
|
||||
$this->default = call_user_func($this->default);
|
||||
}
|
||||
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets a read connection factory by name.
|
||||
*
|
||||
* @param string $name The name of the connection.
|
||||
*
|
||||
* @param callable $callable The factory for the connection.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setRead($name, callable $callable)
|
||||
{
|
||||
$this->read[$name] = $callable;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a read connection by name; if no name is given, picks a
|
||||
* random connection; if no read connections are present, returns the
|
||||
* default connection.
|
||||
*
|
||||
* @param string $name The read connection name to return.
|
||||
*
|
||||
* @return ExtendedPdoInterface
|
||||
*
|
||||
*/
|
||||
public function getRead($name = '')
|
||||
{
|
||||
return $this->getConnection('read', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets a write connection factory by name.
|
||||
*
|
||||
* @param string $name The name of the connection.
|
||||
*
|
||||
* @param callable $callable The factory for the connection.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setWrite($name, callable $callable)
|
||||
{
|
||||
$this->write[$name] = $callable;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a write connection by name; if no name is given, picks a
|
||||
* random connection; if no write connections are present, returns the
|
||||
* default connection.
|
||||
*
|
||||
* @param string $name The write connection name to return.
|
||||
*
|
||||
* @return ExtendedPdoInterface
|
||||
*
|
||||
*/
|
||||
public function getWrite($name = '')
|
||||
{
|
||||
return $this->getConnection('write', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a connection by name.
|
||||
*
|
||||
* @param string $type The connection type ('read' or 'write').
|
||||
*
|
||||
* @param string $name The name of the connection.
|
||||
*
|
||||
* @return ExtendedPdoInterface
|
||||
*
|
||||
* @throws Exception\ConnectionNotFound
|
||||
*
|
||||
*/
|
||||
protected function getConnection($type, $name)
|
||||
{
|
||||
$conn = &$this->{$type};
|
||||
|
||||
if (empty($conn)) {
|
||||
return $this->getDefault();
|
||||
}
|
||||
|
||||
if ($name === '') {
|
||||
$name = array_rand($conn);
|
||||
}
|
||||
|
||||
if (! isset($conn[$name])) {
|
||||
throw new Exception\ConnectionNotFound("{$type}:{$name}");
|
||||
}
|
||||
|
||||
if (! $conn[$name] instanceof ExtendedPdo) {
|
||||
$conn[$name] = call_user_func($conn[$name]);
|
||||
}
|
||||
|
||||
return $conn[$name];
|
||||
}
|
||||
}
|
91
includes/vendor/aura/sql/src/ConnectionLocatorInterface.php
vendored
Normal file
91
includes/vendor/aura/sql/src/ConnectionLocatorInterface.php
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql;
|
||||
|
||||
/**
|
||||
*
|
||||
* Locates PDO connections for default, read, and write databases.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
interface ConnectionLocatorInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Sets the default connection registry entry.
|
||||
*
|
||||
* @param callable $callable The registry entry.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setDefault(callable $callable);
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the default connection object.
|
||||
*
|
||||
* @return ExtendedPdoInterface
|
||||
*
|
||||
*/
|
||||
public function getDefault();
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets a read connection registry entry by name.
|
||||
*
|
||||
* @param string $name The name of the registry entry.
|
||||
*
|
||||
* @param callable $callable The registry entry.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setRead($name, callable $callable);
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a read connection by name; if no name is given, picks a
|
||||
* random connection; if no read connections are present, returns the
|
||||
* default connection.
|
||||
*
|
||||
* @param string $name The read connection name to return.
|
||||
*
|
||||
* @return ExtendedPdoInterface
|
||||
*
|
||||
*/
|
||||
public function getRead($name = '');
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets a write connection registry entry by name.
|
||||
*
|
||||
* @param string $name The name of the registry entry.
|
||||
*
|
||||
* @param callable $callable The registry entry.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setWrite($name, callable $callable);
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a write connection by name; if no name is given, picks a
|
||||
* random connection; if no write connections are present, returns the
|
||||
* default connection.
|
||||
*
|
||||
* @param string $name The write connection name to return.
|
||||
*
|
||||
* @return ExtendedPdoInterface
|
||||
*
|
||||
*/
|
||||
public function getWrite($name = '');
|
||||
}
|
74
includes/vendor/aura/sql/src/DecoratedPdo.php
vendored
Normal file
74
includes/vendor/aura/sql/src/DecoratedPdo.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql;
|
||||
|
||||
use Aura\Sql\Profiler\Profiler;
|
||||
use Aura\Sql\Profiler\ProfilerInterface;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
*
|
||||
* Decorates an existing PDO instance with the extended methods.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class DecoratedPdo extends AbstractExtendedPdo
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Constructor.
|
||||
*
|
||||
* This overrides the parent so that it can take an existing PDO instance
|
||||
* and decorate it with the extended methods.
|
||||
*
|
||||
* @param PDO $pdo An existing PDO instance to decorate.
|
||||
*
|
||||
* @param ProfilerInterface $profiler Tracks and logs query profiles.
|
||||
*
|
||||
*/
|
||||
public function __construct(PDO $pdo, ProfilerInterface $profiler = null)
|
||||
{
|
||||
$this->pdo = $pdo;
|
||||
|
||||
if ($profiler === null) {
|
||||
$profiler = new Profiler();
|
||||
}
|
||||
$this->setProfiler($profiler);
|
||||
|
||||
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
$this->setParser($this->newParser($driver));
|
||||
$this->setQuoteName($driver);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Connects to the database.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
// already connected
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Disconnects from the database; disallowed with decorated PDO connections.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$message = "Cannot disconnect a DecoratedPdo instance.";
|
||||
throw new Exception\CannotDisconnect($message);
|
||||
}
|
||||
}
|
20
includes/vendor/aura/sql/src/Exception.php
vendored
Normal file
20
includes/vendor/aura/sql/src/Exception.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql;
|
||||
|
||||
/**
|
||||
*
|
||||
* Base Exception class for Aura Sql
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
23
includes/vendor/aura/sql/src/Exception/CannotBindValue.php
vendored
Normal file
23
includes/vendor/aura/sql/src/Exception/CannotBindValue.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Exception;
|
||||
|
||||
use Aura\Sql\Exception;
|
||||
|
||||
/**
|
||||
*
|
||||
* Could not bind a value to a placeholder in a statement, generally because
|
||||
* the value is an array, object, or resource.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class CannotBindValue extends Exception
|
||||
{
|
||||
}
|
23
includes/vendor/aura/sql/src/Exception/CannotDisconnect.php
vendored
Normal file
23
includes/vendor/aura/sql/src/Exception/CannotDisconnect.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Exception;
|
||||
|
||||
use Aura\Sql\Exception;
|
||||
|
||||
/**
|
||||
*
|
||||
* ExtendedPdo could not disconnect; e.g., because its PDO connection was
|
||||
* created externally and then injected.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class CannotDisconnect extends Exception
|
||||
{
|
||||
}
|
22
includes/vendor/aura/sql/src/Exception/ConnectionNotFound.php
vendored
Normal file
22
includes/vendor/aura/sql/src/Exception/ConnectionNotFound.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Exception;
|
||||
|
||||
use Aura\Sql\Exception;
|
||||
|
||||
/**
|
||||
*
|
||||
* Locator could not find a named connection.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class ConnectionNotFound extends Exception
|
||||
{
|
||||
}
|
22
includes/vendor/aura/sql/src/Exception/MissingParameter.php
vendored
Normal file
22
includes/vendor/aura/sql/src/Exception/MissingParameter.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Exception;
|
||||
|
||||
use Aura\Sql\Exception;
|
||||
|
||||
/**
|
||||
*
|
||||
* Missing a parameter in the values bound to a statement
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class MissingParameter extends Exception
|
||||
{
|
||||
}
|
163
includes/vendor/aura/sql/src/ExtendedPdo.php
vendored
Normal file
163
includes/vendor/aura/sql/src/ExtendedPdo.php
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql;
|
||||
|
||||
use Aura\Sql\Profiler\Profiler;
|
||||
use Aura\Sql\Profiler\ProfilerInterface;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
*
|
||||
* A lazy-connecting PDO with extended methods.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class ExtendedPdo extends AbstractExtendedPdo
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Constructor arguments for instantiating the PDO connection.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $args = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructor.
|
||||
*
|
||||
* This overrides the parent so that it can take connection attributes as a
|
||||
* constructor parameter, and set them after connection.
|
||||
*
|
||||
* @param string $dsn The data source name for the connection.
|
||||
*
|
||||
* @param string $username The username for the connection.
|
||||
*
|
||||
* @param string $password The password for the connection.
|
||||
*
|
||||
* @param array $options Driver-specific options for the connection.
|
||||
*
|
||||
* @param array $queries Queries to execute after the connection.
|
||||
*
|
||||
* @param ProfilerInterface $profiler Tracks and logs query profiles.
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.construct.php
|
||||
*
|
||||
*/
|
||||
public function __construct(
|
||||
$dsn,
|
||||
$username = null,
|
||||
$password = null,
|
||||
array $options = [],
|
||||
array $queries = [],
|
||||
ProfilerInterface $profiler = null
|
||||
) {
|
||||
// if no error mode is specified, use exceptions
|
||||
if (! isset($options[PDO::ATTR_ERRMODE])) {
|
||||
$options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
|
||||
}
|
||||
|
||||
// retain the arguments for later
|
||||
$this->args = [
|
||||
$dsn,
|
||||
$username,
|
||||
$password,
|
||||
$options,
|
||||
$queries
|
||||
];
|
||||
|
||||
// retain a profiler, instantiating a default one if needed
|
||||
if ($profiler === null) {
|
||||
$profiler = new Profiler();
|
||||
}
|
||||
$this->setProfiler($profiler);
|
||||
|
||||
// retain a query parser
|
||||
$parts = explode(':', $dsn);
|
||||
$parser = $this->newParser($parts[0]);
|
||||
$this->setParser($parser);
|
||||
|
||||
// set quotes for identifier names
|
||||
$this->setQuoteName($parts[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Connects to the database.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
if ($this->pdo) {
|
||||
return;
|
||||
}
|
||||
|
||||
// connect
|
||||
$this->profiler->start(__FUNCTION__);
|
||||
list($dsn, $username, $password, $options, $queries) = $this->args;
|
||||
$this->pdo = new PDO($dsn, $username, $password, $options);
|
||||
$this->profiler->finish();
|
||||
|
||||
// connection-time queries
|
||||
foreach ($queries as $query) {
|
||||
$this->exec($query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Disconnects from the database.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->profiler->start(__FUNCTION__);
|
||||
$this->pdo = null;
|
||||
$this->profiler->finish();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The purpose of this method is to hide sensitive data from stack traces.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function __debugInfo()
|
||||
{
|
||||
return [
|
||||
'args' => [
|
||||
$this->args[0],
|
||||
'****',
|
||||
'****',
|
||||
$this->args[3],
|
||||
$this->args[4],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Return the inner PDO (if any)
|
||||
*
|
||||
* @return \PDO
|
||||
*
|
||||
*/
|
||||
public function getPdo()
|
||||
{
|
||||
$this->connect();
|
||||
return $this->pdo;
|
||||
}
|
||||
}
|
412
includes/vendor/aura/sql/src/ExtendedPdoInterface.php
vendored
Normal file
412
includes/vendor/aura/sql/src/ExtendedPdoInterface.php
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql;
|
||||
|
||||
use Aura\Sql\Parser\ParserInterface;
|
||||
use Aura\Sql\Profiler\ProfilerInterface;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
*
|
||||
* An interface to the Aura.Sql extended PDO object.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
interface ExtendedPdoInterface extends PdoInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Connects to the database.
|
||||
*
|
||||
*/
|
||||
public function connect();
|
||||
|
||||
/**
|
||||
*
|
||||
* Disconnects from the database.
|
||||
*
|
||||
*/
|
||||
public function disconnect();
|
||||
|
||||
/**
|
||||
*
|
||||
* Performs a statement and returns the number of affected rows.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
*/
|
||||
public function fetchAffected($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches a sequential array of rows from the database; the rows
|
||||
* are represented as associative arrays.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function fetchAll($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches an associative array of rows from the database; the rows
|
||||
* are represented as associative arrays. The array of rows is keyed
|
||||
* on the first column of each row.
|
||||
*
|
||||
* N.b.: if multiple rows have the same first column value, the last
|
||||
* row with that value will override earlier rows.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function fetchAssoc($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches the first column of rows as a sequential array.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function fetchCol($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches multiple from the database as an associative array.
|
||||
* The first column will be the index
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @param int $style a fetch style defaults to PDO::FETCH_COLUMN for single
|
||||
* values, use PDO::FETCH_NAMED when fetching a multiple columns
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function fetchGroup(
|
||||
$statement,
|
||||
array $values = [],
|
||||
$style = PDO::FETCH_COLUMN
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches one row from the database as an object, mapping column values
|
||||
* to object properties.
|
||||
*
|
||||
* Warning: PDO "injects property-values BEFORE invoking the constructor -
|
||||
* in other words, if your class initializes property-values to defaults
|
||||
* in the constructor, you will be overwriting the values injected by
|
||||
* fetchObject() !"
|
||||
* <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744>
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @param string $class The name of the class to create.
|
||||
*
|
||||
* @param array $args Arguments to pass to the object constructor.
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
*/
|
||||
public function fetchObject(
|
||||
$statement,
|
||||
array $values = [],
|
||||
$class = 'stdClass',
|
||||
array $args = []
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches a sequential array of rows from the database; the rows
|
||||
* are represented as objects, where the column values are mapped to
|
||||
* object properties.
|
||||
*
|
||||
* Warning: PDO "injects property-values BEFORE invoking the constructor -
|
||||
* in other words, if your class initializes property-values to defaults
|
||||
* in the constructor, you will be overwriting the values injected by
|
||||
* fetchObject() !"
|
||||
* <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744>
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @param string $class The name of the class to create from each
|
||||
* row.
|
||||
*
|
||||
* @param array $args Arguments to pass to each object constructor.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function fetchObjects(
|
||||
$statement,
|
||||
array $values = [],
|
||||
$class = 'stdClass',
|
||||
array $args = []
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches one row from the database as an associative array.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function fetchOne($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches an associative array of rows as key-value pairs (first
|
||||
* column is the key, second column is the value).
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function fetchPairs($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Fetches the very first value (i.e., first column of the first row).
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
*/
|
||||
public function fetchValue($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the Parser instance.
|
||||
*
|
||||
* @return ParserInterface
|
||||
*
|
||||
*/
|
||||
public function getParser();
|
||||
|
||||
/**
|
||||
*
|
||||
* Return the inner PDO (if any)
|
||||
*
|
||||
* @return \PDO
|
||||
*
|
||||
*/
|
||||
public function getPdo();
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the Profiler instance.
|
||||
*
|
||||
* @return ProfilerInterface
|
||||
*
|
||||
*/
|
||||
public function getProfiler();
|
||||
|
||||
/**
|
||||
*
|
||||
* Quotes a multi-part (dotted) identifier name.
|
||||
*
|
||||
* @param string $name The multi-part identifier name.
|
||||
*
|
||||
* @return string The multi-part identifier name, quoted.
|
||||
*
|
||||
*/
|
||||
public function quoteName($name);
|
||||
|
||||
/**
|
||||
*
|
||||
* Quotes a single identifier name.
|
||||
*
|
||||
* @param string $name The identifier name.
|
||||
*
|
||||
* @return string The quoted identifier name.
|
||||
*
|
||||
*/
|
||||
public function quoteSingleName($name);
|
||||
|
||||
/**
|
||||
*
|
||||
* Is the PDO connection active?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function isConnected();
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets the Parser instance.
|
||||
*
|
||||
* @param ParserInterface $parser The Parser instance.
|
||||
*
|
||||
*/
|
||||
public function setParser(ParserInterface $parser);
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets the Profiler instance.
|
||||
*
|
||||
* @param ProfilerInterface $profiler The Profiler instance.
|
||||
*
|
||||
*/
|
||||
public function setProfiler(ProfilerInterface $profiler);
|
||||
|
||||
/**
|
||||
*
|
||||
* Yields rows from the database
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return \Generator
|
||||
*
|
||||
*/
|
||||
public function yieldAll($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Yields rows from the database keyed on the first column of each row.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return \Generator
|
||||
*
|
||||
*/
|
||||
public function yieldAssoc($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Yields the first column of all rows
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return \Generator
|
||||
*
|
||||
*/
|
||||
public function yieldCol($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Yields objects where the column values are mapped to object properties.
|
||||
*
|
||||
* Warning: PDO "injects property-values BEFORE invoking the constructor -
|
||||
* in other words, if your class initializes property-values to defaults
|
||||
* in the constructor, you will be overwriting the values injected by
|
||||
* fetchObject() !"
|
||||
* <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744>
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @param string $class The name of the class to create from each
|
||||
* row.
|
||||
*
|
||||
* @param array $args Arguments to pass to each object constructor.
|
||||
*
|
||||
* @return \Generator
|
||||
*
|
||||
*/
|
||||
public function yieldObjects(
|
||||
$statement,
|
||||
array $values = [],
|
||||
$class = 'stdClass',
|
||||
array $args = []
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* Yields key-value pairs (first column is the key, second column is the
|
||||
* value).
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return \Generator
|
||||
*
|
||||
*/
|
||||
public function yieldPairs($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Performs a query after preparing the statement with bound values, then
|
||||
* returns the result as a PDOStatement.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param array $values Values to bind to the query.
|
||||
*
|
||||
* @return \PDOStatement
|
||||
*
|
||||
*/
|
||||
public function perform($statement, array $values = []);
|
||||
|
||||
/**
|
||||
*
|
||||
* Prepares an SQL statement with bound values.
|
||||
*
|
||||
* This method only binds values that have placeholders in the
|
||||
* statement, thereby avoiding errors from PDO regarding too many bound
|
||||
* values. It also binds all sequential (question-mark) placeholders.
|
||||
*
|
||||
* If a placeholder value is an array, the array is converted to a string
|
||||
* of comma-separated quoted values; e.g., for an `IN (...)` condition.
|
||||
* The quoted string is replaced directly into the statement instead of
|
||||
* using `PDOStatement::bindValue()` proper.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare for execution.
|
||||
*
|
||||
* @param array $values The values to bind to the statement, if any.
|
||||
*
|
||||
* @return \PDOStatement
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.prepare.php
|
||||
*
|
||||
*/
|
||||
public function prepareWithValues($statement, array $values = []);
|
||||
}
|
318
includes/vendor/aura/sql/src/Parser/AbstractParser.php
vendored
Normal file
318
includes/vendor/aura/sql/src/Parser/AbstractParser.php
vendored
Normal file
@ -0,0 +1,318 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Parser;
|
||||
|
||||
use Aura\Sql\Exception\MissingParameter;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parsing/rebuilding functionality for all drivers.
|
||||
*
|
||||
* Note that this does not validate the syntax; it only replaces/rebuilds
|
||||
* placeholders in the query.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
abstract class AbstractParser implements ParserInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Split the query string on these regexes.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $split = [
|
||||
// single-quoted string
|
||||
"'(?:[^'\\\\]|\\\\'?)*'",
|
||||
// double-quoted string
|
||||
'"(?:[^"\\\\]|\\\\"?)*"',
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
* Skip query parts matching this regex.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
*/
|
||||
protected $skip = '/^(\'|\"|\:[^a-zA-Z_])/um';
|
||||
|
||||
/**
|
||||
*
|
||||
* The current numbered-placeholder in the original statement.
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
*/
|
||||
protected $num = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
* How many times has a named placeholder been used?
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $count = [
|
||||
'__' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
* The initial values to be bound.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $values = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* Final placeholders and values to bind.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $final_values = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* Rebuilds a statement with placeholders and bound values.
|
||||
*
|
||||
* @param string $statement The statement to rebuild.
|
||||
*
|
||||
* @param array $values The values to bind and/or replace into a statement.
|
||||
*
|
||||
* @return array An array where element 0 is the rebuilt statement and
|
||||
* element 1 is the rebuilt array of values.
|
||||
*
|
||||
*/
|
||||
public function rebuild($statement, array $values = [])
|
||||
{
|
||||
// match standard PDO execute() behavior of zero-indexed arrays
|
||||
if (array_key_exists(0, $values)) {
|
||||
array_unshift($values, null);
|
||||
}
|
||||
|
||||
$this->values = $values;
|
||||
$statement = $this->rebuildStatement($statement);
|
||||
return [$statement, $this->final_values];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Given a statement, rebuilds it with array values embedded.
|
||||
*
|
||||
* @param string $statement The SQL statement.
|
||||
*
|
||||
* @return string The rebuilt statement.
|
||||
*
|
||||
*/
|
||||
protected function rebuildStatement($statement)
|
||||
{
|
||||
$parts = $this->getParts($statement);
|
||||
return $this->rebuildParts($parts);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Given an array of statement parts, rebuilds each part.
|
||||
*
|
||||
* @param array $parts The statement parts.
|
||||
*
|
||||
* @return string The rebuilt statement.
|
||||
*
|
||||
*/
|
||||
protected function rebuildParts(array $parts)
|
||||
{
|
||||
$statement = '';
|
||||
foreach ($parts as $part) {
|
||||
$statement .= $this->rebuildPart($part);
|
||||
}
|
||||
return $statement;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Rebuilds a single statement part.
|
||||
*
|
||||
* @param string $part The statement part.
|
||||
*
|
||||
* @return string The rebuilt statement.
|
||||
*
|
||||
*/
|
||||
protected function rebuildPart($part)
|
||||
{
|
||||
if (preg_match($this->skip, $part)) {
|
||||
return $part;
|
||||
}
|
||||
|
||||
// split into subparts by ":name" and "?"
|
||||
$subs = preg_split(
|
||||
"/(?<!:)(:[a-zA-Z_][a-zA-Z0-9_]*)|(\?)/um",
|
||||
$part,
|
||||
-1,
|
||||
PREG_SPLIT_DELIM_CAPTURE
|
||||
);
|
||||
|
||||
// check subparts to expand placeholders for bound arrays
|
||||
return $this->prepareValuePlaceholders($subs);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Prepares the sub-parts of a query with placeholders.
|
||||
*
|
||||
* @param array $subs The query subparts.
|
||||
*
|
||||
* @return string The prepared subparts.
|
||||
*
|
||||
*/
|
||||
protected function prepareValuePlaceholders(array $subs)
|
||||
{
|
||||
$str = '';
|
||||
foreach ($subs as $i => $sub) {
|
||||
$char = substr($sub, 0, 1);
|
||||
if ($char == '?') {
|
||||
$str .= $this->prepareNumberedPlaceholder();
|
||||
} elseif ($char == ':') {
|
||||
$str .= $this->prepareNamedPlaceholder($sub);
|
||||
} else {
|
||||
$str .= $sub;
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Bind or quote a numbered placeholder in a query subpart.
|
||||
*
|
||||
* @return string The prepared query subpart.
|
||||
*
|
||||
* @throws MissingParameter
|
||||
*/
|
||||
protected function prepareNumberedPlaceholder()
|
||||
{
|
||||
$this->num ++;
|
||||
if (array_key_exists($this->num, $this->values) === false) {
|
||||
throw new MissingParameter("Parameter {$this->num} is missing from the bound values");
|
||||
}
|
||||
|
||||
$expanded = [];
|
||||
$values = (array) $this->values[$this->num];
|
||||
if (is_null($this->values[$this->num])) {
|
||||
$values[] = null;
|
||||
}
|
||||
foreach ($values as $value) {
|
||||
$count = ++ $this->count['__'];
|
||||
$name = "__{$count}";
|
||||
$expanded[] = ":{$name}";
|
||||
$this->final_values[$name] = $value;
|
||||
}
|
||||
return implode(', ', $expanded);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Bind or quote a named placeholder in a query subpart.
|
||||
*
|
||||
* @param string $sub The query subpart.
|
||||
*
|
||||
* @return string The prepared query subpart.
|
||||
*
|
||||
*/
|
||||
protected function prepareNamedPlaceholder($sub)
|
||||
{
|
||||
$orig = substr($sub, 1);
|
||||
if (array_key_exists($orig, $this->values) === false) {
|
||||
throw new MissingParameter("Parameter '{$orig}' is missing from the bound values");
|
||||
}
|
||||
|
||||
$name = $this->getPlaceholderName($orig);
|
||||
|
||||
// is the corresponding data element an array?
|
||||
$bind_array = is_array($this->values[$orig]);
|
||||
if ($bind_array) {
|
||||
// expand to multiple placeholders
|
||||
return $this->expandNamedPlaceholder($name, $this->values[$orig]);
|
||||
}
|
||||
|
||||
// not an array, retain the placeholder for later
|
||||
$this->final_values[$name] = $this->values[$orig];
|
||||
return ":$name";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Given an original placeholder name, return a replacement name.
|
||||
*
|
||||
* @param string $orig The original placeholder name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function getPlaceholderName($orig)
|
||||
{
|
||||
if (! isset($this->count[$orig])) {
|
||||
$this->count[$orig] = 0;
|
||||
return $orig;
|
||||
}
|
||||
|
||||
$count = ++ $this->count[$orig];
|
||||
return "{$orig}__{$count}";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Given a named placeholder for an array, expand it for the array values,
|
||||
* and bind those values to the expanded names.
|
||||
*
|
||||
* @param string $prefix The named placeholder.
|
||||
*
|
||||
* @param array $values The array values to be bound.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function expandNamedPlaceholder($prefix, array $values)
|
||||
{
|
||||
$i = 0;
|
||||
$expanded = [];
|
||||
foreach ($values as $value) {
|
||||
$name = "{$prefix}_{$i}";
|
||||
$expanded[] = ":{$name}";
|
||||
$this->final_values[$name] = $value;
|
||||
$i ++;
|
||||
}
|
||||
return implode(', ', $expanded);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Given a query string, split it into parts.
|
||||
*
|
||||
* @param string $statement The query string.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
protected function getParts($statement)
|
||||
{
|
||||
$split = implode('|', $this->split);
|
||||
return preg_split(
|
||||
"/($split)/um",
|
||||
$statement,
|
||||
-1,
|
||||
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
|
||||
);
|
||||
}
|
||||
}
|
44
includes/vendor/aura/sql/src/Parser/MysqlParser.php
vendored
Normal file
44
includes/vendor/aura/sql/src/Parser/MysqlParser.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Parser;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parsing/rebuilding functionality for the mysql driver.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class MysqlParser extends AbstractParser
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Split the query string on these regexes.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $split = [
|
||||
// single-quoted string
|
||||
"'(?:[^'\\\\]|\\\\'?)*'",
|
||||
// double-quoted string
|
||||
'"(?:[^"\\\\]|\\\\"?)*"',
|
||||
// backtick-quoted string
|
||||
'`(?:[^`\\\\]|\\\\`?)*`',
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
* Skip query parts matching this regex.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
*/
|
||||
protected $skip = '/^(\'|\"|\`)/um';
|
||||
}
|
36
includes/vendor/aura/sql/src/Parser/NullParser.php
vendored
Normal file
36
includes/vendor/aura/sql/src/Parser/NullParser.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Parser;
|
||||
|
||||
/**
|
||||
*
|
||||
* A parser/rebuilder that does nothing at all; use this when your placeholders
|
||||
* and bound-values are already perfectly matched.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class NullParser implements ParserInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Leaves the query and parameters alone.
|
||||
*
|
||||
* @param string $statement The query statement string.
|
||||
*
|
||||
* @param array $values Bind these values into the query.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function rebuild($statement, array $values = [])
|
||||
{
|
||||
return [$statement, $values];
|
||||
}
|
||||
}
|
34
includes/vendor/aura/sql/src/Parser/ParserInterface.php
vendored
Normal file
34
includes/vendor/aura/sql/src/Parser/ParserInterface.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Parser;
|
||||
|
||||
/**
|
||||
*
|
||||
* Interface for query parsing/rebuilding functionality.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
interface ParserInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Rebuilds a query and its parameters to adapt it to PDO's limitations,
|
||||
* and returns a list of queries.
|
||||
*
|
||||
* @param string $string The query statement string.
|
||||
*
|
||||
* @param array $parameters Bind these values into the query.
|
||||
*
|
||||
* @return array An array where element 0 is the rebuilt statement and
|
||||
* element 1 is the rebuilt array of values.
|
||||
*
|
||||
*/
|
||||
public function rebuild($string, array $parameters = []);
|
||||
}
|
46
includes/vendor/aura/sql/src/Parser/PgsqlParser.php
vendored
Normal file
46
includes/vendor/aura/sql/src/Parser/PgsqlParser.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Parser;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parsing/rebuilding functionality for the pgsl driver.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class PgsqlParser extends AbstractParser
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Split the query string on these regexes.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $split = [
|
||||
// single-quoted string
|
||||
"'(?:[^'\\\\]|\\\\'?)*'",
|
||||
// double-quoted string
|
||||
'"(?:[^"\\\\]|\\\\"?)*"',
|
||||
// double-dollar string (empty dollar-tag)
|
||||
'\$\$(?:[^\$]?)*\$\$',
|
||||
// dollar-tag string -- DOES NOT match tags properly
|
||||
'\$[^\$]+\$.*\$[^\$]+\$',
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
* Skip query parts matching this regex.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
*/
|
||||
protected $skip = '/^(\'|\"|\$|\:[^a-zA-Z_])/um';
|
||||
}
|
36
includes/vendor/aura/sql/src/Parser/SqliteParser.php
vendored
Normal file
36
includes/vendor/aura/sql/src/Parser/SqliteParser.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Parser;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parsing/rebuilding functionality for the sqlite driver.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class SqliteParser extends AbstractParser
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $split = [
|
||||
// single-quoted string
|
||||
"'(?:[^'\\\\]|\\\\'?)*'",
|
||||
// double-quoted string
|
||||
'"(?:[^"\\\\]|\\\\"?)*"',
|
||||
// backticked column names
|
||||
'`(?:[^`\\\\]|\\\\`?)*`',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $skip = '/^(\'|"|`|\:[^a-zA-Z_])/um';
|
||||
}
|
22
includes/vendor/aura/sql/src/Parser/SqlsrvParser.php
vendored
Normal file
22
includes/vendor/aura/sql/src/Parser/SqlsrvParser.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Parser;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parsing/rebuilding functionality for the sqlsrv driver.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
* @todo add $split and $skip for single quote, double quote, and square brackets
|
||||
*
|
||||
*/
|
||||
class SqlsrvParser extends AbstractParser
|
||||
{
|
||||
}
|
189
includes/vendor/aura/sql/src/PdoInterface.php
vendored
Normal file
189
includes/vendor/aura/sql/src/PdoInterface.php
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql;
|
||||
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
*
|
||||
* An interface to the native PDO object.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
interface PdoInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Begins a transaction and turns off autocommit mode.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.begintransaction.php
|
||||
*
|
||||
*/
|
||||
public function beginTransaction();
|
||||
|
||||
/**
|
||||
*
|
||||
* Commits the existing transaction and restores autocommit mode.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.commit.php
|
||||
*
|
||||
*/
|
||||
public function commit();
|
||||
|
||||
/**
|
||||
*
|
||||
* Gets the most recent error code.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
*/
|
||||
public function errorCode();
|
||||
|
||||
/**
|
||||
*
|
||||
* Gets the most recent error info.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function errorInfo();
|
||||
|
||||
/**
|
||||
*
|
||||
* Executes an SQL statement and returns the number of affected rows.
|
||||
*
|
||||
* @param string $statement The SQL statement to execute.
|
||||
*
|
||||
* @return int The number of rows affected.
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.exec.php
|
||||
*
|
||||
*/
|
||||
public function exec($statement);
|
||||
|
||||
/**
|
||||
*
|
||||
* Gets a PDO attribute value.
|
||||
*
|
||||
* @param mixed $attribute The PDO::ATTR_* constant.
|
||||
*
|
||||
* @return mixed The value for the attribute.
|
||||
*
|
||||
*/
|
||||
public function getAttribute($attribute);
|
||||
|
||||
/**
|
||||
*
|
||||
* Is a transaction currently active?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.intransaction.php
|
||||
*
|
||||
*/
|
||||
public function inTransaction();
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the last inserted autoincrement sequence value.
|
||||
*
|
||||
* @param string $name The name of the sequence to check; typically needed
|
||||
* only for PostgreSQL, where it takes the form of `<table>_<column>_seq`.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.lastinsertid.php
|
||||
*
|
||||
*/
|
||||
public function lastInsertId($name = null);
|
||||
|
||||
/**
|
||||
*
|
||||
* Prepares an SQL statement for execution.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare for execution.
|
||||
*
|
||||
* @param array $options Set these attributes on the returned
|
||||
* PDOStatement.
|
||||
*
|
||||
* @return \PDOStatement
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.prepare.php
|
||||
*
|
||||
*/
|
||||
public function prepare($statement, $options = null);
|
||||
|
||||
/**
|
||||
*
|
||||
* Queries the database and returns a PDOStatement.
|
||||
*
|
||||
* @param string $statement The SQL statement to prepare and execute.
|
||||
*
|
||||
* @param mixed ...$fetch Optional fetch-related parameters.
|
||||
*
|
||||
* @return \PDOStatement
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.query.php
|
||||
*
|
||||
*/
|
||||
public function query($statement, ...$fetch);
|
||||
|
||||
/**
|
||||
*
|
||||
* Quotes a value for use in an SQL statement.
|
||||
*
|
||||
* @param mixed $value The value to quote.
|
||||
*
|
||||
* @param int $parameter_type A data type hint for the database driver.
|
||||
*
|
||||
* @return string The quoted value.
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.quote.php
|
||||
*
|
||||
*/
|
||||
public function quote($value, $parameter_type = PDO::PARAM_STR);
|
||||
|
||||
/**
|
||||
*
|
||||
* Rolls back the current transaction and restores autocommit mode.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @see http://php.net/manual/en/pdo.rollback.php
|
||||
*
|
||||
*/
|
||||
public function rollBack();
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets a PDO attribute value.
|
||||
*
|
||||
* @param mixed $attribute The PDO::ATTR_* constant.
|
||||
*
|
||||
* @param mixed $value The value for the attribute.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function setAttribute($attribute, $value);
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns all currently available PDO drivers.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public static function getAvailableDrivers();
|
||||
}
|
64
includes/vendor/aura/sql/src/Profiler/MemoryLogger.php
vendored
Normal file
64
includes/vendor/aura/sql/src/Profiler/MemoryLogger.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Profiler;
|
||||
|
||||
use Psr\Log\AbstractLogger;
|
||||
|
||||
/**
|
||||
*
|
||||
* A naive memory-based logger.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class MemoryLogger extends AbstractLogger
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Log messages.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $messages = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* Logs a message.
|
||||
*
|
||||
* @param mixed $level The log level (ignored).
|
||||
*
|
||||
* @param string $message The log message.
|
||||
*
|
||||
* @param array $context Data to interpolate into the message.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function log($level, $message, array $context = [])
|
||||
{
|
||||
$replace = [];
|
||||
foreach ($context as $key => $val) {
|
||||
$replace['{' . $key . '}'] = $val;
|
||||
}
|
||||
$this->messages[] = strtr($message, $replace);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the logged messages.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function getMessages()
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
}
|
229
includes/vendor/aura/sql/src/Profiler/Profiler.php
vendored
Normal file
229
includes/vendor/aura/sql/src/Profiler/Profiler.php
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Profiler;
|
||||
|
||||
use Aura\Sql\Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
*
|
||||
* Sends query profiles to a logger.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
class Profiler implements ProfilerInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* The current profile information.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $context = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* Log profile data through this interface.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* Turns profile logging off and on.
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @see setActive()
|
||||
*
|
||||
*/
|
||||
protected $active = false;
|
||||
|
||||
/**
|
||||
*
|
||||
* The log level for all messages.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @see setLogLevel()
|
||||
*
|
||||
*/
|
||||
protected $logLevel = LogLevel::DEBUG;
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets the format for the log message, with placeholders.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @see setLogFormat()
|
||||
*
|
||||
*/
|
||||
protected $logFormat = "{function} ({duration} seconds): {statement} {backtrace}";
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger Record profiles through this interface.
|
||||
*
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger = null)
|
||||
{
|
||||
if ($logger === null) {
|
||||
$logger = new MemoryLogger();
|
||||
}
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Enable or disable profiler logging.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
*/
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = (bool) $active;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns true if logging is active.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the underlying logger instance.
|
||||
*
|
||||
* @return \Psr\Log\LoggerInterface
|
||||
*
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the level at which to log profile messages.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getLogLevel()
|
||||
{
|
||||
return $this->logLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Level at which to log profile messages.
|
||||
*
|
||||
* @param string $logLevel A PSR LogLevel constant.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setLogLevel($logLevel)
|
||||
{
|
||||
$this->logLevel = $logLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the log message format string, with placeholders.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getLogFormat()
|
||||
{
|
||||
return $this->logFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets the log message format string, with placeholders.
|
||||
*
|
||||
* @param string $logFormat
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setLogFormat($logFormat)
|
||||
{
|
||||
$this->logFormat = $logFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Starts a profile entry.
|
||||
*
|
||||
* @param string $function The function starting the profile entry.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function start($function)
|
||||
{
|
||||
if (! $this->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->context = [
|
||||
'function' => $function,
|
||||
'start' => microtime(true),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Finishes and logs a profile entry.
|
||||
*
|
||||
* @param string $statement The statement being profiled, if any.
|
||||
*
|
||||
* @param array $values The values bound to the statement, if any.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function finish($statement = null, array $values = [])
|
||||
{
|
||||
if (! $this->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
$finish = microtime(true);
|
||||
$e = new Exception();
|
||||
|
||||
$this->context['finish'] = $finish;
|
||||
$this->context['duration'] = $finish - $this->context['start'];
|
||||
$this->context['statement'] = $statement;
|
||||
$this->context['values'] = empty($values) ? '' : print_r($values, true);
|
||||
$this->context['backtrace'] = $e->getTraceAsString();
|
||||
|
||||
$this->logger->log($this->logLevel, $this->logFormat, $this->context);
|
||||
|
||||
$this->context = [];
|
||||
}
|
||||
}
|
110
includes/vendor/aura/sql/src/Profiler/ProfilerInterface.php
vendored
Normal file
110
includes/vendor/aura/sql/src/Profiler/ProfilerInterface.php
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of Aura for PHP.
|
||||
*
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
*/
|
||||
namespace Aura\Sql\Profiler;
|
||||
|
||||
/**
|
||||
*
|
||||
* Interface to send query profiles to a logger.
|
||||
*
|
||||
* @package Aura.Sql
|
||||
*
|
||||
*/
|
||||
interface ProfilerInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Enable or disable profiler logging.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
*/
|
||||
public function setActive($active);
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns true if logging is active.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function isActive();
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the underlying logger instance.
|
||||
*
|
||||
* @return \Psr\Log\LoggerInterface
|
||||
*
|
||||
*/
|
||||
public function getLogger();
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the level at which to log profile messages.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getLogLevel();
|
||||
|
||||
/**
|
||||
*
|
||||
* Level at which to log profile messages.
|
||||
*
|
||||
* @param string $logLevel A PSR LogLevel constant.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setLogLevel($logLevel);
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the log message format string, with placeholders.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getLogFormat();
|
||||
|
||||
/**
|
||||
*
|
||||
* Sets the log message format string, with placeholders.
|
||||
*
|
||||
* @param string $logFormat
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function setLogFormat($logFormat);
|
||||
|
||||
/**
|
||||
*
|
||||
* Starts a profile entry.
|
||||
*
|
||||
* @param string $function The function starting the profile entry.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function start($function);
|
||||
|
||||
/**
|
||||
*
|
||||
* Finishes and logs a profile entry.
|
||||
*
|
||||
* @param string $statement The statement being profiled, if any.
|
||||
*
|
||||
* @param array $values The values bound to the statement, if any.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
public function finish($statement = null, array $values = []);
|
||||
}
|
12
includes/vendor/autoload.php
vendored
Normal file
12
includes/vendor/autoload.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit2d6d15a8f6cc4bfbfd4a2943a6c4df59::getLoader();
|
232
includes/vendor/build-script/yourls-build.sh
vendored
Normal file
232
includes/vendor/build-script/yourls-build.sh
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
#!/bin/bash
|
||||
|
||||
####################################################################
|
||||
# This file is part of YOURLS
|
||||
#
|
||||
# List (and remove) unneeded files for production
|
||||
#
|
||||
# Run this script when adding, updating or removing a 3rd party
|
||||
# library that goes in the `vendor` directory.
|
||||
#
|
||||
# Typical use:
|
||||
#
|
||||
# $ composer update --no-dev --prefer-dist
|
||||
# $ ./includes/vendor/build-script/yourls-build.sh ./includes/vendor
|
||||
# $ commit & push
|
||||
#
|
||||
####################################################################
|
||||
|
||||
|
||||
## OPTIONS ##########################################################
|
||||
|
||||
# This directories in /vendor won't be cleaned up
|
||||
# Must be explicit names, case sensitive, no wildcard eg "README.*"
|
||||
#
|
||||
PRESERVE_IN_VENDOR=(
|
||||
'composer'
|
||||
'build-script'
|
||||
'symfony'
|
||||
)
|
||||
|
||||
# Files & dirs to keep in each library directory
|
||||
# Must be explicit names, case sensitive, no wildcard eg "README.*"
|
||||
#
|
||||
PRESERVE_IN_LIB=(
|
||||
'src'
|
||||
'library'
|
||||
'lib'
|
||||
'Psr'
|
||||
'README.md'
|
||||
'readme.md'
|
||||
'certificates'
|
||||
)
|
||||
|
||||
# Nothing to edit past this line !
|
||||
|
||||
|
||||
## VARS #############################################################
|
||||
|
||||
# Default values.
|
||||
TESTRUN=true
|
||||
|
||||
# Colors and fancyness
|
||||
RED='\033[0;31m'
|
||||
NORM='\033[0m'
|
||||
BOLD='\033[1m'
|
||||
GREEN='\033[0;32m'
|
||||
PURPLE='\033[0;35m'
|
||||
|
||||
# Set Script Name variable
|
||||
SCRIPT=`basename ${BASH_SOURCE[0]}`
|
||||
|
||||
|
||||
## FUNCS ############################################################
|
||||
|
||||
# Print help
|
||||
rtfm () {
|
||||
echo -e "\nUsage: "
|
||||
echo -e " ${BOLD}${SCRIPT}${NORM} [-dh] <directory to cleanup>"
|
||||
echo -e ""
|
||||
echo -e "Examples: "
|
||||
echo -e " ${BOLD}${SCRIPT}${NORM} [-dh] ."
|
||||
echo -e " ${BOLD}${SCRIPT}${NORM} [-dh] /some/path/to/clean"
|
||||
echo -e ""
|
||||
echo -e "Options:"
|
||||
echo -e " ${BOLD}-h${NORM} Display this ${BOLD}H${NORM}elp message"
|
||||
echo -e " ${BOLD}-d${NORM} Actually ${BOLD}D${NORM}elete files flagged by this script"
|
||||
echo -e ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
# in_array NEEDLE HAYSTACK
|
||||
# Return 0/1
|
||||
in_array () {
|
||||
local e
|
||||
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
# Cleans the mess
|
||||
cleanup () {
|
||||
# Return if function called with no parameter
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
# Directory we are in
|
||||
CUR=$1
|
||||
|
||||
# Loop over each file and delete those we don't want to keep
|
||||
echo -e "${PURPLE}Cleaning: $(basename $(dirname "$CUR"))/$(basename "$CUR") ${NORM}"
|
||||
for FILE in $(ls -A $CUR)
|
||||
do
|
||||
|
||||
if in_array $FILE "${PRESERVE_IN_LIB[@]}"
|
||||
then
|
||||
echo -e "${GREEN}+${NORM} KEEP: $FILE"
|
||||
else
|
||||
echo -e "${RED}-${NORM} DEL : $FILE"
|
||||
maybe_delete "${CUR}${FILE}"
|
||||
fi
|
||||
|
||||
done;
|
||||
|
||||
# If directory is empty, delete
|
||||
if [ ! "$(ls -A $CUR)" ]
|
||||
then
|
||||
echo -e "${RED}-${NORM} del : $(basename "$CUR") (empty dir)"
|
||||
maybe_delete "$CUR"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
}
|
||||
|
||||
# Delete file if not in test run
|
||||
maybe_delete () {
|
||||
if [ "$TESTRUN" = false ]
|
||||
then
|
||||
rm -rf "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check the number of arguments. If none are passed, print help and exit.
|
||||
args_or_die () {
|
||||
if [ $1 -eq 0 ]; then
|
||||
rtfm
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
## WORK #############################################################
|
||||
|
||||
# We should have some arguments
|
||||
args_or_die "$#"
|
||||
|
||||
# Check options
|
||||
while getopts "dh" opt; do
|
||||
case $opt in
|
||||
d)
|
||||
TESTRUN=false
|
||||
;;
|
||||
h)
|
||||
rtfm
|
||||
;;
|
||||
\?)
|
||||
rtfm
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1)) #This tells getopts to move on to the next argument.
|
||||
|
||||
# Again, we should have some arguments after dealing with options if any
|
||||
# Yes, this isn't perfect, there should be one test. Will do.
|
||||
args_or_die "$#"
|
||||
|
||||
# Check for valid dir
|
||||
if [ ! -d "$1" ]
|
||||
then
|
||||
echo -e "Need a valid directory, '${RED}$1${NORM}' is not."
|
||||
rtfm
|
||||
else
|
||||
# Resolve directory (expand '.' or '../stuff' as full path)
|
||||
TARGETDIR=$(cd "$1"; pwd)
|
||||
fi
|
||||
|
||||
# Dry run notice if applicable
|
||||
if [ "$TESTRUN" = true ]
|
||||
then
|
||||
echo -e "Test mode. ${RED}Nothing will be deleted${NORM}.\n"
|
||||
echo -e "Use with ${RED}-d${NORM} if you are OK with the proposed changes (or clean up manually).\n"
|
||||
fi
|
||||
|
||||
|
||||
# 1. Get list of all directories in target directory, except the one
|
||||
# listed in PRESERVE_IN_VENDOR that we don't want to touch
|
||||
#
|
||||
VENDORS=($(ls -d $TARGETDIR/*/))
|
||||
TEMP=(${VENDORS[@]})
|
||||
|
||||
for (( i=0; i<${#VENDORS[@]}; i++ ))
|
||||
do
|
||||
DIR=$(basename "${VENDORS[i]}")
|
||||
if in_array "$DIR" "${PRESERVE_IN_VENDOR[@]}"
|
||||
then
|
||||
unset TEMP[$i]
|
||||
fi
|
||||
done
|
||||
|
||||
VENDORS=(${TEMP[@]})
|
||||
|
||||
# 2. Loop over each directory and clean up
|
||||
#
|
||||
for DIR in ${VENDORS[@]}
|
||||
do
|
||||
SUBDIRS=$(ls -d $DIR*/ 2>/dev/null)
|
||||
if [ ! -z "$SUBDIRS" ]
|
||||
then
|
||||
# This VENDORS directory has subdirectory: process each subdir
|
||||
for SUBDIR in $SUBDIRS
|
||||
do
|
||||
cleanup $SUBDIR
|
||||
done;
|
||||
else
|
||||
# This directory contains no subdirectory
|
||||
cleanup $DIR
|
||||
fi
|
||||
done
|
||||
|
||||
# Exit reminder
|
||||
if [ "$TESTRUN" = true ]
|
||||
then
|
||||
echo -e "(${GREEN}Nothing has been deleted${NORM})\n"
|
||||
else
|
||||
echo -e "... all done $GREEN ;) $NORM\n"
|
||||
fi
|
||||
|
||||
|
||||
|
572
includes/vendor/composer/ClassLoader.php
vendored
Normal file
572
includes/vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,572 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
352
includes/vendor/composer/InstalledVersions.php
vendored
Normal file
352
includes/vendor/composer/InstalledVersions.php
vendored
Normal file
@ -0,0 +1,352 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
21
includes/vendor/composer/LICENSE
vendored
Normal file
21
includes/vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
12
includes/vendor/composer/autoload_classmap.php
vendored
Normal file
12
includes/vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
|
||||
'Requests' => $vendorDir . '/rmccue/requests/library/Requests.php',
|
||||
);
|
15
includes/vendor/composer/autoload_files.php
vendored
Normal file
15
includes/vendor/composer/autoload_files.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
|
||||
'b45b351e6b6f7487d819961fef2fda77' => $vendorDir . '/jakeasmith/http_build_url/src/http_build_url.php',
|
||||
'941748b3c8cae4466c827dfb5ca9602a' => $vendorDir . '/rmccue/requests/library/Deprecated.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
);
|
10
includes/vendor/composer/autoload_namespaces.php
vendored
Normal file
10
includes/vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'Ozh\\Bookmarkletgen\\' => array($vendorDir . '/ozh/bookmarkletgen/src'),
|
||||
);
|
24
includes/vendor/composer/autoload_psr4.php
vendored
Normal file
24
includes/vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'YOURLS\\' => array($baseDir . '/includes'),
|
||||
'WpOrg\\Requests\\' => array($vendorDir . '/rmccue/requests/src'),
|
||||
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
|
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
|
||||
'Spatie\\ArrayToXml\\' => array($vendorDir . '/spatie/array-to-xml/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||
'POMO\\' => array($vendorDir . '/pomo/pomo/src'),
|
||||
'MaxMind\\WebService\\' => array($vendorDir . '/maxmind/web-service-common/src/WebService'),
|
||||
'MaxMind\\Exception\\' => array($vendorDir . '/maxmind/web-service-common/src/Exception'),
|
||||
'MaxMind\\Db\\' => array($vendorDir . '/maxmind-db/reader/src/MaxMind/Db'),
|
||||
'GeoIp2\\' => array($vendorDir . '/geoip2/geoip2/src'),
|
||||
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
|
||||
'Aura\\Sql\\' => array($vendorDir . '/aura/sql/src'),
|
||||
);
|
57
includes/vendor/composer/autoload_real.php
vendored
Normal file
57
includes/vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit2d6d15a8f6cc4bfbfd4a2943a6c4df59
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit2d6d15a8f6cc4bfbfd4a2943a6c4df59', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit2d6d15a8f6cc4bfbfd4a2943a6c4df59', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit2d6d15a8f6cc4bfbfd4a2943a6c4df59::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInit2d6d15a8f6cc4bfbfd4a2943a6c4df59::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire2d6d15a8f6cc4bfbfd4a2943a6c4df59($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileIdentifier
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequire2d6d15a8f6cc4bfbfd4a2943a6c4df59($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}
|
149
includes/vendor/composer/autoload_static.php
vendored
Normal file
149
includes/vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit2d6d15a8f6cc4bfbfd4a2943a6c4df59
|
||||
{
|
||||
public static $files = array (
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
|
||||
'b45b351e6b6f7487d819961fef2fda77' => __DIR__ . '/..' . '/jakeasmith/http_build_url/src/http_build_url.php',
|
||||
'941748b3c8cae4466c827dfb5ca9602a' => __DIR__ . '/..' . '/rmccue/requests/library/Deprecated.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'Y' =>
|
||||
array (
|
||||
'YOURLS\\' => 7,
|
||||
),
|
||||
'W' =>
|
||||
array (
|
||||
'WpOrg\\Requests\\' => 15,
|
||||
),
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Php72\\' => 23,
|
||||
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
|
||||
'Spatie\\ArrayToXml\\' => 18,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\Log\\' => 8,
|
||||
'POMO\\' => 5,
|
||||
),
|
||||
'M' =>
|
||||
array (
|
||||
'MaxMind\\WebService\\' => 19,
|
||||
'MaxMind\\Exception\\' => 18,
|
||||
'MaxMind\\Db\\' => 11,
|
||||
),
|
||||
'G' =>
|
||||
array (
|
||||
'GeoIp2\\' => 7,
|
||||
),
|
||||
'C' =>
|
||||
array (
|
||||
'Composer\\CaBundle\\' => 18,
|
||||
),
|
||||
'A' =>
|
||||
array (
|
||||
'Aura\\Sql\\' => 9,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'YOURLS\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../../..' . '/includes',
|
||||
),
|
||||
'WpOrg\\Requests\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/rmccue/requests/src',
|
||||
),
|
||||
'Symfony\\Polyfill\\Php72\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
|
||||
),
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||
),
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
|
||||
),
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
|
||||
),
|
||||
'Spatie\\ArrayToXml\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/spatie/array-to-xml/src',
|
||||
),
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
||||
),
|
||||
'POMO\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/pomo/pomo/src',
|
||||
),
|
||||
'MaxMind\\WebService\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService',
|
||||
),
|
||||
'MaxMind\\Exception\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception',
|
||||
),
|
||||
'MaxMind\\Db\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db',
|
||||
),
|
||||
'GeoIp2\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/geoip2/geoip2/src',
|
||||
),
|
||||
'Composer\\CaBundle\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
|
||||
),
|
||||
'Aura\\Sql\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/aura/sql/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'O' =>
|
||||
array (
|
||||
'Ozh\\Bookmarkletgen\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ozh/bookmarkletgen/src',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
|
||||
'Requests' => __DIR__ . '/..' . '/rmccue/requests/library/Requests.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit2d6d15a8f6cc4bfbfd4a2943a6c4df59::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit2d6d15a8f6cc4bfbfd4a2943a6c4df59::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit2d6d15a8f6cc4bfbfd4a2943a6c4df59::$prefixesPsr0;
|
||||
$loader->classMap = ComposerStaticInit2d6d15a8f6cc4bfbfd4a2943a6c4df59::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
19
includes/vendor/composer/ca-bundle/LICENSE
vendored
Normal file
19
includes/vendor/composer/ca-bundle/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2016 Composer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
85
includes/vendor/composer/ca-bundle/README.md
vendored
Normal file
85
includes/vendor/composer/ca-bundle/README.md
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
composer/ca-bundle
|
||||
==================
|
||||
|
||||
Small utility library that lets you find a path to the system CA bundle,
|
||||
and includes a fallback to the Mozilla CA bundle.
|
||||
|
||||
Originally written as part of [composer/composer](https://github.com/composer/composer),
|
||||
now extracted and made available as a stand-alone library.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install the latest version with:
|
||||
|
||||
```bash
|
||||
$ composer require composer/ca-bundle
|
||||
```
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.
|
||||
|
||||
|
||||
Basic usage
|
||||
-----------
|
||||
|
||||
### `Composer\CaBundle\CaBundle`
|
||||
|
||||
- `CaBundle::getSystemCaRootBundlePath()`: Returns the system CA bundle path, or a path to the bundled one as fallback
|
||||
- `CaBundle::getBundledCaBundlePath()`: Returns the path to the bundled CA file
|
||||
- `CaBundle::validateCaFile($filename)`: Validates a CA file using openssl_x509_parse only if it is safe to use
|
||||
- `CaBundle::isOpensslParseSafe()`: Test if it is safe to use the PHP function openssl_x509_parse()
|
||||
- `CaBundle::reset()`: Resets the static caches
|
||||
|
||||
|
||||
#### To use with curl
|
||||
|
||||
```php
|
||||
$curl = curl_init("https://example.org/");
|
||||
|
||||
$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
|
||||
if (is_dir($caPathOrFile)) {
|
||||
curl_setopt($curl, CURLOPT_CAPATH, $caPathOrFile);
|
||||
} else {
|
||||
curl_setopt($curl, CURLOPT_CAINFO, $caPathOrFile);
|
||||
}
|
||||
|
||||
$result = curl_exec($curl);
|
||||
```
|
||||
|
||||
#### To use with php streams
|
||||
|
||||
```php
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET"
|
||||
)
|
||||
);
|
||||
|
||||
$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
|
||||
if (is_dir($caPathOrFile)) {
|
||||
$opts['ssl']['capath'] = $caPathOrFile;
|
||||
} else {
|
||||
$opts['ssl']['cafile'] = $caPathOrFile;
|
||||
}
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$result = file_get_contents('https://example.com', false, $context);
|
||||
```
|
||||
|
||||
#### To use with Guzzle
|
||||
|
||||
```php
|
||||
$client = new \GuzzleHttp\Client([
|
||||
\GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
|
||||
]);
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
composer/ca-bundle is licensed under the MIT License, see the LICENSE file for details.
|
54
includes/vendor/composer/ca-bundle/composer.json
vendored
Normal file
54
includes/vendor/composer/ca-bundle/composer.json
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"cabundle",
|
||||
"cacert",
|
||||
"certificate",
|
||||
"ssl",
|
||||
"tls"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "http://seld.be"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"irc": "irc://irc.freenode.org/composer",
|
||||
"issues": "https://github.com/composer/ca-bundle/issues"
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^4.2 || ^5",
|
||||
"phpstan/phpstan": "^0.12.55",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Composer\\CaBundle\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Composer\\CaBundle\\": "tests"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor/bin/simple-phpunit",
|
||||
"phpstan": "vendor/bin/phpstan analyse"
|
||||
}
|
||||
}
|
3232
includes/vendor/composer/ca-bundle/res/cacert.pem
vendored
Normal file
3232
includes/vendor/composer/ca-bundle/res/cacert.pem
vendored
Normal file
File diff suppressed because it is too large
Load Diff
431
includes/vendor/composer/ca-bundle/src/CaBundle.php
vendored
Normal file
431
includes/vendor/composer/ca-bundle/src/CaBundle.php
vendored
Normal file
@ -0,0 +1,431 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of composer/ca-bundle.
|
||||
*
|
||||
* (c) Composer <https://github.com/composer>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\CaBundle;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Process\PhpProcess;
|
||||
|
||||
/**
|
||||
* @author Chris Smith <chris@cs278.org>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class CaBundle
|
||||
{
|
||||
/** @var string|null */
|
||||
private static $caPath;
|
||||
/** @var array<string, bool> */
|
||||
private static $caFileValidity = array();
|
||||
/** @var bool|null */
|
||||
private static $useOpensslParse;
|
||||
|
||||
/**
|
||||
* Returns the system CA bundle path, or a path to the bundled one
|
||||
*
|
||||
* This method was adapted from Sslurp.
|
||||
* https://github.com/EvanDotPro/Sslurp
|
||||
*
|
||||
* (c) Evan Coury <me@evancoury.com>
|
||||
*
|
||||
* For the full copyright and license information, please see below:
|
||||
*
|
||||
* Copyright (c) 2013, Evan Coury
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
||||
* @return string path to a CA bundle file or directory
|
||||
*/
|
||||
public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
|
||||
{
|
||||
if (self::$caPath !== null) {
|
||||
return self::$caPath;
|
||||
}
|
||||
$caBundlePaths = array();
|
||||
|
||||
// If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
|
||||
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
||||
$caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
|
||||
|
||||
// If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
|
||||
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
||||
$caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
|
||||
|
||||
$caBundlePaths[] = ini_get('openssl.cafile');
|
||||
$caBundlePaths[] = ini_get('openssl.capath');
|
||||
|
||||
$otherLocations = array(
|
||||
'/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
|
||||
'/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
|
||||
'/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
|
||||
'/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
|
||||
'/usr/ssl/certs/ca-bundle.crt', // Cygwin
|
||||
'/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
|
||||
'/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
|
||||
'/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
|
||||
'/etc/ssl/cert.pem', // OpenBSD
|
||||
'/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
|
||||
'/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
|
||||
'/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package
|
||||
);
|
||||
|
||||
foreach($otherLocations as $location) {
|
||||
$otherLocations[] = dirname($location);
|
||||
}
|
||||
|
||||
$caBundlePaths = array_merge($caBundlePaths, $otherLocations);
|
||||
|
||||
foreach ($caBundlePaths as $caBundle) {
|
||||
if ($caBundle && self::caFileUsable($caBundle, $logger)) {
|
||||
return self::$caPath = $caBundle;
|
||||
}
|
||||
|
||||
if ($caBundle && self::caDirUsable($caBundle, $logger)) {
|
||||
return self::$caPath = $caBundle;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the bundled CA file
|
||||
*
|
||||
* In case you don't want to trust the user or the system, you can use this directly
|
||||
*
|
||||
* @return string path to a CA bundle file
|
||||
*/
|
||||
public static function getBundledCaBundlePath()
|
||||
{
|
||||
$caBundleFile = __DIR__.'/../res/cacert.pem';
|
||||
|
||||
// cURL does not understand 'phar://' paths
|
||||
// see https://github.com/composer/ca-bundle/issues/10
|
||||
if (0 === strpos($caBundleFile, 'phar://')) {
|
||||
$tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-');
|
||||
if (false === $tempCaBundleFile) {
|
||||
throw new \RuntimeException('Could not create a temporary file to store the bundled CA file');
|
||||
}
|
||||
|
||||
file_put_contents(
|
||||
$tempCaBundleFile,
|
||||
file_get_contents($caBundleFile)
|
||||
);
|
||||
|
||||
register_shutdown_function(function() use ($tempCaBundleFile) {
|
||||
@unlink($tempCaBundleFile);
|
||||
});
|
||||
|
||||
$caBundleFile = $tempCaBundleFile;
|
||||
}
|
||||
|
||||
return $caBundleFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a CA file using opensl_x509_parse only if it is safe to use
|
||||
*
|
||||
* @param string $filename
|
||||
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateCaFile($filename, LoggerInterface $logger = null)
|
||||
{
|
||||
static $warned = false;
|
||||
|
||||
if (isset(self::$caFileValidity[$filename])) {
|
||||
return self::$caFileValidity[$filename];
|
||||
}
|
||||
|
||||
$contents = file_get_contents($filename);
|
||||
|
||||
// assume the CA is valid if php is vulnerable to
|
||||
// https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
|
||||
if (!static::isOpensslParseSafe()) {
|
||||
if (!$warned && $logger) {
|
||||
$logger->warning(sprintf(
|
||||
'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
|
||||
PHP_VERSION
|
||||
));
|
||||
$warned = true;
|
||||
}
|
||||
|
||||
$isValid = !empty($contents);
|
||||
} elseif (is_string($contents) && strlen($contents) > 0) {
|
||||
$contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
|
||||
if (null === $contents) {
|
||||
// regex extraction failed
|
||||
$isValid = false;
|
||||
} else {
|
||||
$isValid = (bool) openssl_x509_parse($contents);
|
||||
}
|
||||
} else {
|
||||
$isValid = false;
|
||||
}
|
||||
|
||||
if ($logger) {
|
||||
$logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
|
||||
}
|
||||
|
||||
return self::$caFileValidity[$filename] = $isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if it is safe to use the PHP function openssl_x509_parse().
|
||||
*
|
||||
* This checks if OpenSSL extensions is vulnerable to remote code execution
|
||||
* via the exploit documented as CVE-2013-6420.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isOpensslParseSafe()
|
||||
{
|
||||
if (null !== self::$useOpensslParse) {
|
||||
return self::$useOpensslParse;
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID >= 50600) {
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
// Vulnerable:
|
||||
// PHP 5.3.0 - PHP 5.3.27
|
||||
// PHP 5.4.0 - PHP 5.4.22
|
||||
// PHP 5.5.0 - PHP 5.5.6
|
||||
if (
|
||||
(PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
|
||||
|| (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
|
||||
|| PHP_VERSION_ID >= 50507
|
||||
) {
|
||||
// This version of PHP has the fix for CVE-2013-6420 applied.
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
// Windows is probably insecure in this case.
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
$compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
|
||||
$regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
|
||||
|
||||
if (preg_match($regex, PHP_VERSION, $m)) {
|
||||
return ((int) $m[1]) >= $fixedVersion;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Hard coded list of PHP distributions with the fix backported.
|
||||
if (
|
||||
$compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
|
||||
|| $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
|
||||
|| $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
|
||||
) {
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
// Symfony Process component is missing so we assume it is unsafe at this point
|
||||
if (!class_exists('Symfony\Component\Process\PhpProcess')) {
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
// This is where things get crazy, because distros backport security
|
||||
// fixes the chances are on NIX systems the fix has been applied but
|
||||
// it's not possible to verify that from the PHP version.
|
||||
//
|
||||
// To verify exec a new PHP process and run the issue testcase with
|
||||
// known safe input that replicates the bug.
|
||||
|
||||
// Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
|
||||
// changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
|
||||
$cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
|
||||
$script = <<<'EOT'
|
||||
|
||||
error_reporting(-1);
|
||||
$info = openssl_x509_parse(base64_decode('%s'));
|
||||
var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
|
||||
|
||||
EOT;
|
||||
$script = '<'."?php\n".sprintf($script, $cert);
|
||||
|
||||
try {
|
||||
$process = new PhpProcess($script);
|
||||
$process->mustRun();
|
||||
} catch (\Exception $e) {
|
||||
// In the case of any exceptions just accept it is not possible to
|
||||
// determine the safety of openssl_x509_parse and bail out.
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
$output = preg_split('{\r?\n}', trim($process->getOutput()));
|
||||
$errorOutput = trim($process->getErrorOutput());
|
||||
|
||||
if (
|
||||
is_array($output)
|
||||
&& count($output) === 3
|
||||
&& $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
|
||||
&& $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
|
||||
&& $output[2] === 'int(-1)'
|
||||
&& preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
|
||||
) {
|
||||
// This PHP has the fix backported probably by a distro security team.
|
||||
return self::$useOpensslParse = true;
|
||||
}
|
||||
|
||||
return self::$useOpensslParse = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the static caches
|
||||
* @return void
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
self::$caFileValidity = array();
|
||||
self::$caPath = null;
|
||||
self::$useOpensslParse = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return string|false
|
||||
*/
|
||||
private static function getEnvVariable($name)
|
||||
{
|
||||
if (isset($_SERVER[$name])) {
|
||||
return (string) $_SERVER[$name];
|
||||
}
|
||||
|
||||
if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|false $certFile
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function caFileUsable($certFile, LoggerInterface $logger = null)
|
||||
{
|
||||
return $certFile
|
||||
&& static::isFile($certFile, $logger)
|
||||
&& static::isReadable($certFile, $logger)
|
||||
&& static::validateCaFile($certFile, $logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|false $certDir
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function caDirUsable($certDir, LoggerInterface $logger = null)
|
||||
{
|
||||
return $certDir
|
||||
&& static::isDir($certDir, $logger)
|
||||
&& static::isReadable($certDir, $logger)
|
||||
&& static::glob($certDir . '/*', $logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $certFile
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function isFile($certFile, LoggerInterface $logger = null)
|
||||
{
|
||||
$isFile = @is_file($certFile);
|
||||
if (!$isFile && $logger) {
|
||||
$logger->debug(sprintf('Checked CA file %s does not exist or it is not a file.', $certFile));
|
||||
}
|
||||
|
||||
return $isFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $certDir
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function isDir($certDir, LoggerInterface $logger = null)
|
||||
{
|
||||
$isDir = @is_dir($certDir);
|
||||
if (!$isDir && $logger) {
|
||||
$logger->debug(sprintf('Checked directory %s does not exist or it is not a directory.', $certDir));
|
||||
}
|
||||
|
||||
return $isDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $certFileOrDir
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function isReadable($certFileOrDir, LoggerInterface $logger = null)
|
||||
{
|
||||
$isReadable = @is_readable($certFileOrDir);
|
||||
if (!$isReadable && $logger) {
|
||||
$logger->debug(sprintf('Checked file or directory %s is not readable.', $certFileOrDir));
|
||||
}
|
||||
|
||||
return $isReadable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $pattern
|
||||
* @param LoggerInterface|null $logger
|
||||
* @return bool
|
||||
*/
|
||||
private static function glob($pattern, LoggerInterface $logger = null)
|
||||
{
|
||||
$certs = glob($pattern);
|
||||
if ($certs === false) {
|
||||
if ($logger) {
|
||||
$logger->debug(sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count($certs) === 0) {
|
||||
if ($logger) {
|
||||
$logger->debug(sprintf("No CA files found for pattern: %s", $pattern));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
1011
includes/vendor/composer/installed.json
vendored
Normal file
1011
includes/vendor/composer/installed.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
158
includes/vendor/composer/installed.php
vendored
Normal file
158
includes/vendor/composer/installed.php
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '59464102ee27cb5c808625c92448a48cebefda6f',
|
||||
'name' => 'yourls/yourls',
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'aura/sql' => array(
|
||||
'pretty_version' => '3.1.0',
|
||||
'version' => '3.1.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../aura/sql',
|
||||
'aliases' => array(),
|
||||
'reference' => '88d8b8ed1bcfd588a649fdc7e7ac89ec047abbca',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'composer/ca-bundle' => array(
|
||||
'pretty_version' => '1.3.1',
|
||||
'version' => '1.3.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/./ca-bundle',
|
||||
'aliases' => array(),
|
||||
'reference' => '4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'geoip2/geoip2' => array(
|
||||
'pretty_version' => 'v2.12.2',
|
||||
'version' => '2.12.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../geoip2/geoip2',
|
||||
'aliases' => array(),
|
||||
'reference' => '83adb44ac4b9553d36b579a14673ed124583082f',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jakeasmith/http_build_url' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jakeasmith/http_build_url',
|
||||
'aliases' => array(),
|
||||
'reference' => '93c273e77cb1edead0cf8bcf8cd2003428e74e37',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'maxmind-db/reader' => array(
|
||||
'pretty_version' => 'v1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../maxmind-db/reader',
|
||||
'aliases' => array(),
|
||||
'reference' => 'b1f3c0699525336d09cc5161a2861268d9f2ae5b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'maxmind/web-service-common' => array(
|
||||
'pretty_version' => 'v0.9.0',
|
||||
'version' => '0.9.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../maxmind/web-service-common',
|
||||
'aliases' => array(),
|
||||
'reference' => '4dc5a3e8df38aea4ca3b1096cee3a038094e9b53',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ozh/bookmarkletgen' => array(
|
||||
'pretty_version' => '1.2',
|
||||
'version' => '1.2.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ozh/bookmarkletgen',
|
||||
'aliases' => array(),
|
||||
'reference' => '3319b53c493a1474a03d1cc4e087617652284c20',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'pomo/pomo' => array(
|
||||
'pretty_version' => 'v1.4.1',
|
||||
'version' => '1.4.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../pomo/pomo',
|
||||
'aliases' => array(),
|
||||
'reference' => '1594bd1f90c89a45ffc3da2ee6d5d582bfac7542',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'rmccue/requests' => array(
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../rmccue/requests',
|
||||
'aliases' => array(),
|
||||
'reference' => 'b01ce7c91657d604f298751686d7f5eec87b9493',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'spatie/array-to-xml' => array(
|
||||
'pretty_version' => '2.16.0',
|
||||
'version' => '2.16.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../spatie/array-to-xml',
|
||||
'aliases' => array(),
|
||||
'reference' => 'db39308c5236b69b89cadc3f44f191704814eae2',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-intl-idn' => array(
|
||||
'pretty_version' => 'v1.25.0',
|
||||
'version' => '1.25.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn',
|
||||
'aliases' => array(),
|
||||
'reference' => '749045c69efb97c70d25d7463abba812e91f3a44',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-intl-normalizer' => array(
|
||||
'pretty_version' => 'v1.25.0',
|
||||
'version' => '1.25.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
|
||||
'aliases' => array(),
|
||||
'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.25.0',
|
||||
'version' => '1.25.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php72' => array(
|
||||
'pretty_version' => 'v1.25.0',
|
||||
'version' => '1.25.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php72',
|
||||
'aliases' => array(),
|
||||
'reference' => '9a142215a36a3888e30d0a9eeea9766764e96976',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'yourls/yourls' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '59464102ee27cb5c808625c92448a48cebefda6f',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
26
includes/vendor/composer/platform_check.php
vendored
Normal file
26
includes/vendor/composer/platform_check.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70400)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
428
includes/vendor/geoip2/geoip2/README.md
vendored
Normal file
428
includes/vendor/geoip2/geoip2/README.md
vendored
Normal file
@ -0,0 +1,428 @@
|
||||
# GeoIP2 PHP API #
|
||||
|
||||
## Description ##
|
||||
|
||||
This package provides an API for the GeoIP2 and GeoLite2
|
||||
[web services](https://dev.maxmind.com/geoip/docs/web-services?lang=en) and
|
||||
[databases](https://dev.maxmind.com/geoip/docs/databases?lang=en).
|
||||
|
||||
## Install via Composer ##
|
||||
|
||||
We recommend installing this package with [Composer](https://getcomposer.org/).
|
||||
|
||||
### Download Composer ###
|
||||
|
||||
To download Composer, run in the root directory of your project:
|
||||
|
||||
```bash
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
```
|
||||
|
||||
You should now have the file `composer.phar` in your project directory.
|
||||
|
||||
### Install Dependencies ###
|
||||
|
||||
Run in your project root:
|
||||
|
||||
```sh
|
||||
php composer.phar require geoip2/geoip2:~2.0
|
||||
```
|
||||
|
||||
You should now have the files `composer.json` and `composer.lock` as well as
|
||||
the directory `vendor` in your project directory. If you use a version control
|
||||
system, `composer.json` should be added to it.
|
||||
|
||||
### Require Autoloader ###
|
||||
|
||||
After installing the dependencies, you need to require the Composer autoloader
|
||||
from your code:
|
||||
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
```
|
||||
|
||||
## Install via Phar ##
|
||||
|
||||
Although we strongly recommend using Composer, we also provide a
|
||||
[phar archive](https://php.net/manual/en/book.phar.php) containing most of the
|
||||
dependencies for GeoIP2. Our latest phar archive is available on
|
||||
[our releases page](https://github.com/maxmind/GeoIP2-php/releases).
|
||||
|
||||
### Install Dependencies ###
|
||||
|
||||
In order to use the phar archive, you must have the PHP
|
||||
[Phar extension](https://php.net/manual/en/book.phar.php) installed and
|
||||
enabled.
|
||||
|
||||
If you will be making web service requests, you must have the PHP
|
||||
[cURL extension](https://php.net/manual/en/book.curl.php)
|
||||
installed to use this archive. For Debian based distributions, this can
|
||||
typically be found in the the `php-curl` package. For other operating
|
||||
systems, please consult the relevant documentation. After installing the
|
||||
extension you may need to restart your web server.
|
||||
|
||||
If you are missing this extension, you will see errors like the following:
|
||||
|
||||
```
|
||||
PHP Fatal error: Uncaught Error: Call to undefined function MaxMind\WebService\curl_version()
|
||||
```
|
||||
|
||||
### Require Package ###
|
||||
|
||||
To use the archive, just require it from your script:
|
||||
|
||||
```php
|
||||
require 'geoip2.phar';
|
||||
```
|
||||
|
||||
## Optional C Extension ##
|
||||
|
||||
The [MaxMind DB API](https://github.com/maxmind/MaxMind-DB-Reader-php)
|
||||
includes an optional C extension that you may install to dramatically increase
|
||||
the performance of lookups in GeoIP2 or GeoLite2 databases. To install, please
|
||||
follow the instructions included with that API.
|
||||
|
||||
The extension has no effect on web-service lookups.
|
||||
|
||||
## IP Geolocation Usage ##
|
||||
|
||||
IP geolocation is inherently imprecise. Locations are often near the center of
|
||||
the population. Any location provided by a GeoIP2 database or web service
|
||||
should not be used to identify a particular address or household.
|
||||
|
||||
## Database Reader ##
|
||||
|
||||
### Usage ###
|
||||
|
||||
To use this API, you must create a new `\GeoIp2\Database\Reader` object with
|
||||
the path to the database file as the first argument to the constructor. You
|
||||
may then call the method corresponding to the database you are using.
|
||||
|
||||
If the lookup succeeds, the method call will return a model class for the
|
||||
record in the database. This model in turn contains multiple container
|
||||
classes for the different parts of the data such as the city in which the
|
||||
IP address is located.
|
||||
|
||||
If the record is not found, a `\GeoIp2\Exception\AddressNotFoundException`
|
||||
is thrown. If the database is invalid or corrupt, a
|
||||
`\MaxMind\Db\InvalidDatabaseException` will be thrown.
|
||||
|
||||
See the API documentation for more details.
|
||||
|
||||
### City Example ###
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// This creates the Reader object, which should be reused across
|
||||
// lookups.
|
||||
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-City.mmdb');
|
||||
|
||||
// Replace "city" with the appropriate method for your database, e.g.,
|
||||
// "country".
|
||||
$record = $reader->city('128.101.101.101');
|
||||
|
||||
print($record->country->isoCode . "\n"); // 'US'
|
||||
print($record->country->name . "\n"); // 'United States'
|
||||
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
||||
|
||||
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
||||
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
||||
|
||||
print($record->city->name . "\n"); // 'Minneapolis'
|
||||
|
||||
print($record->postal->code . "\n"); // '55455'
|
||||
|
||||
print($record->location->latitude . "\n"); // 44.9733
|
||||
print($record->location->longitude . "\n"); // -93.2323
|
||||
|
||||
print($record->traits->network . "\n"); // '128.101.101.101/32'
|
||||
|
||||
```
|
||||
|
||||
### Anonymous IP Example ###
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// This creates the Reader object, which should be reused across
|
||||
// lookups.
|
||||
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Anonymous-IP.mmdb');
|
||||
|
||||
$record = $reader->anonymousIp('128.101.101.101');
|
||||
|
||||
if ($record->isAnonymous) { print "anon\n"; }
|
||||
print($record->ipAddress . "\n"); // '128.101.101.101'
|
||||
print($record->network . "\n"); // '128.101.101.101/32'
|
||||
|
||||
```
|
||||
|
||||
### Connection-Type Example ###
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// This creates the Reader object, which should be reused across
|
||||
// lookups.
|
||||
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Connection-Type.mmdb');
|
||||
|
||||
$record = $reader->connectionType('128.101.101.101');
|
||||
|
||||
print($record->connectionType . "\n"); // 'Corporate'
|
||||
print($record->ipAddress . "\n"); // '128.101.101.101'
|
||||
print($record->network . "\n"); // '128.101.101.101/32'
|
||||
|
||||
```
|
||||
|
||||
### Domain Example ###
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// This creates the Reader object, which should be reused across
|
||||
// lookups.
|
||||
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Domain.mmdb');
|
||||
|
||||
$record = $reader->domain('128.101.101.101');
|
||||
|
||||
print($record->domain . "\n"); // 'umn.edu'
|
||||
print($record->ipAddress . "\n"); // '128.101.101.101'
|
||||
print($record->network . "\n"); // '128.101.101.101/32'
|
||||
|
||||
```
|
||||
|
||||
### Enterprise Example ###
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// This creates the Reader object, which should be reused across
|
||||
// lookups.
|
||||
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Enterprise.mmdb');
|
||||
|
||||
// Use the ->enterprise method to do a lookup in the Enterprise database
|
||||
$record = $reader->enterprise('128.101.101.101');
|
||||
|
||||
print($record->country->confidence . "\n"); // 99
|
||||
print($record->country->isoCode . "\n"); // 'US'
|
||||
print($record->country->name . "\n"); // 'United States'
|
||||
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
||||
|
||||
print($record->mostSpecificSubdivision->confidence . "\n"); // 77
|
||||
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
||||
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
||||
|
||||
print($record->city->confidence . "\n"); // 60
|
||||
print($record->city->name . "\n"); // 'Minneapolis'
|
||||
|
||||
print($record->postal->code . "\n"); // '55455'
|
||||
|
||||
print($record->location->accuracyRadius . "\n"); // 50
|
||||
print($record->location->latitude . "\n"); // 44.9733
|
||||
print($record->location->longitude . "\n"); // -93.2323
|
||||
|
||||
print($record->traits->network . "\n"); // '128.101.101.101/32'
|
||||
|
||||
```
|
||||
|
||||
### ISP Example ###
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// This creates the Reader object, which should be reused across
|
||||
// lookups.
|
||||
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-ISP.mmdb');
|
||||
|
||||
$record = $reader->isp('128.101.101.101');
|
||||
|
||||
print($record->autonomousSystemNumber . "\n"); // 217
|
||||
print($record->autonomousSystemOrganization . "\n"); // 'University of Minnesota'
|
||||
print($record->isp . "\n"); // 'University of Minnesota'
|
||||
print($record->organization . "\n"); // 'University of Minnesota'
|
||||
|
||||
print($record->ipAddress . "\n"); // '128.101.101.101'
|
||||
print($record->network . "\n"); // '128.101.101.101/32'
|
||||
|
||||
```
|
||||
|
||||
## Web Service Client ##
|
||||
|
||||
### Usage ###
|
||||
|
||||
To use this API, you must create a new `\GeoIp2\WebService\Client`
|
||||
object with your `$accountId` and `$licenseKey`:
|
||||
|
||||
```php
|
||||
$client = new Client(42, 'abcdef123456');
|
||||
```
|
||||
|
||||
You may also call the constructor with additional arguments. The third argument
|
||||
specifies the language preferences when using the `->name` method on the model
|
||||
classes that this client creates. The fourth argument is additional options
|
||||
such as `host` and `timeout`.
|
||||
|
||||
For instance, to call the GeoLite2 web service instead of GeoIP2 Precision:
|
||||
|
||||
```php
|
||||
$client = new Client(42, 'abcdef123456', ['en'], ['host' => 'geolite.info']);
|
||||
```
|
||||
|
||||
After creating the client, you may now call the method corresponding to a
|
||||
specific endpoint with the IP address to look up, e.g.:
|
||||
|
||||
```php
|
||||
$record = $client->city('128.101.101.101');
|
||||
```
|
||||
|
||||
If the request succeeds, the method call will return a model class for the
|
||||
endpoint you called. This model in turn contains multiple record classes, each
|
||||
of which represents part of the data returned by the web service.
|
||||
|
||||
If there is an error, a structured exception is thrown.
|
||||
|
||||
See the API documentation for more details.
|
||||
|
||||
### Example ###
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
use GeoIp2\WebService\Client;
|
||||
|
||||
// This creates a Client object that can be reused across requests.
|
||||
// Replace "42" with your account ID and "license_key" with your license
|
||||
// key. Set the "host" to "geolite.info" in the fourth argument options
|
||||
// array to use the GeoLite2 web service instead of GeoIP2 Precision.
|
||||
$client = new Client(42, 'abcdef123456');
|
||||
|
||||
// Replace "city" with the method corresponding to the web service that
|
||||
// you are using, e.g., "country", "insights".
|
||||
$record = $client->city('128.101.101.101');
|
||||
|
||||
print($record->country->isoCode . "\n"); // 'US'
|
||||
print($record->country->name . "\n"); // 'United States'
|
||||
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
||||
|
||||
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
||||
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
||||
|
||||
print($record->city->name . "\n"); // 'Minneapolis'
|
||||
|
||||
print($record->postal->code . "\n"); // '55455'
|
||||
|
||||
print($record->location->latitude . "\n"); // 44.9733
|
||||
print($record->location->longitude . "\n"); // -93.2323
|
||||
|
||||
print($record->traits->network . "\n"); // '128.101.101.101/32'
|
||||
|
||||
```
|
||||
|
||||
## Values to use for Database or Array Keys ##
|
||||
|
||||
**We strongly discourage you from using a value from any `names` property as
|
||||
a key in a database or array.**
|
||||
|
||||
These names may change between releases. Instead we recommend using one of the
|
||||
following:
|
||||
|
||||
* `GeoIp2\Record\City` - `$city->geonameId`
|
||||
* `GeoIp2\Record\Continent` - `$continent->code` or `$continent->geonameId`
|
||||
* `GeoIp2\Record\Country` and `GeoIp2\Record\RepresentedCountry` -
|
||||
`$country->isoCode` or `$country->geonameId`
|
||||
* `GeoIp2\Record\Subdivision` - `$subdivision->isoCode` or `$subdivision->geonameId`
|
||||
|
||||
### What data is returned? ###
|
||||
|
||||
While many of the end points return the same basic records, the attributes
|
||||
which can be populated vary between end points. In addition, while an end
|
||||
point may offer a particular piece of data, MaxMind does not always have every
|
||||
piece of data for any given IP address.
|
||||
|
||||
Because of these factors, it is possible for any end point to return a record
|
||||
where some or all of the attributes are unpopulated.
|
||||
|
||||
See the
|
||||
[GeoIP2 Precision web service docs](https://dev.maxmind.com/geoip/docs/web-services?lang=en)
|
||||
for details on what data each end point may return.
|
||||
|
||||
The only piece of data which is always returned is the `ipAddress`
|
||||
attribute in the `GeoIp2\Record\Traits` record.
|
||||
|
||||
## Integration with GeoNames ##
|
||||
|
||||
[GeoNames](https://www.geonames.org/) offers web services and downloadable
|
||||
databases with data on geographical features around the world, including
|
||||
populated places. They offer both free and paid premium data. Each
|
||||
feature is unique identified by a `geonameId`, which is an integer.
|
||||
|
||||
Many of the records returned by the GeoIP2 web services and databases
|
||||
include a `geonameId` property. This is the ID of a geographical feature
|
||||
(city, region, country, etc.) in the GeoNames database.
|
||||
|
||||
Some of the data that MaxMind provides is also sourced from GeoNames. We
|
||||
source things like place names, ISO codes, and other similar data from
|
||||
the GeoNames premium data set.
|
||||
|
||||
## Reporting data problems ##
|
||||
|
||||
If the problem you find is that an IP address is incorrectly mapped,
|
||||
please
|
||||
[submit your correction to MaxMind](https://www.maxmind.com/en/correction).
|
||||
|
||||
If you find some other sort of mistake, like an incorrect spelling,
|
||||
please check the [GeoNames site](https://www.geonames.org/) first. Once
|
||||
you've searched for a place and found it on the GeoNames map view, there
|
||||
are a number of links you can use to correct data ("move", "edit",
|
||||
"alternate names", etc.). Once the correction is part of the GeoNames
|
||||
data set, it will be automatically incorporated into future MaxMind
|
||||
releases.
|
||||
|
||||
If you are a paying MaxMind customer and you're not sure where to submit
|
||||
a correction, please
|
||||
[contact MaxMind support](https://www.maxmind.com/en/support) for help.
|
||||
|
||||
## Other Support ##
|
||||
|
||||
Please report all issues with this code using the
|
||||
[GitHub issue tracker](https://github.com/maxmind/GeoIP2-php/issues).
|
||||
|
||||
If you are having an issue with a MaxMind service that is not specific
|
||||
to the client API, please see
|
||||
[our support page](https://www.maxmind.com/en/support).
|
||||
|
||||
## Requirements ##
|
||||
|
||||
This library requires PHP 7.2 or greater.
|
||||
|
||||
This library also relies on the [MaxMind DB Reader](https://github.com/maxmind/MaxMind-DB-Reader-php).
|
||||
|
||||
## Contributing ##
|
||||
|
||||
Patches and pull requests are encouraged. All code should follow the PSR-2
|
||||
style guidelines. Please include unit tests whenever possible. You may obtain
|
||||
the test data for the maxmind-db folder by running `git submodule update
|
||||
--init --recursive` or adding `--recursive` to your initial clone, or from
|
||||
https://github.com/maxmind/MaxMind-DB
|
||||
|
||||
## Versioning ##
|
||||
|
||||
The GeoIP2 PHP API uses [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## Copyright and License ##
|
||||
|
||||
This software is Copyright (c) 2013-2020 by MaxMind, Inc.
|
||||
|
||||
This is free software, licensed under the Apache License, Version 2.0.
|
292
includes/vendor/geoip2/geoip2/src/Database/Reader.php
vendored
Normal file
292
includes/vendor/geoip2/geoip2/src/Database/Reader.php
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Database;
|
||||
|
||||
use GeoIp2\Exception\AddressNotFoundException;
|
||||
use GeoIp2\Model\AbstractModel;
|
||||
use GeoIp2\ProviderInterface;
|
||||
use MaxMind\Db\Reader as DbReader;
|
||||
use MaxMind\Db\Reader\InvalidDatabaseException;
|
||||
|
||||
/**
|
||||
* Instances of this class provide a reader for the GeoIP2 database format.
|
||||
* IP addresses can be looked up using the database specific methods.
|
||||
*
|
||||
* ## Usage ##
|
||||
*
|
||||
* The basic API for this class is the same for every database. First, you
|
||||
* create a reader object, specifying a file name. You then call the method
|
||||
* corresponding to the specific database, passing it the IP address you want
|
||||
* to look up.
|
||||
*
|
||||
* If the request succeeds, the method call will return a model class for
|
||||
* the method you called. This model in turn contains multiple record classes,
|
||||
* each of which represents part of the data returned by the database. If
|
||||
* the database does not contain the requested information, the attributes
|
||||
* on the record class will have a `null` value.
|
||||
*
|
||||
* If the address is not in the database, an
|
||||
* {@link \GeoIp2\Exception\AddressNotFoundException} exception will be
|
||||
* thrown. If an invalid IP address is passed to one of the methods, a
|
||||
* SPL {@link \InvalidArgumentException} will be thrown. If the database is
|
||||
* corrupt or invalid, a {@link \MaxMind\Db\Reader\InvalidDatabaseException}
|
||||
* will be thrown.
|
||||
*/
|
||||
class Reader implements ProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var DbReader
|
||||
*/
|
||||
private $dbReader;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dbType;
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
private $locales;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $filename the path to the GeoIP2 database file
|
||||
* @param array $locales list of locale codes to use in name property
|
||||
* from most preferred to least preferred
|
||||
*
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function __construct(
|
||||
string $filename,
|
||||
array $locales = ['en']
|
||||
) {
|
||||
$this->dbReader = new DbReader($filename);
|
||||
$this->dbType = $this->dbReader->metadata()->databaseType;
|
||||
$this->locales = $locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoIP2 City model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function city(string $ipAddress): \GeoIp2\Model\City
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->modelFor('City', 'City', $ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoIP2 Country model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function country(string $ipAddress): \GeoIp2\Model\Country
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->modelFor('Country', 'Country', $ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoIP2 Anonymous IP model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function anonymousIp(string $ipAddress): \GeoIp2\Model\AnonymousIp
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->flatModelFor(
|
||||
'AnonymousIp',
|
||||
'GeoIP2-Anonymous-IP',
|
||||
$ipAddress
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoLite2 ASN model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function asn(string $ipAddress): \GeoIp2\Model\Asn
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->flatModelFor(
|
||||
'Asn',
|
||||
'GeoLite2-ASN',
|
||||
$ipAddress
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoIP2 Connection Type model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function connectionType(string $ipAddress): \GeoIp2\Model\ConnectionType
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->flatModelFor(
|
||||
'ConnectionType',
|
||||
'GeoIP2-Connection-Type',
|
||||
$ipAddress
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoIP2 Domain model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function domain(string $ipAddress): \GeoIp2\Model\Domain
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->flatModelFor(
|
||||
'Domain',
|
||||
'GeoIP2-Domain',
|
||||
$ipAddress
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoIP2 Enterprise model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function enterprise(string $ipAddress): \GeoIp2\Model\Enterprise
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->modelFor('Enterprise', 'Enterprise', $ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a GeoIP2 ISP model.
|
||||
*
|
||||
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
||||
* not in the database
|
||||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
||||
* is corrupt or invalid
|
||||
*/
|
||||
public function isp(string $ipAddress): \GeoIp2\Model\Isp
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->flatModelFor(
|
||||
'Isp',
|
||||
'GeoIP2-ISP',
|
||||
$ipAddress
|
||||
);
|
||||
}
|
||||
|
||||
private function modelFor(string $class, string $type, string $ipAddress): AbstractModel
|
||||
{
|
||||
[$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress);
|
||||
|
||||
$record['traits']['ip_address'] = $ipAddress;
|
||||
$record['traits']['prefix_len'] = $prefixLen;
|
||||
|
||||
$class = 'GeoIp2\\Model\\' . $class;
|
||||
|
||||
return new $class($record, $this->locales);
|
||||
}
|
||||
|
||||
private function flatModelFor(string $class, string $type, string $ipAddress): AbstractModel
|
||||
{
|
||||
[$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress);
|
||||
|
||||
$record['ip_address'] = $ipAddress;
|
||||
$record['prefix_len'] = $prefixLen;
|
||||
$class = 'GeoIp2\\Model\\' . $class;
|
||||
|
||||
return new $class($record);
|
||||
}
|
||||
|
||||
private function getRecord(string $class, string $type, string $ipAddress): array
|
||||
{
|
||||
if (strpos($this->dbType, $type) === false) {
|
||||
$method = lcfirst($class);
|
||||
|
||||
throw new \BadMethodCallException(
|
||||
"The $method method cannot be used to open a {$this->dbType} database"
|
||||
);
|
||||
}
|
||||
[$record, $prefixLen] = $this->dbReader->getWithPrefixLen($ipAddress);
|
||||
if ($record === null) {
|
||||
throw new AddressNotFoundException(
|
||||
"The address $ipAddress is not in the database."
|
||||
);
|
||||
}
|
||||
if (!\is_array($record)) {
|
||||
// This can happen on corrupt databases. Generally,
|
||||
// MaxMind\Db\Reader will throw a
|
||||
// MaxMind\Db\Reader\InvalidDatabaseException, but occasionally
|
||||
// the lookup may result in a record that looks valid but is not
|
||||
// an array. This mostly happens when the user is ignoring all
|
||||
// exceptions and the more frequent InvalidDatabaseException
|
||||
// exceptions go unnoticed.
|
||||
throw new InvalidDatabaseException(
|
||||
"Expected an array when looking up $ipAddress but received: "
|
||||
. \gettype($record)
|
||||
);
|
||||
}
|
||||
|
||||
return [$record, $prefixLen];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException if arguments are passed to the method
|
||||
* @throws \BadMethodCallException if the database has been closed
|
||||
*
|
||||
* @return \MaxMind\Db\Reader\Metadata object for the database
|
||||
*/
|
||||
public function metadata(): DbReader\Metadata
|
||||
{
|
||||
return $this->dbReader->metadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the GeoIP2 database and returns the resources to the system.
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
$this->dbReader->close();
|
||||
}
|
||||
}
|
12
includes/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php
vendored
Normal file
12
includes/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Exception;
|
||||
|
||||
/**
|
||||
* This class represents a generic error.
|
||||
*/
|
||||
class AddressNotFoundException extends GeoIp2Exception
|
||||
{
|
||||
}
|
12
includes/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php
vendored
Normal file
12
includes/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Exception;
|
||||
|
||||
/**
|
||||
* This class represents a generic error.
|
||||
*/
|
||||
class AuthenticationException extends GeoIp2Exception
|
||||
{
|
||||
}
|
12
includes/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php
vendored
Normal file
12
includes/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Exception;
|
||||
|
||||
/**
|
||||
* This class represents a generic error.
|
||||
*/
|
||||
class GeoIp2Exception extends \Exception
|
||||
{
|
||||
}
|
28
includes/vendor/geoip2/geoip2/src/Exception/HttpException.php
vendored
Normal file
28
includes/vendor/geoip2/geoip2/src/Exception/HttpException.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Exception;
|
||||
|
||||
/**
|
||||
* This class represents an HTTP transport error.
|
||||
*/
|
||||
class HttpException extends GeoIp2Exception
|
||||
{
|
||||
/**
|
||||
* The URI queried.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $uri;
|
||||
|
||||
public function __construct(
|
||||
string $message,
|
||||
int $httpStatus,
|
||||
string $uri,
|
||||
\Exception $previous = null
|
||||
) {
|
||||
$this->uri = $uri;
|
||||
parent::__construct($message, $httpStatus, $previous);
|
||||
}
|
||||
}
|
30
includes/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php
vendored
Normal file
30
includes/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Exception;
|
||||
|
||||
/**
|
||||
* This class represents an error returned by MaxMind's GeoIP2
|
||||
* web service.
|
||||
*/
|
||||
class InvalidRequestException extends HttpException
|
||||
{
|
||||
/**
|
||||
* The code returned by the MaxMind web service.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $error;
|
||||
|
||||
public function __construct(
|
||||
string $message,
|
||||
string $error,
|
||||
int $httpStatus,
|
||||
string $uri,
|
||||
\Exception $previous = null
|
||||
) {
|
||||
$this->error = $error;
|
||||
parent::__construct($message, $httpStatus, $uri, $previous);
|
||||
}
|
||||
}
|
12
includes/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php
vendored
Normal file
12
includes/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Exception;
|
||||
|
||||
/**
|
||||
* This class represents a generic error.
|
||||
*/
|
||||
class OutOfQueriesException extends GeoIp2Exception
|
||||
{
|
||||
}
|
68
includes/vendor/geoip2/geoip2/src/Model/AbstractModel.php
vendored
Normal file
68
includes/vendor/geoip2/geoip2/src/Model/AbstractModel.php
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
abstract class AbstractModel implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected $raw;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw)
|
||||
{
|
||||
$this->raw = $raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function get(string $field)
|
||||
{
|
||||
if (isset($this->raw[$field])) {
|
||||
return $this->raw[$field];
|
||||
}
|
||||
if (preg_match('/^is_/', $field)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $attr)
|
||||
{
|
||||
if ($attr !== 'instance' && property_exists($this, $attr)) {
|
||||
return $this->{$attr};
|
||||
}
|
||||
|
||||
throw new \RuntimeException("Unknown attribute: $attr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __isset(string $attr): bool
|
||||
{
|
||||
return $attr !== 'instance' && isset($this->{$attr});
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->raw;
|
||||
}
|
||||
}
|
84
includes/vendor/geoip2/geoip2/src/Model/AnonymousIp.php
vendored
Normal file
84
includes/vendor/geoip2/geoip2/src/Model/AnonymousIp.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 Anonymous IP model.
|
||||
*
|
||||
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
||||
* any sort of anonymous network.
|
||||
* @property-read bool $isAnonymousVpn This is true if the IP address is
|
||||
* registered to an anonymous VPN provider. If a VPN provider does not
|
||||
* register subnets under names associated with them, we will likely only
|
||||
* flag their IP ranges using the isHostingProvider property.
|
||||
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
||||
* to a hosting or VPN provider (see description of isAnonymousVpn property).
|
||||
* @property-read bool $isPublicProxy This is true if the IP address belongs to
|
||||
* a public proxy.
|
||||
* @property-read bool $isResidentialProxy This is true if the IP address is
|
||||
* on a suspected anonymizing network and belongs to a residential ISP.
|
||||
* @property-read bool $isTorExitNode This is true if the IP address is a Tor
|
||||
* exit node.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class AnonymousIp extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isAnonymous;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isAnonymousVpn;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isHostingProvider;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isPublicProxy;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isResidentialProxy;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isTorExitNode;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $ipAddress;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw)
|
||||
{
|
||||
parent::__construct($raw);
|
||||
|
||||
$this->isAnonymous = $this->get('is_anonymous');
|
||||
$this->isAnonymousVpn = $this->get('is_anonymous_vpn');
|
||||
$this->isHostingProvider = $this->get('is_hosting_provider');
|
||||
$this->isPublicProxy = $this->get('is_public_proxy');
|
||||
$this->isResidentialProxy = $this->get('is_residential_proxy');
|
||||
$this->isTorExitNode = $this->get('is_tor_exit_node');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
55
includes/vendor/geoip2/geoip2/src/Model/Asn.php
vendored
Normal file
55
includes/vendor/geoip2/geoip2/src/Model/Asn.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoLite2 ASN model.
|
||||
*
|
||||
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
||||
* associated with the IP address.
|
||||
* @property-read string|null $autonomousSystemOrganization The organization
|
||||
* associated with the registered autonomous system number for the IP
|
||||
* address.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class Asn extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
protected $autonomousSystemNumber;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $autonomousSystemOrganization;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $ipAddress;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw)
|
||||
{
|
||||
parent::__construct($raw);
|
||||
$this->autonomousSystemNumber = $this->get('autonomous_system_number');
|
||||
$this->autonomousSystemOrganization =
|
||||
$this->get('autonomous_system_organization');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
120
includes/vendor/geoip2/geoip2/src/Model/City.php
vendored
Normal file
120
includes/vendor/geoip2/geoip2/src/Model/City.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
/**
|
||||
* Model class for the data returned by GeoIP2 City web service and database.
|
||||
*
|
||||
* The only difference between the City and Insights model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* https://dev.maxmind.com/geoip/docs/web-services?lang=en for more details.
|
||||
*
|
||||
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
||||
* address.
|
||||
* @property-read \GeoIp2\Record\Location $location Location data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\Postal $postal Postal data for the
|
||||
* requested IP address.
|
||||
* @property-read array $subdivisions An array \GeoIp2\Record\Subdivision
|
||||
* objects representing the country subdivisions for the requested IP
|
||||
* address. The number and type of subdivisions varies by country, but a
|
||||
* subdivision is typically a state, province, county, etc. Subdivisions
|
||||
* are ordered from most general (largest) to most specific (smallest).
|
||||
* If the response did not contain any subdivisions, this method returns
|
||||
* an empty array.
|
||||
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
||||
* representing the most specific subdivision returned. If the response
|
||||
* did not contain any subdivisions, this method returns an empty
|
||||
* \GeoIp2\Record\Subdivision object.
|
||||
*/
|
||||
class City extends Country
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var \GeoIp2\Record\City
|
||||
*/
|
||||
protected $city;
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var \GeoIp2\Record\Location
|
||||
*/
|
||||
protected $location;
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var \GeoIp2\Record\Postal
|
||||
*/
|
||||
protected $postal;
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<\GeoIp2\Record\Subdivision>
|
||||
*/
|
||||
protected $subdivisions = [];
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw, array $locales = ['en'])
|
||||
{
|
||||
parent::__construct($raw, $locales);
|
||||
|
||||
$this->city = new \GeoIp2\Record\City($this->get('city'), $locales);
|
||||
$this->location = new \GeoIp2\Record\Location($this->get('location'));
|
||||
$this->postal = new \GeoIp2\Record\Postal($this->get('postal'));
|
||||
|
||||
$this->createSubdivisions($raw, $locales);
|
||||
}
|
||||
|
||||
private function createSubdivisions(array $raw, array $locales): void
|
||||
{
|
||||
if (!isset($raw['subdivisions'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($raw['subdivisions'] as $sub) {
|
||||
$this->subdivisions[] =
|
||||
new \GeoIp2\Record\Subdivision($sub, $locales)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $attr)
|
||||
{
|
||||
if ($attr === 'mostSpecificSubdivision') {
|
||||
return $this->{$attr}();
|
||||
}
|
||||
|
||||
return parent::__get($attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __isset(string $attr): bool
|
||||
{
|
||||
if ($attr === 'mostSpecificSubdivision') {
|
||||
// We always return a mostSpecificSubdivision, even if it is the
|
||||
// empty subdivision
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::__isset($attr);
|
||||
}
|
||||
|
||||
private function mostSpecificSubdivision(): \GeoIp2\Record\Subdivision
|
||||
{
|
||||
return empty($this->subdivisions) ?
|
||||
new \GeoIp2\Record\Subdivision([], $this->locales) :
|
||||
end($this->subdivisions);
|
||||
}
|
||||
}
|
48
includes/vendor/geoip2/geoip2/src/Model/ConnectionType.php
vendored
Normal file
48
includes/vendor/geoip2/geoip2/src/Model/ConnectionType.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 Connection-Type model.
|
||||
*
|
||||
* @property-read string|null $connectionType The connection type may take the
|
||||
* following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
|
||||
* Additional values may be added in the future.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class ConnectionType extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $connectionType;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $ipAddress;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw)
|
||||
{
|
||||
parent::__construct($raw);
|
||||
|
||||
$this->connectionType = $this->get('connection_type');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
92
includes/vendor/geoip2/geoip2/src/Model/Country.php
vendored
Normal file
92
includes/vendor/geoip2/geoip2/src/Model/Country.php
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
/**
|
||||
* Model class for the data returned by GeoIP2 Country web service and database.
|
||||
*
|
||||
* The only difference between the City and Insights model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* https://dev.maxmind.com/geoip/docs/web-services?lang=en for more details.
|
||||
*
|
||||
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
||||
* requested IP address.
|
||||
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
||||
* IP address. This object represents the country where MaxMind believes the
|
||||
* end user is located.
|
||||
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
||||
* account.
|
||||
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
||||
* data for the requested IP address. This record represents the country
|
||||
* where the ISP has registered a given IP block and may differ from the
|
||||
* user's country.
|
||||
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
||||
* Represented country data for the requested IP address. The represented
|
||||
* country is used for things like military bases. It is only present when
|
||||
* the represented country differs from the country.
|
||||
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
||||
* requested IP address.
|
||||
* @property-read array $raw The raw data from the web service.
|
||||
*/
|
||||
class Country extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @var \GeoIp2\Record\Continent
|
||||
*/
|
||||
protected $continent;
|
||||
/**
|
||||
* @var \GeoIp2\Record\Country
|
||||
*/
|
||||
protected $country;
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $locales;
|
||||
/**
|
||||
* @var \GeoIp2\Record\MaxMind
|
||||
*/
|
||||
protected $maxmind;
|
||||
/**
|
||||
* @var \GeoIp2\Record\Country
|
||||
*/
|
||||
protected $registeredCountry;
|
||||
/**
|
||||
* @var \GeoIp2\Record\RepresentedCountry
|
||||
*/
|
||||
protected $representedCountry;
|
||||
/**
|
||||
* @var \GeoIp2\Record\Traits
|
||||
*/
|
||||
protected $traits;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw, array $locales = ['en'])
|
||||
{
|
||||
parent::__construct($raw);
|
||||
|
||||
$this->continent = new \GeoIp2\Record\Continent(
|
||||
$this->get('continent'),
|
||||
$locales
|
||||
);
|
||||
$this->country = new \GeoIp2\Record\Country(
|
||||
$this->get('country'),
|
||||
$locales
|
||||
);
|
||||
$this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind'));
|
||||
$this->registeredCountry = new \GeoIp2\Record\Country(
|
||||
$this->get('registered_country'),
|
||||
$locales
|
||||
);
|
||||
$this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
|
||||
$this->get('represented_country'),
|
||||
$locales
|
||||
);
|
||||
$this->traits = new \GeoIp2\Record\Traits($this->get('traits'));
|
||||
|
||||
$this->locales = $locales;
|
||||
}
|
||||
}
|
48
includes/vendor/geoip2/geoip2/src/Model/Domain.php
vendored
Normal file
48
includes/vendor/geoip2/geoip2/src/Model/Domain.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 Domain model.
|
||||
*
|
||||
* @property-read string|null $domain The second level domain associated with the
|
||||
* IP address. This will be something like "example.com" or
|
||||
* "example.co.uk", not "foo.example.com".
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class Domain extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $domain;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $ipAddress;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw)
|
||||
{
|
||||
parent::__construct($raw);
|
||||
|
||||
$this->domain = $this->get('domain');
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
16
includes/vendor/geoip2/geoip2/src/Model/Enterprise.php
vendored
Normal file
16
includes/vendor/geoip2/geoip2/src/Model/Enterprise.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
/**
|
||||
* Model class for the data returned by GeoIP2 Enterprise database lookups.
|
||||
*
|
||||
* The only difference between the City and Enterprise model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* https://dev.maxmind.com/geoip/docs/web-services?lang=en for more details.
|
||||
*/
|
||||
class Enterprise extends City
|
||||
{
|
||||
}
|
16
includes/vendor/geoip2/geoip2/src/Model/Insights.php
vendored
Normal file
16
includes/vendor/geoip2/geoip2/src/Model/Insights.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
/**
|
||||
* Model class for the data returned by GeoIP2 Precision: Insights web service.
|
||||
*
|
||||
* The only difference between the City and Insights model classes is which
|
||||
* fields in each record may be populated. See
|
||||
* https://dev.maxmind.com/geoip/docs/web-services?lang=en for more details.
|
||||
*/
|
||||
class Insights extends City
|
||||
{
|
||||
}
|
86
includes/vendor/geoip2/geoip2/src/Model/Isp.php
vendored
Normal file
86
includes/vendor/geoip2/geoip2/src/Model/Isp.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Model;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* This class provides the GeoIP2 ISP model.
|
||||
*
|
||||
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
||||
* associated with the IP address.
|
||||
* @property-read string|null $autonomousSystemOrganization The organization
|
||||
* associated with the registered autonomous system number for the IP
|
||||
* address.
|
||||
* @property-read string|null $isp The name of the ISP associated with the IP
|
||||
* address.
|
||||
* @property-read string|null $mobileCountryCode The [mobile country code
|
||||
* (MCC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with
|
||||
* the IP address and ISP.
|
||||
* @property-read string|null $mobileNetworkCode The [mobile network code
|
||||
* (MNC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with
|
||||
* the IP address and ISP.
|
||||
* @property-read string|null $organization The name of the organization associated
|
||||
* with the IP address.
|
||||
* @property-read string $ipAddress The IP address that the data in the model is
|
||||
* for.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
*/
|
||||
class Isp extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
protected $autonomousSystemNumber;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $autonomousSystemOrganization;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $isp;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $mobileCountryCode;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $mobileNetworkCode;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $organization;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $ipAddress;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $network;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(array $raw)
|
||||
{
|
||||
parent::__construct($raw);
|
||||
$this->autonomousSystemNumber = $this->get('autonomous_system_number');
|
||||
$this->autonomousSystemOrganization =
|
||||
$this->get('autonomous_system_organization');
|
||||
$this->isp = $this->get('isp');
|
||||
$this->mobileCountryCode = $this->get('mobile_country_code');
|
||||
$this->mobileNetworkCode = $this->get('mobile_network_code');
|
||||
$this->organization = $this->get('organization');
|
||||
|
||||
$ipAddress = $this->get('ip_address');
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
|
||||
}
|
||||
}
|
22
includes/vendor/geoip2/geoip2/src/ProviderInterface.php
vendored
Normal file
22
includes/vendor/geoip2/geoip2/src/ProviderInterface.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2;
|
||||
|
||||
interface ProviderInterface
|
||||
{
|
||||
/**
|
||||
* @param string $ipAddress an IPv4 or IPv6 address to lookup
|
||||
*
|
||||
* @return \GeoIp2\Model\Country a Country model for the requested IP address
|
||||
*/
|
||||
public function country(string $ipAddress): Model\Country;
|
||||
|
||||
/**
|
||||
* @param string $ipAddress an IPv4 or IPv6 address to lookup
|
||||
*
|
||||
* @return \GeoIp2\Model\City a City model for the requested IP address
|
||||
*/
|
||||
public function city(string $ipAddress): Model\City;
|
||||
}
|
68
includes/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php
vendored
Normal file
68
includes/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
abstract class AbstractPlaceRecord extends AbstractRecord
|
||||
{
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
private $locales;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(?array $record, array $locales = ['en'])
|
||||
{
|
||||
$this->locales = $locales;
|
||||
parent::__construct($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $attr)
|
||||
{
|
||||
if ($attr === 'name') {
|
||||
return $this->name();
|
||||
}
|
||||
|
||||
return parent::__get($attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __isset(string $attr): bool
|
||||
{
|
||||
if ($attr === 'name') {
|
||||
return $this->firstSetNameLocale() !== null;
|
||||
}
|
||||
|
||||
return parent::__isset($attr);
|
||||
}
|
||||
|
||||
private function name(): ?string
|
||||
{
|
||||
$locale = $this->firstSetNameLocale();
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
return $locale === null ? null : $this->names[$locale];
|
||||
}
|
||||
|
||||
private function firstSetNameLocale(): ?string
|
||||
{
|
||||
foreach ($this->locales as $locale) {
|
||||
// @phpstan-ignore-next-line
|
||||
if (isset($this->names[$locale])) {
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
67
includes/vendor/geoip2/geoip2/src/Record/AbstractRecord.php
vendored
Normal file
67
includes/vendor/geoip2/geoip2/src/Record/AbstractRecord.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
abstract class AbstractRecord implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
private $record;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public function __construct(?array $record)
|
||||
{
|
||||
$this->record = isset($record) ? $record : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get(string $attr)
|
||||
{
|
||||
// XXX - kind of ugly but greatly reduces boilerplate code
|
||||
$key = $this->attributeToKey($attr);
|
||||
|
||||
if ($this->__isset($attr)) {
|
||||
return $this->record[$key];
|
||||
}
|
||||
if ($this->validAttribute($attr)) {
|
||||
if (preg_match('/^is_/', $key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new \RuntimeException("Unknown attribute: $attr");
|
||||
}
|
||||
|
||||
public function __isset(string $attr): bool
|
||||
{
|
||||
return $this->validAttribute($attr)
|
||||
&& isset($this->record[$this->attributeToKey($attr)]);
|
||||
}
|
||||
|
||||
private function attributeToKey(string $attr): string
|
||||
{
|
||||
return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));
|
||||
}
|
||||
|
||||
private function validAttribute(string $attr): bool
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return \in_array($attr, $this->validAttributes, true);
|
||||
}
|
||||
|
||||
public function jsonSerialize(): ?array
|
||||
{
|
||||
return $this->record;
|
||||
}
|
||||
}
|
33
includes/vendor/geoip2/geoip2/src/Record/City.php
vendored
Normal file
33
includes/vendor/geoip2/geoip2/src/Record/City.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* City-level data associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location services and databases besides
|
||||
* Country.
|
||||
*
|
||||
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
||||
* confidence that the city is correct. This attribute is only available
|
||||
* from the Insights service and the GeoIP2 Enterprise database.
|
||||
* @property-read int|null $geonameId The GeoName ID for the city. This attribute
|
||||
* is returned by all location services and databases.
|
||||
* @property-read string|null $name The name of the city based on the locales list
|
||||
* passed to the constructor. This attribute is returned by all location
|
||||
* services and databases.
|
||||
* @property-read array|null $names A array map where the keys are locale codes
|
||||
* and the values are names. This attribute is returned by all location
|
||||
* services and databases.
|
||||
*/
|
||||
class City extends AbstractPlaceRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = ['confidence', 'geonameId', 'names'];
|
||||
}
|
36
includes/vendor/geoip2/geoip2/src/Record/Continent.php
vendored
Normal file
36
includes/vendor/geoip2/geoip2/src/Record/Continent.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* Contains data for the continent record associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location services and databases.
|
||||
*
|
||||
* @property-read string|null $code A two character continent code like "NA" (North
|
||||
* America) or "OC" (Oceania). This attribute is returned by all location
|
||||
* services and databases.
|
||||
* @property-read int|null $geonameId The GeoName ID for the continent. This
|
||||
* attribute is returned by all location services and databases.
|
||||
* @property-read string|null $name Returns the name of the continent based on the
|
||||
* locales list passed to the constructor. This attribute is returned by all location
|
||||
* services and databases.
|
||||
* @property-read array|null $names An array map where the keys are locale codes
|
||||
* and the values are names. This attribute is returned by all location
|
||||
* services and databases.
|
||||
*/
|
||||
class Continent extends AbstractPlaceRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = [
|
||||
'code',
|
||||
'geonameId',
|
||||
'names',
|
||||
];
|
||||
}
|
44
includes/vendor/geoip2/geoip2/src/Record/Country.php
vendored
Normal file
44
includes/vendor/geoip2/geoip2/src/Record/Country.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* Contains data for the country record associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location services and databases.
|
||||
*
|
||||
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
||||
* confidence that the country is correct. This attribute is only available
|
||||
* from the Insights service and the GeoIP2 Enterprise database.
|
||||
* @property-read int|null $geonameId The GeoName ID for the country. This
|
||||
* attribute is returned by all location services and databases.
|
||||
* @property-read bool $isInEuropeanUnion This is true if the country is a
|
||||
* member state of the European Union. This attribute is returned by all
|
||||
* location services and databases.
|
||||
* @property-read string|null $isoCode The two-character ISO 3166-1 alpha code
|
||||
* for the country. See https://en.wikipedia.org/wiki/ISO_3166-1. This
|
||||
* attribute is returned by all location services and databases.
|
||||
* @property-read string|null $name The name of the country based on the locales
|
||||
* list passed to the constructor. This attribute is returned by all location
|
||||
* services and databases.
|
||||
* @property-read array|null $names An array map where the keys are locale codes
|
||||
* and the values are names. This attribute is returned by all location
|
||||
* services and databases.
|
||||
*/
|
||||
class Country extends AbstractPlaceRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = [
|
||||
'confidence',
|
||||
'geonameId',
|
||||
'isInEuropeanUnion',
|
||||
'isoCode',
|
||||
'names',
|
||||
];
|
||||
}
|
56
includes/vendor/geoip2/geoip2/src/Record/Location.php
vendored
Normal file
56
includes/vendor/geoip2/geoip2/src/Record/Location.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* Contains data for the location record associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location services and databases besides
|
||||
* Country.
|
||||
*
|
||||
* @property-read int|null $averageIncome The average income in US dollars
|
||||
* associated with the requested IP address. This attribute is only available
|
||||
* from the Insights service.
|
||||
* @property-read int|null $accuracyRadius The approximate accuracy radius in
|
||||
* kilometers around the latitude and longitude for the IP address. This is
|
||||
* the radius where we have a 67% confidence that the device using the IP
|
||||
* address resides within the circle centered at the latitude and longitude
|
||||
* with the provided radius.
|
||||
* @property-read float|null $latitude The approximate latitude of the location
|
||||
* associated with the IP address. This value is not precise and should not be
|
||||
* used to identify a particular address or household.
|
||||
* @property-read float|null $longitude The approximate longitude of the location
|
||||
* associated with the IP address. This value is not precise and should not be
|
||||
* used to identify a particular address or household.
|
||||
* @property-read int|null $populationDensity The estimated population per square
|
||||
* kilometer associated with the IP address. This attribute is only available
|
||||
* from the Insights service.
|
||||
* @property-read int|null $metroCode The metro code of the location if the location
|
||||
* is in the US. MaxMind returns the same metro codes as the
|
||||
* Google AdWords API. See
|
||||
* https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions.
|
||||
* @property-read string|null $timeZone The time zone associated with location, as
|
||||
* specified by the IANA Time Zone Database, e.g., "America/New_York". See
|
||||
* https://www.iana.org/time-zones.
|
||||
*/
|
||||
class Location extends AbstractRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = [
|
||||
'averageIncome',
|
||||
'accuracyRadius',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'metroCode',
|
||||
'populationDensity',
|
||||
'postalCode',
|
||||
'postalConfidence',
|
||||
'timeZone',
|
||||
];
|
||||
}
|
23
includes/vendor/geoip2/geoip2/src/Record/MaxMind.php
vendored
Normal file
23
includes/vendor/geoip2/geoip2/src/Record/MaxMind.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* Contains data about your account.
|
||||
*
|
||||
* This record is returned by all location services and databases.
|
||||
*
|
||||
* @property-read int|null $queriesRemaining The number of remaining queries you
|
||||
* have for the service you are calling.
|
||||
*/
|
||||
class MaxMind extends AbstractRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = ['queriesRemaining'];
|
||||
}
|
30
includes/vendor/geoip2/geoip2/src/Record/Postal.php
vendored
Normal file
30
includes/vendor/geoip2/geoip2/src/Record/Postal.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* Contains data for the postal record associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location databases and services besides
|
||||
* Country.
|
||||
*
|
||||
* @property-read string|null $code The postal code of the location. Postal codes
|
||||
* are not available for all countries. In some countries, this will only
|
||||
* contain part of the postal code. This attribute is returned by all location
|
||||
* databases and services besides Country.
|
||||
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
||||
* confidence that the postal code is correct. This attribute is only
|
||||
* available from the Insights service and the GeoIP2 Enterprise
|
||||
* database.
|
||||
*/
|
||||
class Postal extends AbstractRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = ['code', 'confidence'];
|
||||
}
|
33
includes/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php
vendored
Normal file
33
includes/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* Contains data for the represented country associated with an IP address.
|
||||
*
|
||||
* This class contains the country-level data associated with an IP address
|
||||
* for the IP's represented country. The represented country is the country
|
||||
* represented by something like a military base.
|
||||
*
|
||||
* @property-read string|null $type A string indicating the type of entity that is
|
||||
* representing the country. Currently we only return <code>military</code>
|
||||
* but this could expand to include other types in the future.
|
||||
*/
|
||||
class RepresentedCountry extends Country
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = [
|
||||
'confidence',
|
||||
'geonameId',
|
||||
'isInEuropeanUnion',
|
||||
'isoCode',
|
||||
'names',
|
||||
'type',
|
||||
];
|
||||
}
|
44
includes/vendor/geoip2/geoip2/src/Record/Subdivision.php
vendored
Normal file
44
includes/vendor/geoip2/geoip2/src/Record/Subdivision.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
/**
|
||||
* Contains data for the subdivisions associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location databases and services besides
|
||||
* Country.
|
||||
*
|
||||
* @property-read int|null $confidence This is a value from 0-100 indicating
|
||||
* MaxMind's confidence that the subdivision is correct. This attribute is
|
||||
* only available from the Insights service and the GeoIP2 Enterprise
|
||||
* database.
|
||||
* @property-read int|null $geonameId This is a GeoName ID for the subdivision.
|
||||
* This attribute is returned by all location databases and services besides
|
||||
* Country.
|
||||
* @property-read string|null $isoCode This is a string up to three characters long
|
||||
* contain the subdivision portion of the ISO 3166-2 code. See
|
||||
* https://en.wikipedia.org/wiki/ISO_3166-2. This attribute is returned by all
|
||||
* location databases and services except Country.
|
||||
* @property-read string|null $name The name of the subdivision based on the
|
||||
* locales list passed to the constructor. This attribute is returned by all
|
||||
* location databases and services besides Country.
|
||||
* @property-read array|null $names An array map where the keys are locale codes
|
||||
* and the values are names. This attribute is returned by all location
|
||||
* databases and services besides Country.
|
||||
*/
|
||||
class Subdivision extends AbstractPlaceRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = [
|
||||
'confidence',
|
||||
'geonameId',
|
||||
'isoCode',
|
||||
'names',
|
||||
];
|
||||
}
|
158
includes/vendor/geoip2/geoip2/src/Record/Traits.php
vendored
Normal file
158
includes/vendor/geoip2/geoip2/src/Record/Traits.php
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\Record;
|
||||
|
||||
use GeoIp2\Util;
|
||||
|
||||
/**
|
||||
* Contains data for the traits record associated with an IP address.
|
||||
*
|
||||
* This record is returned by all location services and databases.
|
||||
*
|
||||
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
||||
* associated with the IP address. See
|
||||
* https://en.wikipedia.org/wiki/Autonomous_system_(Internet%29. This attribute
|
||||
* is only available from the City and Insights web service and the GeoIP2
|
||||
* Enterprise database.
|
||||
* @property-read string|null $autonomousSystemOrganization The organization
|
||||
* associated with the registered autonomous system number for the IP address.
|
||||
* See https://en.wikipedia.org/wiki/Autonomous_system_(Internet%29. This
|
||||
* attribute is only available from the City and Insights web service and the
|
||||
* GeoIP2 Enterprise database.
|
||||
* @property-read string|null $connectionType The connection type may take the
|
||||
* following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
|
||||
* Additional values may be added in the future. This attribute is only
|
||||
* available in the GeoIP2 Enterprise database.
|
||||
* @property-read string|null $domain The second level domain associated with the
|
||||
* IP address. This will be something like "example.com" or "example.co.uk",
|
||||
* not "foo.example.com". This attribute is only available from the
|
||||
* City and Insights web service and the GeoIP2 Enterprise
|
||||
* database.
|
||||
* @property-read string $ipAddress The IP address that the data in the model
|
||||
* is for. If you performed a "me" lookup against the web service, this
|
||||
* will be the externally routable IP address for the system the code is
|
||||
* running on. If the system is behind a NAT, this may differ from the IP
|
||||
* address locally assigned to it. This attribute is returned by all end
|
||||
* points.
|
||||
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
||||
* any sort of anonymous network. This property is only available from GeoIP2
|
||||
* Precision Insights.
|
||||
* @property-read bool $isAnonymousProxy *Deprecated.* Please see our GeoIP2
|
||||
* Anonymous IP database
|
||||
* (https://www.maxmind.com/en/geoip2-anonymous-ip-database) to determine
|
||||
* whether the IP address is used by an anonymizing service.
|
||||
* @property-read bool $isAnonymousVpn This is true if the IP address is
|
||||
* registered to an anonymous VPN provider. If a VPN provider does not register
|
||||
* subnets under names associated with them, we will likely only flag their IP
|
||||
* ranges using the isHostingProvider property. This property is only available
|
||||
* from GeoIP2 Precision Insights.
|
||||
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
||||
* to a hosting or VPN provider (see description of isAnonymousVpn property).
|
||||
* This property is only available from GeoIP2 Precision Insights.
|
||||
* @property-read bool $isLegitimateProxy This attribute is true if MaxMind
|
||||
* believes this IP address to be a legitimate proxy, such as an internal
|
||||
* VPN used by a corporation. This attribute is only available in the GeoIP2
|
||||
* Enterprise database.
|
||||
* @property-read bool $isPublicProxy This is true if the IP address belongs to
|
||||
* a public proxy. This property is only available from GeoIP2 Precision
|
||||
* Insights.
|
||||
* @property-read bool $isResidentialProxy This is true if the IP address is
|
||||
* on a suspected anonymizing network and belongs to a residential ISP. This
|
||||
* property is only available from GeoIP2 Precision Insights.
|
||||
* @property-read bool $isSatelliteProvider *Deprecated.* Due to the
|
||||
* increased coverage by mobile carriers, very few satellite providers now
|
||||
* serve multiple countries. As a result, the output does not provide
|
||||
* sufficiently relevant data for us to maintain it.
|
||||
* @property-read bool $isTorExitNode This is true if the IP address is a Tor
|
||||
* exit node. This property is only available from GeoIP2 Precision Insights.
|
||||
* @property-read string|null $isp The name of the ISP associated with the IP
|
||||
* address. This attribute is only available from the City and Insights web
|
||||
* services and the GeoIP2 Enterprise database.
|
||||
* @property-read string $network The network in CIDR notation associated with
|
||||
* the record. In particular, this is the largest network where all of the
|
||||
* fields besides $ipAddress have the same value.
|
||||
* @property-read string|null $organization The name of the organization associated
|
||||
* with the IP address. This attribute is only available from the City and
|
||||
* Insights web services and the GeoIP2 Enterprise database.
|
||||
* @property-read string|null $mobileCountryCode The [mobile country code
|
||||
* (MCC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with
|
||||
* the IP address and ISP. This property is available from the City and
|
||||
* Insights web services and the GeoIP2 Enterprise database.
|
||||
* @property-read string|null $mobileNetworkCode The [mobile network code
|
||||
* (MNC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with
|
||||
* the IP address and ISP. This property is available from the City and
|
||||
* Insights web services and the GeoIP2 Enterprise database.
|
||||
* @property-read float|null $staticIpScore An indicator of how static or
|
||||
* dynamic an IP address is. This property is only available from GeoIP2
|
||||
* Precision Insights.
|
||||
* @property-read int|null $userCount The estimated number of users sharing
|
||||
* the IP/network during the past 24 hours. For IPv4, the count is for the
|
||||
* individual IP. For IPv6, the count is for the /64 network. This property is
|
||||
* only available from GeoIP2 Precision Insights.
|
||||
* @property-read string|null $userType <p>The user type associated with the IP
|
||||
* address. This can be one of the following values:</p>
|
||||
* <ul>
|
||||
* <li>business
|
||||
* <li>cafe
|
||||
* <li>cellular
|
||||
* <li>college
|
||||
* <li>content_delivery_network
|
||||
* <li>dialup
|
||||
* <li>government
|
||||
* <li>hosting
|
||||
* <li>library
|
||||
* <li>military
|
||||
* <li>residential
|
||||
* <li>router
|
||||
* <li>school
|
||||
* <li>search_engine_spider
|
||||
* <li>traveler
|
||||
* </ul>
|
||||
* <p>
|
||||
* This attribute is only available from the Insights web service and the
|
||||
* GeoIP2 Enterprise database.
|
||||
* </p>
|
||||
*/
|
||||
class Traits extends AbstractRecord
|
||||
{
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $validAttributes = [
|
||||
'autonomousSystemNumber',
|
||||
'autonomousSystemOrganization',
|
||||
'connectionType',
|
||||
'domain',
|
||||
'ipAddress',
|
||||
'isAnonymous',
|
||||
'isAnonymousProxy',
|
||||
'isAnonymousVpn',
|
||||
'isHostingProvider',
|
||||
'isLegitimateProxy',
|
||||
'isp',
|
||||
'isPublicProxy',
|
||||
'isResidentialProxy',
|
||||
'isSatelliteProvider',
|
||||
'isTorExitNode',
|
||||
'mobileCountryCode',
|
||||
'mobileNetworkCode',
|
||||
'network',
|
||||
'organization',
|
||||
'staticIpScore',
|
||||
'userCount',
|
||||
'userType',
|
||||
];
|
||||
|
||||
public function __construct(?array $record)
|
||||
{
|
||||
if (!isset($record['network']) && isset($record['ip_address'], $record['prefix_len'])) {
|
||||
$record['network'] = Util::cidr($record['ip_address'], $record['prefix_len']);
|
||||
}
|
||||
|
||||
parent::__construct($record);
|
||||
}
|
||||
}
|
36
includes/vendor/geoip2/geoip2/src/Util.php
vendored
Normal file
36
includes/vendor/geoip2/geoip2/src/Util.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2;
|
||||
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* This returns the network in CIDR notation for the given IP and prefix
|
||||
* length. This is for internal use only.
|
||||
*
|
||||
* @internal
|
||||
* @ignore
|
||||
*/
|
||||
public static function cidr(string $ipAddress, int $prefixLen): string
|
||||
{
|
||||
$ipBytes = inet_pton($ipAddress);
|
||||
$networkBytes = str_repeat("\0", \strlen($ipBytes));
|
||||
|
||||
$curPrefix = $prefixLen;
|
||||
for ($i = 0; $i < \strlen($ipBytes) && $curPrefix > 0; $i++) {
|
||||
$b = $ipBytes[$i];
|
||||
if ($curPrefix < 8) {
|
||||
$shiftN = 8 - $curPrefix;
|
||||
$b = \chr(0xFF & (\ord($b) >> $shiftN) << $shiftN);
|
||||
}
|
||||
$networkBytes[$i] = $b;
|
||||
$curPrefix -= 8;
|
||||
}
|
||||
|
||||
$network = inet_ntop($networkBytes);
|
||||
|
||||
return "$network/$prefixLen";
|
||||
}
|
||||
}
|
253
includes/vendor/geoip2/geoip2/src/WebService/Client.php
vendored
Normal file
253
includes/vendor/geoip2/geoip2/src/WebService/Client.php
vendored
Normal file
@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeoIp2\WebService;
|
||||
|
||||
use GeoIp2\Exception\AddressNotFoundException;
|
||||
use GeoIp2\Exception\AuthenticationException;
|
||||
use GeoIp2\Exception\GeoIp2Exception;
|
||||
use GeoIp2\Exception\HttpException;
|
||||
use GeoIp2\Exception\InvalidRequestException;
|
||||
use GeoIp2\Exception\OutOfQueriesException;
|
||||
use GeoIp2\Model\City;
|
||||
use GeoIp2\Model\Country;
|
||||
use GeoIp2\Model\Insights;
|
||||
use GeoIp2\ProviderInterface;
|
||||
use MaxMind\WebService\Client as WsClient;
|
||||
|
||||
/**
|
||||
* This class provides a client API for all the GeoIP2 Precision web services.
|
||||
* The services are Country, City, and Insights. Each service returns a
|
||||
* different set of data about an IP address, with Country returning the
|
||||
* least data and Insights the most.
|
||||
*
|
||||
* Each web service is represented by a different model class, and these model
|
||||
* classes in turn contain multiple record classes. The record classes have
|
||||
* attributes which contain data about the IP address.
|
||||
*
|
||||
* If the web service does not return a particular piece of data for an IP
|
||||
* address, the associated attribute is not populated.
|
||||
*
|
||||
* The web service may not return any information for an entire record, in
|
||||
* which case all of the attributes for that record class will be empty.
|
||||
*
|
||||
* ## Usage ##
|
||||
*
|
||||
* The basic API for this class is the same for all of the web service end
|
||||
* points. First you create a web service object with your MaxMind `$accountId`
|
||||
* and `$licenseKey`, then you call the method corresponding to a specific end
|
||||
* point, passing it the IP address you want to look up.
|
||||
*
|
||||
* If the request succeeds, the method call will return a model class for
|
||||
* the service you called. This model in turn contains multiple record
|
||||
* classes, each of which represents part of the data returned by the web
|
||||
* service.
|
||||
*
|
||||
* If the request fails, the client class throws an exception.
|
||||
*/
|
||||
class Client implements ProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
private $locales;
|
||||
/**
|
||||
* @var WsClient
|
||||
*/
|
||||
private $client;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $basePath = '/geoip/v2.1';
|
||||
|
||||
public const VERSION = 'v2.12.2';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $accountId your MaxMind account ID
|
||||
* @param string $licenseKey your MaxMind license key
|
||||
* @param array $locales list of locale codes to use in name property
|
||||
* from most preferred to least preferred
|
||||
* @param array $options array of options. Valid options include:
|
||||
* * `host` - The host to use when querying the web service. To
|
||||
* query the GeoLite2 web service instead of GeoIP2 Precision,
|
||||
* set the host to `geolite.info`.
|
||||
* * `timeout` - Timeout in seconds.
|
||||
* * `connectTimeout` - Initial connection timeout in seconds.
|
||||
* * `proxy` - The HTTP proxy to use. May include a schema, port,
|
||||
* username, and password, e.g.,
|
||||
* `http://username:password@127.0.0.1:10`.
|
||||
*/
|
||||
public function __construct(
|
||||
int $accountId,
|
||||
string $licenseKey,
|
||||
array $locales = ['en'],
|
||||
array $options = []
|
||||
) {
|
||||
$this->locales = $locales;
|
||||
|
||||
// This is for backwards compatibility. Do not remove except for a
|
||||
// major version bump.
|
||||
// @phpstan-ignore-next-line
|
||||
if (\is_string($options)) {
|
||||
$options = ['host' => $options];
|
||||
}
|
||||
|
||||
if (!isset($options['host'])) {
|
||||
$options['host'] = 'geoip.maxmind.com';
|
||||
}
|
||||
|
||||
$options['userAgent'] = $this->userAgent();
|
||||
|
||||
$this->client = new WsClient($accountId, $licenseKey, $options);
|
||||
}
|
||||
|
||||
private function userAgent(): string
|
||||
{
|
||||
return 'GeoIP2-API/' . self::VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calls the City service.
|
||||
*
|
||||
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
||||
* address is provided, the address that the web service is called
|
||||
* from will be used.
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
|
||||
* provided is not in our database (e.g., a private address).
|
||||
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
||||
* with the account ID or license key that you provided
|
||||
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
|
||||
* of queries
|
||||
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
||||
* invalid for some other reason. This may indicate an issue
|
||||
* with this API. Please report the error to MaxMind.
|
||||
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
|
||||
* This could indicate a problem with the connection between
|
||||
* your server and the web service or that the web service
|
||||
* returned an invalid document or 500 error code
|
||||
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
|
||||
* class to the above exceptions. It will be thrown directly
|
||||
* if a 200 status code is returned but the body is invalid.
|
||||
*/
|
||||
public function city(string $ipAddress = 'me'): City
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->responseFor('city', 'City', $ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calls the Country service.
|
||||
*
|
||||
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
||||
* address is provided, the address that the web service is called
|
||||
* from will be used.
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g.,
|
||||
* a private address).
|
||||
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
||||
* with the account ID or license key that you provided
|
||||
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out of queries
|
||||
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
||||
* invalid for some other reason. This may indicate an
|
||||
* issue with this API. Please report the error to MaxMind.
|
||||
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error
|
||||
* code or message was returned. This could indicate a problem
|
||||
* with the connection between your server and the web service
|
||||
* or that the web service returned an invalid document or 500
|
||||
* error code.
|
||||
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent class to the above exceptions. It
|
||||
* will be thrown directly if a 200 status code is returned but
|
||||
* the body is invalid.
|
||||
*/
|
||||
public function country(string $ipAddress = 'me'): Country
|
||||
{
|
||||
return $this->responseFor('country', 'Country', $ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calls the Insights service. Insights is only supported by GeoIP2
|
||||
* Precision. The GeoLite2 web service does not support it.
|
||||
*
|
||||
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
||||
* address is provided, the address that the web service is called
|
||||
* from will be used.
|
||||
*
|
||||
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
|
||||
* provided is not in our database (e.g., a private address).
|
||||
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
||||
* with the account ID or license key that you provided
|
||||
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
|
||||
* of queries
|
||||
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
||||
* invalid for some other reason. This may indicate an
|
||||
* issue with this API. Please report the error to MaxMind.
|
||||
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
|
||||
* This could indicate a problem with the connection between
|
||||
* your server and the web service or that the web service
|
||||
* returned an invalid document or 500 error code
|
||||
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
|
||||
* class to the above exceptions. It will be thrown directly
|
||||
* if a 200 status code is returned but the body is invalid.
|
||||
*/
|
||||
public function insights(string $ipAddress = 'me'): Insights
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->responseFor('insights', 'Insights', $ipAddress);
|
||||
}
|
||||
|
||||
private function responseFor(string $endpoint, string $class, string $ipAddress): Country
|
||||
{
|
||||
$path = implode('/', [self::$basePath, $endpoint, $ipAddress]);
|
||||
|
||||
try {
|
||||
$body = $this->client->get('GeoIP2 ' . $class, $path);
|
||||
} catch (\MaxMind\Exception\IpAddressNotFoundException $ex) {
|
||||
throw new AddressNotFoundException(
|
||||
$ex->getMessage(),
|
||||
$ex->getStatusCode(),
|
||||
$ex
|
||||
);
|
||||
} catch (\MaxMind\Exception\AuthenticationException $ex) {
|
||||
throw new AuthenticationException(
|
||||
$ex->getMessage(),
|
||||
$ex->getStatusCode(),
|
||||
$ex
|
||||
);
|
||||
} catch (\MaxMind\Exception\InsufficientFundsException $ex) {
|
||||
throw new OutOfQueriesException(
|
||||
$ex->getMessage(),
|
||||
$ex->getStatusCode(),
|
||||
$ex
|
||||
);
|
||||
} catch (\MaxMind\Exception\InvalidRequestException $ex) {
|
||||
throw new InvalidRequestException(
|
||||
$ex->getMessage(),
|
||||
$ex->getErrorCode(),
|
||||
$ex->getStatusCode(),
|
||||
$ex->getUri(),
|
||||
$ex
|
||||
);
|
||||
} catch (\MaxMind\Exception\HttpException $ex) {
|
||||
throw new HttpException(
|
||||
$ex->getMessage(),
|
||||
$ex->getStatusCode(),
|
||||
$ex->getUri(),
|
||||
$ex
|
||||
);
|
||||
} catch (\MaxMind\Exception\WebServiceException $ex) {
|
||||
throw new GeoIp2Exception(
|
||||
$ex->getMessage(),
|
||||
$ex->getCode(),
|
||||
$ex
|
||||
);
|
||||
}
|
||||
|
||||
$class = 'GeoIp2\\Model\\' . $class;
|
||||
|
||||
return new $class($body, $this->locales);
|
||||
}
|
||||
}
|
20
includes/vendor/jakeasmith/http_build_url/readme.md
vendored
Normal file
20
includes/vendor/jakeasmith/http_build_url/readme.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# http_build_url() for PHP
|
||||
|
||||
[](https://travis-ci.org/jakeasmith/http_build_url)
|
||||
[](https://codeclimate.com/github/jakeasmith/http_build_url)
|
||||
[](https://packagist.org/packages/jakeasmith/http_build_url)
|
||||
[](https://packagist.org/packages/jakeasmith/http_build_url)
|
||||
|
||||
This simple library provides functionality for [`http_build_url()`](http://us2.php.net/manual/en/function.http-build-url.php) to environments without pecl_http. It aims to mimic the functionality of the pecl function in every way and ships with a full suite of tests that have been run against both the original function and the one in this package.
|
||||
|
||||
## Installation
|
||||
|
||||
The easiest way to install this library is to use [Composer](https://getcomposer.org/) from the command line.
|
||||
|
||||
```
|
||||
$ composer require jakeasmith/http_build_url ^1
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
174
includes/vendor/jakeasmith/http_build_url/src/http_build_url.php
vendored
Normal file
174
includes/vendor/jakeasmith/http_build_url/src/http_build_url.php
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* URL constants as defined in the PHP Manual under "Constants usable with
|
||||
* http_build_url()".
|
||||
*
|
||||
* @see http://us2.php.net/manual/en/http.constants.php#http.constants.url
|
||||
*/
|
||||
if (!defined('HTTP_URL_REPLACE')) {
|
||||
define('HTTP_URL_REPLACE', 1);
|
||||
}
|
||||
if (!defined('HTTP_URL_JOIN_PATH')) {
|
||||
define('HTTP_URL_JOIN_PATH', 2);
|
||||
}
|
||||
if (!defined('HTTP_URL_JOIN_QUERY')) {
|
||||
define('HTTP_URL_JOIN_QUERY', 4);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_USER')) {
|
||||
define('HTTP_URL_STRIP_USER', 8);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_PASS')) {
|
||||
define('HTTP_URL_STRIP_PASS', 16);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_AUTH')) {
|
||||
define('HTTP_URL_STRIP_AUTH', 32);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_PORT')) {
|
||||
define('HTTP_URL_STRIP_PORT', 64);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_PATH')) {
|
||||
define('HTTP_URL_STRIP_PATH', 128);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_QUERY')) {
|
||||
define('HTTP_URL_STRIP_QUERY', 256);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_FRAGMENT')) {
|
||||
define('HTTP_URL_STRIP_FRAGMENT', 512);
|
||||
}
|
||||
if (!defined('HTTP_URL_STRIP_ALL')) {
|
||||
define('HTTP_URL_STRIP_ALL', 1024);
|
||||
}
|
||||
|
||||
if (!function_exists('http_build_url')) {
|
||||
|
||||
/**
|
||||
* Build a URL.
|
||||
*
|
||||
* The parts of the second URL will be merged into the first according to
|
||||
* the flags argument.
|
||||
*
|
||||
* @param mixed $url (part(s) of) an URL in form of a string or
|
||||
* associative array like parse_url() returns
|
||||
* @param mixed $parts same as the first argument
|
||||
* @param int $flags a bitmask of binary or'ed HTTP_URL constants;
|
||||
* HTTP_URL_REPLACE is the default
|
||||
* @param array $new_url if set, it will be filled with the parts of the
|
||||
* composed url like parse_url() would return
|
||||
* @return string
|
||||
*/
|
||||
function http_build_url($url, $parts = array(), $flags = HTTP_URL_REPLACE, &$new_url = array())
|
||||
{
|
||||
is_array($url) || $url = parse_url($url);
|
||||
is_array($parts) || $parts = parse_url($parts);
|
||||
|
||||
isset($url['query']) && is_string($url['query']) || $url['query'] = null;
|
||||
isset($parts['query']) && is_string($parts['query']) || $parts['query'] = null;
|
||||
|
||||
$keys = array('user', 'pass', 'port', 'path', 'query', 'fragment');
|
||||
|
||||
// HTTP_URL_STRIP_ALL and HTTP_URL_STRIP_AUTH cover several other flags.
|
||||
if ($flags & HTTP_URL_STRIP_ALL) {
|
||||
$flags |= HTTP_URL_STRIP_USER | HTTP_URL_STRIP_PASS
|
||||
| HTTP_URL_STRIP_PORT | HTTP_URL_STRIP_PATH
|
||||
| HTTP_URL_STRIP_QUERY | HTTP_URL_STRIP_FRAGMENT;
|
||||
} elseif ($flags & HTTP_URL_STRIP_AUTH) {
|
||||
$flags |= HTTP_URL_STRIP_USER | HTTP_URL_STRIP_PASS;
|
||||
}
|
||||
|
||||
// Schema and host are alwasy replaced
|
||||
foreach (array('scheme', 'host') as $part) {
|
||||
if (isset($parts[$part])) {
|
||||
$url[$part] = $parts[$part];
|
||||
}
|
||||
}
|
||||
|
||||
if ($flags & HTTP_URL_REPLACE) {
|
||||
foreach ($keys as $key) {
|
||||
if (isset($parts[$key])) {
|
||||
$url[$key] = $parts[$key];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isset($parts['path']) && ($flags & HTTP_URL_JOIN_PATH)) {
|
||||
if (isset($url['path']) && substr($parts['path'], 0, 1) !== '/') {
|
||||
// Workaround for trailing slashes
|
||||
$url['path'] .= 'a';
|
||||
$url['path'] = rtrim(
|
||||
str_replace(basename($url['path']), '', $url['path']),
|
||||
'/'
|
||||
) . '/' . ltrim($parts['path'], '/');
|
||||
} else {
|
||||
$url['path'] = $parts['path'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($parts['query']) && ($flags & HTTP_URL_JOIN_QUERY)) {
|
||||
if (isset($url['query'])) {
|
||||
parse_str($url['query'], $url_query);
|
||||
parse_str($parts['query'], $parts_query);
|
||||
|
||||
$url['query'] = http_build_query(
|
||||
array_replace_recursive(
|
||||
$url_query,
|
||||
$parts_query
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$url['query'] = $parts['query'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($url['path']) && $url['path'] !== '' && substr($url['path'], 0, 1) !== '/') {
|
||||
$url['path'] = '/' . $url['path'];
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$strip = 'HTTP_URL_STRIP_' . strtoupper($key);
|
||||
if ($flags & constant($strip)) {
|
||||
unset($url[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$parsed_string = '';
|
||||
|
||||
if (!empty($url['scheme'])) {
|
||||
$parsed_string .= $url['scheme'] . '://';
|
||||
}
|
||||
|
||||
if (!empty($url['user'])) {
|
||||
$parsed_string .= $url['user'];
|
||||
|
||||
if (isset($url['pass'])) {
|
||||
$parsed_string .= ':' . $url['pass'];
|
||||
}
|
||||
|
||||
$parsed_string .= '@';
|
||||
}
|
||||
|
||||
if (!empty($url['host'])) {
|
||||
$parsed_string .= $url['host'];
|
||||
}
|
||||
|
||||
if (!empty($url['port'])) {
|
||||
$parsed_string .= ':' . $url['port'];
|
||||
}
|
||||
|
||||
if (!empty($url['path'])) {
|
||||
$parsed_string .= $url['path'];
|
||||
}
|
||||
|
||||
if (!empty($url['query'])) {
|
||||
$parsed_string .= '?' . $url['query'];
|
||||
}
|
||||
|
||||
if (!empty($url['fragment'])) {
|
||||
$parsed_string .= '#' . $url['fragment'];
|
||||
}
|
||||
|
||||
$new_url = $url;
|
||||
|
||||
return $parsed_string;
|
||||
}
|
||||
}
|
185
includes/vendor/maxmind-db/reader/README.md
vendored
Normal file
185
includes/vendor/maxmind-db/reader/README.md
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
# MaxMind DB Reader PHP API #
|
||||
|
||||
## Description ##
|
||||
|
||||
This is the PHP API for reading MaxMind DB files. MaxMind DB is a binary file
|
||||
format that stores data indexed by IP address subnets (IPv4 or IPv6).
|
||||
|
||||
## Installation (Composer) ##
|
||||
|
||||
We recommend installing this package with [Composer](https://getcomposer.org/).
|
||||
|
||||
### Download Composer ###
|
||||
|
||||
To download Composer, run in the root directory of your project:
|
||||
|
||||
```bash
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
```
|
||||
|
||||
You should now have the file `composer.phar` in your project directory.
|
||||
|
||||
### Install Dependencies ###
|
||||
|
||||
Run in your project root:
|
||||
|
||||
```
|
||||
php composer.phar require maxmind-db/reader:~1.0
|
||||
```
|
||||
|
||||
You should now have the files `composer.json` and `composer.lock` as well as
|
||||
the directory `vendor` in your project directory. If you use a version control
|
||||
system, `composer.json` should be added to it.
|
||||
|
||||
### Require Autoloader ###
|
||||
|
||||
After installing the dependencies, you need to require the Composer autoloader
|
||||
from your code:
|
||||
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
```
|
||||
|
||||
## Installation (Standalone) ##
|
||||
|
||||
If you don't want to use Composer for some reason, a custom
|
||||
`autoload.php` is provided for you in the project root. To use the
|
||||
library, simply include that file,
|
||||
|
||||
```php
|
||||
require('/path/to/MaxMind-DB-Reader-php/autoload.php');
|
||||
```
|
||||
|
||||
and then instantiate the reader class normally:
|
||||
|
||||
```php
|
||||
use MaxMind\Db\Reader;
|
||||
$reader = new Reader('example.mmdb');
|
||||
```
|
||||
|
||||
## Installation (RPM)
|
||||
|
||||
RPMs are available in the [official Fedora repository](https://apps.fedoraproject.org/packages/php-maxminddb).
|
||||
|
||||
To install on Fedora, run:
|
||||
|
||||
```bash
|
||||
dnf install php-maxminddb
|
||||
```
|
||||
|
||||
To install on CentOS or RHEL 7, first [enable the EPEL repository](https://fedoraproject.org/wiki/EPEL)
|
||||
and then run:
|
||||
|
||||
```bash
|
||||
yum install php-maxminddb
|
||||
```
|
||||
|
||||
Please note that these packages are *not* maintained by MaxMind.
|
||||
|
||||
## Usage ##
|
||||
|
||||
## Example ##
|
||||
|
||||
```php
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use MaxMind\Db\Reader;
|
||||
|
||||
$ipAddress = '24.24.24.24';
|
||||
$databaseFile = 'GeoIP2-City.mmdb';
|
||||
|
||||
$reader = new Reader($databaseFile);
|
||||
|
||||
// get returns just the record for the IP address
|
||||
print_r($reader->get($ipAddress));
|
||||
|
||||
// getWithPrefixLen returns an array containing the record and the
|
||||
// associated prefix length for that record.
|
||||
print_r($reader->getWithPrefixLen($ipAddress));
|
||||
|
||||
$reader->close();
|
||||
```
|
||||
|
||||
## Optional PHP C Extension ##
|
||||
|
||||
MaxMind provides an optional C extension that is a drop-in replacement for
|
||||
`MaxMind\Db\Reader`. In order to use this extension, you must install the
|
||||
Reader API as described above and install the extension as described below. If
|
||||
you are using an autoloader, no changes to your code should be necessary.
|
||||
|
||||
### Installing Extension ###
|
||||
|
||||
First install [libmaxminddb](https://github.com/maxmind/libmaxminddb) as
|
||||
described in its [README.md
|
||||
file](https://github.com/maxmind/libmaxminddb/blob/main/README.md#installing-from-a-tarball).
|
||||
After successfully installing libmaxmindb, you may install the extension
|
||||
from [pecl](https://pecl.php.net/package/maxminddb):
|
||||
|
||||
```
|
||||
pecl install maxminddb
|
||||
```
|
||||
|
||||
Alternatively, you may install it from the source. To do so, run the following
|
||||
commands from the top-level directory of this distribution:
|
||||
|
||||
```
|
||||
cd ext
|
||||
phpize
|
||||
./configure
|
||||
make
|
||||
make test
|
||||
sudo make install
|
||||
```
|
||||
|
||||
You then must load your extension. The recommend method is to add the
|
||||
following to your `php.ini` file:
|
||||
|
||||
```
|
||||
extension=maxminddb.so
|
||||
```
|
||||
|
||||
Note: You may need to install the PHP development package on your OS such as
|
||||
php5-dev for Debian-based systems or php-devel for RedHat/Fedora-based ones.
|
||||
|
||||
## 128-bit Integer Support ##
|
||||
|
||||
The MaxMind DB format includes 128-bit unsigned integer as a type. Although
|
||||
no MaxMind-distributed database currently makes use of this type, both the
|
||||
pure PHP reader and the C extension support this type. The pure PHP reader
|
||||
requires gmp or bcmath to read databases with 128-bit unsigned integers.
|
||||
|
||||
The integer is currently returned as a hexadecimal string (prefixed with "0x")
|
||||
by the C extension and a decimal string (no prefix) by the pure PHP reader.
|
||||
Any change to make the reader implementations always return either a
|
||||
hexadecimal or decimal representation of the integer will NOT be considered a
|
||||
breaking change.
|
||||
|
||||
## Support ##
|
||||
|
||||
Please report all issues with this code using the [GitHub issue tracker](https://github.com/maxmind/MaxMind-DB-Reader-php/issues).
|
||||
|
||||
If you are having an issue with a MaxMind service that is not specific to the
|
||||
client API, please see [our support page](https://www.maxmind.com/en/support).
|
||||
|
||||
## Requirements ##
|
||||
|
||||
This library requires PHP 7.2 or greater.
|
||||
|
||||
The GMP or BCMath extension may be required to read some databases
|
||||
using the pure PHP API.
|
||||
|
||||
## Contributing ##
|
||||
|
||||
Patches and pull requests are encouraged. All code should follow the PSR-1 and
|
||||
PSR-2 style guidelines. Please include unit tests whenever possible.
|
||||
|
||||
## Versioning ##
|
||||
|
||||
The MaxMind DB Reader PHP API uses [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## Copyright and License ##
|
||||
|
||||
This software is Copyright (c) 2014-2020 by MaxMind, Inc.
|
||||
|
||||
This is free software, licensed under the Apache License, Version 2.0.
|
373
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php
vendored
Normal file
373
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Db;
|
||||
|
||||
use ArgumentCountError;
|
||||
use BadMethodCallException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use MaxMind\Db\Reader\Decoder;
|
||||
use MaxMind\Db\Reader\InvalidDatabaseException;
|
||||
use MaxMind\Db\Reader\Metadata;
|
||||
use MaxMind\Db\Reader\Util;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Instances of this class provide a reader for the MaxMind DB format. IP
|
||||
* addresses can be looked up using the get method.
|
||||
*/
|
||||
class Reader
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private static $DATA_SECTION_SEPARATOR_SIZE = 16;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com";
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private static $METADATA_START_MARKER_LENGTH = 14;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KiB
|
||||
|
||||
/**
|
||||
* @var Decoder
|
||||
*/
|
||||
private $decoder;
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $fileHandle;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $fileSize;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $ipV4Start;
|
||||
/**
|
||||
* @var Metadata
|
||||
*/
|
||||
private $metadata;
|
||||
|
||||
/**
|
||||
* Constructs a Reader for the MaxMind DB format. The file passed to it must
|
||||
* be a valid MaxMind DB file such as a GeoIp2 database file.
|
||||
*
|
||||
* @param string $database
|
||||
* the MaxMind DB file to use
|
||||
*
|
||||
* @throws InvalidArgumentException for invalid database path or unknown arguments
|
||||
* @throws InvalidDatabaseException
|
||||
* if the database is invalid or there is an error reading
|
||||
* from it
|
||||
*/
|
||||
public function __construct(string $database)
|
||||
{
|
||||
if (\func_num_args() !== 1) {
|
||||
throw new ArgumentCountError(
|
||||
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
|
||||
);
|
||||
}
|
||||
|
||||
$fileHandle = @fopen($database, 'rb');
|
||||
if ($fileHandle === false) {
|
||||
throw new InvalidArgumentException(
|
||||
"The file \"$database\" does not exist or is not readable."
|
||||
);
|
||||
}
|
||||
$this->fileHandle = $fileHandle;
|
||||
|
||||
$fileSize = @filesize($database);
|
||||
if ($fileSize === false) {
|
||||
throw new UnexpectedValueException(
|
||||
"Error determining the size of \"$database\"."
|
||||
);
|
||||
}
|
||||
$this->fileSize = $fileSize;
|
||||
|
||||
$start = $this->findMetadataStart($database);
|
||||
$metadataDecoder = new Decoder($this->fileHandle, $start);
|
||||
[$metadataArray] = $metadataDecoder->decode($start);
|
||||
$this->metadata = new Metadata($metadataArray);
|
||||
$this->decoder = new Decoder(
|
||||
$this->fileHandle,
|
||||
$this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
|
||||
);
|
||||
$this->ipV4Start = $this->ipV4StartNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the record for the IP address.
|
||||
*
|
||||
* @param string $ipAddress
|
||||
* the IP address to look up
|
||||
*
|
||||
* @throws BadMethodCallException if this method is called on a closed database
|
||||
* @throws InvalidArgumentException if something other than a single IP address is passed to the method
|
||||
* @throws InvalidDatabaseException
|
||||
* if the database is invalid or there is an error reading
|
||||
* from it
|
||||
*
|
||||
* @return mixed the record for the IP address
|
||||
*/
|
||||
public function get(string $ipAddress)
|
||||
{
|
||||
if (\func_num_args() !== 1) {
|
||||
throw new ArgumentCountError(
|
||||
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
|
||||
);
|
||||
}
|
||||
[$record] = $this->getWithPrefixLen($ipAddress);
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the record for the IP address and its associated network prefix length.
|
||||
*
|
||||
* @param string $ipAddress
|
||||
* the IP address to look up
|
||||
*
|
||||
* @throws BadMethodCallException if this method is called on a closed database
|
||||
* @throws InvalidArgumentException if something other than a single IP address is passed to the method
|
||||
* @throws InvalidDatabaseException
|
||||
* if the database is invalid or there is an error reading
|
||||
* from it
|
||||
*
|
||||
* @return array an array where the first element is the record and the
|
||||
* second the network prefix length for the record
|
||||
*/
|
||||
public function getWithPrefixLen(string $ipAddress): array
|
||||
{
|
||||
if (\func_num_args() !== 1) {
|
||||
throw new ArgumentCountError(
|
||||
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
|
||||
);
|
||||
}
|
||||
|
||||
if (!\is_resource($this->fileHandle)) {
|
||||
throw new BadMethodCallException(
|
||||
'Attempt to read from a closed MaxMind DB.'
|
||||
);
|
||||
}
|
||||
|
||||
[$pointer, $prefixLen] = $this->findAddressInTree($ipAddress);
|
||||
if ($pointer === 0) {
|
||||
return [null, $prefixLen];
|
||||
}
|
||||
|
||||
return [$this->resolveDataPointer($pointer), $prefixLen];
|
||||
}
|
||||
|
||||
private function findAddressInTree(string $ipAddress): array
|
||||
{
|
||||
$packedAddr = @inet_pton($ipAddress);
|
||||
if ($packedAddr === false) {
|
||||
throw new InvalidArgumentException(
|
||||
"The value \"$ipAddress\" is not a valid IP address."
|
||||
);
|
||||
}
|
||||
|
||||
$rawAddress = unpack('C*', $packedAddr);
|
||||
|
||||
$bitCount = \count($rawAddress) * 8;
|
||||
|
||||
// The first node of the tree is always node 0, at the beginning of the
|
||||
// value
|
||||
$node = 0;
|
||||
|
||||
$metadata = $this->metadata;
|
||||
|
||||
// Check if we are looking up an IPv4 address in an IPv6 tree. If this
|
||||
// is the case, we can skip over the first 96 nodes.
|
||||
if ($metadata->ipVersion === 6) {
|
||||
if ($bitCount === 32) {
|
||||
$node = $this->ipV4Start;
|
||||
}
|
||||
} elseif ($metadata->ipVersion === 4 && $bitCount === 128) {
|
||||
throw new InvalidArgumentException(
|
||||
"Error looking up $ipAddress. You attempted to look up an"
|
||||
. ' IPv6 address in an IPv4-only database.'
|
||||
);
|
||||
}
|
||||
|
||||
$nodeCount = $metadata->nodeCount;
|
||||
|
||||
for ($i = 0; $i < $bitCount && $node < $nodeCount; ++$i) {
|
||||
$tempBit = 0xFF & $rawAddress[($i >> 3) + 1];
|
||||
$bit = 1 & ($tempBit >> 7 - ($i % 8));
|
||||
|
||||
$node = $this->readNode($node, $bit);
|
||||
}
|
||||
if ($node === $nodeCount) {
|
||||
// Record is empty
|
||||
return [0, $i];
|
||||
}
|
||||
if ($node > $nodeCount) {
|
||||
// Record is a data pointer
|
||||
return [$node, $i];
|
||||
}
|
||||
|
||||
throw new InvalidDatabaseException(
|
||||
'Invalid or corrupt database. Maximum search depth reached without finding a leaf node'
|
||||
);
|
||||
}
|
||||
|
||||
private function ipV4StartNode(): int
|
||||
{
|
||||
// If we have an IPv4 database, the start node is the first node
|
||||
if ($this->metadata->ipVersion === 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$node = 0;
|
||||
|
||||
for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; ++$i) {
|
||||
$node = $this->readNode($node, 0);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function readNode(int $nodeNumber, int $index): int
|
||||
{
|
||||
$baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
|
||||
|
||||
switch ($this->metadata->recordSize) {
|
||||
case 24:
|
||||
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
|
||||
[, $node] = unpack('N', "\x00" . $bytes);
|
||||
|
||||
return $node;
|
||||
|
||||
case 28:
|
||||
$bytes = Util::read($this->fileHandle, $baseOffset + 3 * $index, 4);
|
||||
if ($index === 0) {
|
||||
$middle = (0xF0 & \ord($bytes[3])) >> 4;
|
||||
} else {
|
||||
$middle = 0x0F & \ord($bytes[0]);
|
||||
}
|
||||
[, $node] = unpack('N', \chr($middle) . substr($bytes, $index, 3));
|
||||
|
||||
return $node;
|
||||
|
||||
case 32:
|
||||
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
|
||||
[, $node] = unpack('N', $bytes);
|
||||
|
||||
return $node;
|
||||
|
||||
default:
|
||||
throw new InvalidDatabaseException(
|
||||
'Unknown record size: '
|
||||
. $this->metadata->recordSize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
private function resolveDataPointer(int $pointer)
|
||||
{
|
||||
$resolved = $pointer - $this->metadata->nodeCount
|
||||
+ $this->metadata->searchTreeSize;
|
||||
if ($resolved >= $this->fileSize) {
|
||||
throw new InvalidDatabaseException(
|
||||
"The MaxMind DB file's search tree is corrupt"
|
||||
);
|
||||
}
|
||||
|
||||
[$data] = $this->decoder->decode($resolved);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an extremely naive but reasonably readable implementation. There
|
||||
* are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
|
||||
* an issue, but I suspect it won't be.
|
||||
*/
|
||||
private function findMetadataStart(string $filename): int
|
||||
{
|
||||
$handle = $this->fileHandle;
|
||||
$fstat = fstat($handle);
|
||||
$fileSize = $fstat['size'];
|
||||
$marker = self::$METADATA_START_MARKER;
|
||||
$markerLength = self::$METADATA_START_MARKER_LENGTH;
|
||||
|
||||
$minStart = $fileSize - min(self::$METADATA_MAX_SIZE, $fileSize);
|
||||
|
||||
for ($offset = $fileSize - $markerLength; $offset >= $minStart; --$offset) {
|
||||
if (fseek($handle, $offset) !== 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$value = fread($handle, $markerLength);
|
||||
if ($value === $marker) {
|
||||
return $offset + $markerLength;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidDatabaseException(
|
||||
"Error opening database file ($filename). " .
|
||||
'Is this a valid MaxMind DB file?'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if arguments are passed to the method
|
||||
* @throws BadMethodCallException if the database has been closed
|
||||
*
|
||||
* @return Metadata object for the database
|
||||
*/
|
||||
public function metadata(): Metadata
|
||||
{
|
||||
if (\func_num_args()) {
|
||||
throw new ArgumentCountError(
|
||||
sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
|
||||
);
|
||||
}
|
||||
|
||||
// Not technically required, but this makes it consistent with
|
||||
// C extension and it allows us to change our implementation later.
|
||||
if (!\is_resource($this->fileHandle)) {
|
||||
throw new BadMethodCallException(
|
||||
'Attempt to read from a closed MaxMind DB.'
|
||||
);
|
||||
}
|
||||
|
||||
return clone $this->metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the MaxMind DB and returns resources to the system.
|
||||
*
|
||||
* @throws Exception
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
if (\func_num_args()) {
|
||||
throw new ArgumentCountError(
|
||||
sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
|
||||
);
|
||||
}
|
||||
|
||||
if (!\is_resource($this->fileHandle)) {
|
||||
throw new BadMethodCallException(
|
||||
'Attempt to close a closed MaxMind DB.'
|
||||
);
|
||||
}
|
||||
fclose($this->fileHandle);
|
||||
}
|
||||
}
|
374
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php
vendored
Normal file
374
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php
vendored
Normal file
@ -0,0 +1,374 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Db\Reader;
|
||||
|
||||
// @codingStandardsIgnoreLine
|
||||
use RuntimeException;
|
||||
|
||||
class Decoder
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $fileStream;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $pointerBase;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $pointerBaseByteSize;
|
||||
/**
|
||||
* This is only used for unit testing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $pointerTestHack;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $switchByteOrder;
|
||||
|
||||
private const _EXTENDED = 0;
|
||||
private const _POINTER = 1;
|
||||
private const _UTF8_STRING = 2;
|
||||
private const _DOUBLE = 3;
|
||||
private const _BYTES = 4;
|
||||
private const _UINT16 = 5;
|
||||
private const _UINT32 = 6;
|
||||
private const _MAP = 7;
|
||||
private const _INT32 = 8;
|
||||
private const _UINT64 = 9;
|
||||
private const _UINT128 = 10;
|
||||
private const _ARRAY = 11;
|
||||
private const _CONTAINER = 12;
|
||||
private const _END_MARKER = 13;
|
||||
private const _BOOLEAN = 14;
|
||||
private const _FLOAT = 15;
|
||||
|
||||
/**
|
||||
* @param resource $fileStream
|
||||
*/
|
||||
public function __construct(
|
||||
$fileStream,
|
||||
int $pointerBase = 0,
|
||||
bool $pointerTestHack = false
|
||||
) {
|
||||
$this->fileStream = $fileStream;
|
||||
$this->pointerBase = $pointerBase;
|
||||
|
||||
$this->pointerBaseByteSize = $pointerBase > 0 ? log($pointerBase, 2) / 8 : 0;
|
||||
$this->pointerTestHack = $pointerTestHack;
|
||||
|
||||
$this->switchByteOrder = $this->isPlatformLittleEndian();
|
||||
}
|
||||
|
||||
public function decode(int $offset): array
|
||||
{
|
||||
$ctrlByte = \ord(Util::read($this->fileStream, $offset, 1));
|
||||
++$offset;
|
||||
|
||||
$type = $ctrlByte >> 5;
|
||||
|
||||
// Pointers are a special case, we don't read the next $size bytes, we
|
||||
// use the size to determine the length of the pointer and then follow
|
||||
// it.
|
||||
if ($type === self::_POINTER) {
|
||||
[$pointer, $offset] = $this->decodePointer($ctrlByte, $offset);
|
||||
|
||||
// for unit testing
|
||||
if ($this->pointerTestHack) {
|
||||
return [$pointer];
|
||||
}
|
||||
|
||||
[$result] = $this->decode($pointer);
|
||||
|
||||
return [$result, $offset];
|
||||
}
|
||||
|
||||
if ($type === self::_EXTENDED) {
|
||||
$nextByte = \ord(Util::read($this->fileStream, $offset, 1));
|
||||
|
||||
$type = $nextByte + 7;
|
||||
|
||||
if ($type < 8) {
|
||||
throw new InvalidDatabaseException(
|
||||
'Something went horribly wrong in the decoder. An extended type '
|
||||
. 'resolved to a type number < 8 ('
|
||||
. $type
|
||||
. ')'
|
||||
);
|
||||
}
|
||||
|
||||
++$offset;
|
||||
}
|
||||
|
||||
[$size, $offset] = $this->sizeFromCtrlByte($ctrlByte, $offset);
|
||||
|
||||
return $this->decodeByType($type, $offset, $size);
|
||||
}
|
||||
|
||||
private function decodeByType(int $type, int $offset, int $size): array
|
||||
{
|
||||
switch ($type) {
|
||||
case self::_MAP:
|
||||
return $this->decodeMap($size, $offset);
|
||||
|
||||
case self::_ARRAY:
|
||||
return $this->decodeArray($size, $offset);
|
||||
|
||||
case self::_BOOLEAN:
|
||||
return [$this->decodeBoolean($size), $offset];
|
||||
}
|
||||
|
||||
$newOffset = $offset + $size;
|
||||
$bytes = Util::read($this->fileStream, $offset, $size);
|
||||
|
||||
switch ($type) {
|
||||
case self::_BYTES:
|
||||
case self::_UTF8_STRING:
|
||||
return [$bytes, $newOffset];
|
||||
|
||||
case self::_DOUBLE:
|
||||
$this->verifySize(8, $size);
|
||||
|
||||
return [$this->decodeDouble($bytes), $newOffset];
|
||||
|
||||
case self::_FLOAT:
|
||||
$this->verifySize(4, $size);
|
||||
|
||||
return [$this->decodeFloat($bytes), $newOffset];
|
||||
|
||||
case self::_INT32:
|
||||
return [$this->decodeInt32($bytes, $size), $newOffset];
|
||||
|
||||
case self::_UINT16:
|
||||
case self::_UINT32:
|
||||
case self::_UINT64:
|
||||
case self::_UINT128:
|
||||
return [$this->decodeUint($bytes, $size), $newOffset];
|
||||
|
||||
default:
|
||||
throw new InvalidDatabaseException(
|
||||
'Unknown or unexpected type: ' . $type
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function verifySize(int $expected, int $actual): void
|
||||
{
|
||||
if ($expected !== $actual) {
|
||||
throw new InvalidDatabaseException(
|
||||
"The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function decodeArray(int $size, int $offset): array
|
||||
{
|
||||
$array = [];
|
||||
|
||||
for ($i = 0; $i < $size; ++$i) {
|
||||
[$value, $offset] = $this->decode($offset);
|
||||
$array[] = $value;
|
||||
}
|
||||
|
||||
return [$array, $offset];
|
||||
}
|
||||
|
||||
private function decodeBoolean(int $size): bool
|
||||
{
|
||||
return $size !== 0;
|
||||
}
|
||||
|
||||
private function decodeDouble(string $bytes): float
|
||||
{
|
||||
// This assumes IEEE 754 doubles, but most (all?) modern platforms
|
||||
// use them.
|
||||
[, $double] = unpack('E', $bytes);
|
||||
|
||||
return $double;
|
||||
}
|
||||
|
||||
private function decodeFloat(string $bytes): float
|
||||
{
|
||||
// This assumes IEEE 754 floats, but most (all?) modern platforms
|
||||
// use them.
|
||||
[, $float] = unpack('G', $bytes);
|
||||
|
||||
return $float;
|
||||
}
|
||||
|
||||
private function decodeInt32(string $bytes, int $size): int
|
||||
{
|
||||
switch ($size) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
$bytes = str_pad($bytes, 4, "\x00", \STR_PAD_LEFT);
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDatabaseException(
|
||||
"The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
|
||||
);
|
||||
}
|
||||
|
||||
[, $int] = unpack('l', $this->maybeSwitchByteOrder($bytes));
|
||||
|
||||
return $int;
|
||||
}
|
||||
|
||||
private function decodeMap(int $size, int $offset): array
|
||||
{
|
||||
$map = [];
|
||||
|
||||
for ($i = 0; $i < $size; ++$i) {
|
||||
[$key, $offset] = $this->decode($offset);
|
||||
[$value, $offset] = $this->decode($offset);
|
||||
$map[$key] = $value;
|
||||
}
|
||||
|
||||
return [$map, $offset];
|
||||
}
|
||||
|
||||
private function decodePointer(int $ctrlByte, int $offset): array
|
||||
{
|
||||
$pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
|
||||
|
||||
$buffer = Util::read($this->fileStream, $offset, $pointerSize);
|
||||
$offset = $offset + $pointerSize;
|
||||
|
||||
switch ($pointerSize) {
|
||||
case 1:
|
||||
$packed = \chr($ctrlByte & 0x7) . $buffer;
|
||||
[, $pointer] = unpack('n', $packed);
|
||||
$pointer += $this->pointerBase;
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$packed = "\x00" . \chr($ctrlByte & 0x7) . $buffer;
|
||||
[, $pointer] = unpack('N', $packed);
|
||||
$pointer += $this->pointerBase + 2048;
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$packed = \chr($ctrlByte & 0x7) . $buffer;
|
||||
|
||||
// It is safe to use 'N' here, even on 32 bit machines as the
|
||||
// first bit is 0.
|
||||
[, $pointer] = unpack('N', $packed);
|
||||
$pointer += $this->pointerBase + 526336;
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// We cannot use unpack here as we might overflow on 32 bit
|
||||
// machines
|
||||
$pointerOffset = $this->decodeUint($buffer, $pointerSize);
|
||||
|
||||
$pointerBase = $this->pointerBase;
|
||||
|
||||
if (\PHP_INT_MAX - $pointerBase >= $pointerOffset) {
|
||||
$pointer = $pointerOffset + $pointerBase;
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
'The database offset is too large to be represented on your platform.'
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDatabaseException(
|
||||
'Unexpected pointer size ' . $pointerSize
|
||||
);
|
||||
}
|
||||
|
||||
return [$pointer, $offset];
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
private function decodeUint(string $bytes, int $byteLength)
|
||||
{
|
||||
if ($byteLength === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$integer = 0;
|
||||
|
||||
// PHP integers are signed. PHP_INT_SIZE - 1 is the number of
|
||||
// complete bytes that can be converted to an integer. However,
|
||||
// we can convert another byte if the leading bit is zero.
|
||||
$useRealInts = $byteLength <= \PHP_INT_SIZE - 1
|
||||
|| ($byteLength === \PHP_INT_SIZE && (\ord($bytes[0]) & 0x80) === 0);
|
||||
|
||||
for ($i = 0; $i < $byteLength; ++$i) {
|
||||
$part = \ord($bytes[$i]);
|
||||
|
||||
// We only use gmp or bcmath if the final value is too big
|
||||
if ($useRealInts) {
|
||||
$integer = ($integer << 8) + $part;
|
||||
} elseif (\extension_loaded('gmp')) {
|
||||
$integer = gmp_strval(gmp_add(gmp_mul((string) $integer, '256'), $part));
|
||||
} elseif (\extension_loaded('bcmath')) {
|
||||
$integer = bcadd(bcmul((string) $integer, '256'), (string) $part);
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
'The gmp or bcmath extension must be installed to read this database.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $integer;
|
||||
}
|
||||
|
||||
private function sizeFromCtrlByte(int $ctrlByte, int $offset): array
|
||||
{
|
||||
$size = $ctrlByte & 0x1F;
|
||||
|
||||
if ($size < 29) {
|
||||
return [$size, $offset];
|
||||
}
|
||||
|
||||
$bytesToRead = $size - 28;
|
||||
$bytes = Util::read($this->fileStream, $offset, $bytesToRead);
|
||||
|
||||
if ($size === 29) {
|
||||
$size = 29 + \ord($bytes);
|
||||
} elseif ($size === 30) {
|
||||
[, $adjust] = unpack('n', $bytes);
|
||||
$size = 285 + $adjust;
|
||||
} else {
|
||||
[, $adjust] = unpack('N', "\x00" . $bytes);
|
||||
$size = $adjust + 65821;
|
||||
}
|
||||
|
||||
return [$size, $offset + $bytesToRead];
|
||||
}
|
||||
|
||||
private function maybeSwitchByteOrder(string $bytes): string
|
||||
{
|
||||
return $this->switchByteOrder ? strrev($bytes) : $bytes;
|
||||
}
|
||||
|
||||
private function isPlatformLittleEndian(): bool
|
||||
{
|
||||
$testint = 0x00FF;
|
||||
$packed = pack('S', $testint);
|
||||
|
||||
return $testint === current(unpack('v', $packed));
|
||||
}
|
||||
}
|
14
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php
vendored
Normal file
14
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Db\Reader;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* This class should be thrown when unexpected data is found in the database.
|
||||
*/
|
||||
class InvalidDatabaseException extends Exception
|
||||
{
|
||||
}
|
112
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php
vendored
Normal file
112
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Db\Reader;
|
||||
|
||||
use ArgumentCountError;
|
||||
|
||||
/**
|
||||
* This class provides the metadata for the MaxMind DB file.
|
||||
*/
|
||||
class Metadata
|
||||
{
|
||||
/**
|
||||
* This is an unsigned 16-bit integer indicating the major version number
|
||||
* for the database's binary format.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $binaryFormatMajorVersion;
|
||||
/**
|
||||
* This is an unsigned 16-bit integer indicating the minor version number
|
||||
* for the database's binary format.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $binaryFormatMinorVersion;
|
||||
/**
|
||||
* This is an unsigned 64-bit integer that contains the database build
|
||||
* timestamp as a Unix epoch value.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $buildEpoch;
|
||||
/**
|
||||
* This is a string that indicates the structure of each data record
|
||||
* associated with an IP address. The actual definition of these
|
||||
* structures is left up to the database creator.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $databaseType;
|
||||
/**
|
||||
* This key will always point to a map (associative array). The keys of
|
||||
* that map will be language codes, and the values will be a description
|
||||
* in that language as a UTF-8 string. May be undefined for some
|
||||
* databases.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $description;
|
||||
/**
|
||||
* This is an unsigned 16-bit integer which is always 4 or 6. It indicates
|
||||
* whether the database contains IPv4 or IPv6 address data.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $ipVersion;
|
||||
/**
|
||||
* An array of strings, each of which is a language code. A given record
|
||||
* may contain data items that have been localized to some or all of
|
||||
* these languages. This may be undefined.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $languages;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $nodeByteSize;
|
||||
/**
|
||||
* This is an unsigned 32-bit integer indicating the number of nodes in
|
||||
* the search tree.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $nodeCount;
|
||||
/**
|
||||
* This is an unsigned 16-bit integer. It indicates the number of bits in a
|
||||
* record in the search tree. Note that each node consists of two records.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $recordSize;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $searchTreeSize;
|
||||
|
||||
public function __construct(array $metadata)
|
||||
{
|
||||
if (\func_num_args() !== 1) {
|
||||
throw new ArgumentCountError(
|
||||
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
|
||||
);
|
||||
}
|
||||
|
||||
$this->binaryFormatMajorVersion =
|
||||
$metadata['binary_format_major_version'];
|
||||
$this->binaryFormatMinorVersion =
|
||||
$metadata['binary_format_minor_version'];
|
||||
$this->buildEpoch = $metadata['build_epoch'];
|
||||
$this->databaseType = $metadata['database_type'];
|
||||
$this->languages = $metadata['languages'];
|
||||
$this->description = $metadata['description'];
|
||||
$this->ipVersion = $metadata['ip_version'];
|
||||
$this->nodeCount = $metadata['node_count'];
|
||||
$this->recordSize = $metadata['record_size'];
|
||||
$this->nodeByteSize = $this->recordSize / 4;
|
||||
$this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
|
||||
}
|
||||
}
|
32
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php
vendored
Normal file
32
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Db\Reader;
|
||||
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* @param resource $stream
|
||||
*/
|
||||
public static function read($stream, int $offset, int $numberOfBytes): string
|
||||
{
|
||||
if ($numberOfBytes === 0) {
|
||||
return '';
|
||||
}
|
||||
if (fseek($stream, $offset) === 0) {
|
||||
$value = fread($stream, $numberOfBytes);
|
||||
|
||||
// We check that the number of bytes read is equal to the number
|
||||
// asked for. We use ftell as getting the length of $value is
|
||||
// much slower.
|
||||
if ($value !== false && ftell($stream) - $offset === $numberOfBytes) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidDatabaseException(
|
||||
'The MaxMind DB file contains bad data'
|
||||
);
|
||||
}
|
||||
}
|
25
includes/vendor/maxmind/web-service-common/README.md
vendored
Normal file
25
includes/vendor/maxmind/web-service-common/README.md
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Common Code for MaxMind Web Service Clients #
|
||||
|
||||
This is _not_ intended for direct use by third parties. Rather, it is for
|
||||
shared code between MaxMind's various web service client APIs.
|
||||
|
||||
## Requirements ##
|
||||
|
||||
The library requires PHP 7.2 or greater.
|
||||
|
||||
There are several other dependencies as defined in the `composer.json` file.
|
||||
|
||||
## Contributing ##
|
||||
|
||||
Patches and pull requests are encouraged. All code should follow the PSR-2
|
||||
style guidelines. Please include unit tests whenever possible.
|
||||
|
||||
## Versioning ##
|
||||
|
||||
This API uses [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## Copyright and License ##
|
||||
|
||||
This software is Copyright (c) 2015-2020 by MaxMind, Inc.
|
||||
|
||||
This is free software, licensed under the Apache License, Version 2.0.
|
12
includes/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php
vendored
Normal file
12
includes/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
/**
|
||||
* This class represents an error authenticating.
|
||||
*/
|
||||
class AuthenticationException extends InvalidRequestException
|
||||
{
|
||||
}
|
44
includes/vendor/maxmind/web-service-common/src/Exception/HttpException.php
vendored
Normal file
44
includes/vendor/maxmind/web-service-common/src/Exception/HttpException.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
/**
|
||||
* This class represents an HTTP transport error.
|
||||
*/
|
||||
class HttpException extends WebServiceException
|
||||
{
|
||||
/**
|
||||
* The URI queried.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $uri;
|
||||
|
||||
/**
|
||||
* @param string $message a message describing the error
|
||||
* @param int $httpStatus the HTTP status code of the response
|
||||
* @param string $uri the URI used in the request
|
||||
* @param \Exception $previous the previous exception, if any
|
||||
*/
|
||||
public function __construct(
|
||||
string $message,
|
||||
int $httpStatus,
|
||||
string $uri,
|
||||
\Exception $previous = null
|
||||
) {
|
||||
$this->uri = $uri;
|
||||
parent::__construct($message, $httpStatus, $previous);
|
||||
}
|
||||
|
||||
public function getUri(): string
|
||||
{
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
return $this->getCode();
|
||||
}
|
||||
}
|
12
includes/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php
vendored
Normal file
12
includes/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when the account is out of credits.
|
||||
*/
|
||||
class InsufficientFundsException extends InvalidRequestException
|
||||
{
|
||||
}
|
14
includes/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php
vendored
Normal file
14
includes/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
/**
|
||||
* This class represents an error in creating the request to be sent to the
|
||||
* web service. For example, if the array cannot be encoded as JSON or if there
|
||||
* is a missing or invalid field.
|
||||
*/
|
||||
class InvalidInputException extends WebServiceException
|
||||
{
|
||||
}
|
41
includes/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php
vendored
Normal file
41
includes/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when a MaxMind web service returns an error relating to the request.
|
||||
*/
|
||||
class InvalidRequestException extends HttpException
|
||||
{
|
||||
/**
|
||||
* The code returned by the MaxMind web service.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* @param string $message the exception message
|
||||
* @param string $error the error code returned by the MaxMind web service
|
||||
* @param int $httpStatus the HTTP status code of the response
|
||||
* @param string $uri the URI queries
|
||||
* @param \Exception $previous the previous exception, if any
|
||||
*/
|
||||
public function __construct(
|
||||
string $message,
|
||||
string $error,
|
||||
int $httpStatus,
|
||||
string $uri,
|
||||
\Exception $previous = null
|
||||
) {
|
||||
$this->error = $error;
|
||||
parent::__construct($message, $httpStatus, $uri, $previous);
|
||||
}
|
||||
|
||||
public function getErrorCode(): string
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
}
|
9
includes/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php
vendored
Normal file
9
includes/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
class IpAddressNotFoundException extends InvalidRequestException
|
||||
{
|
||||
}
|
12
includes/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php
vendored
Normal file
12
includes/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
/**
|
||||
* This exception is thrown when the service requires permission to access.
|
||||
*/
|
||||
class PermissionRequiredException extends InvalidRequestException
|
||||
{
|
||||
}
|
12
includes/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php
vendored
Normal file
12
includes/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\Exception;
|
||||
|
||||
/**
|
||||
* This class represents a generic web service error.
|
||||
*/
|
||||
class WebServiceException extends \Exception
|
||||
{
|
||||
}
|
546
includes/vendor/maxmind/web-service-common/src/WebService/Client.php
vendored
Normal file
546
includes/vendor/maxmind/web-service-common/src/WebService/Client.php
vendored
Normal file
@ -0,0 +1,546 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\WebService;
|
||||
|
||||
use Composer\CaBundle\CaBundle;
|
||||
use MaxMind\Exception\AuthenticationException;
|
||||
use MaxMind\Exception\HttpException;
|
||||
use MaxMind\Exception\InsufficientFundsException;
|
||||
use MaxMind\Exception\InvalidInputException;
|
||||
use MaxMind\Exception\InvalidRequestException;
|
||||
use MaxMind\Exception\IpAddressNotFoundException;
|
||||
use MaxMind\Exception\PermissionRequiredException;
|
||||
use MaxMind\Exception\WebServiceException;
|
||||
use MaxMind\WebService\Http\RequestFactory;
|
||||
|
||||
/**
|
||||
* This class is not intended to be used directly by an end-user of a
|
||||
* MaxMind web service. Please use the appropriate client API for the service
|
||||
* that you are using.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
public const VERSION = '0.2.0';
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $caBundle;
|
||||
|
||||
/**
|
||||
* @var float|null
|
||||
*/
|
||||
private $connectTimeout;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $host = 'api.maxmind.com';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $useHttps = true;
|
||||
|
||||
/**
|
||||
* @var RequestFactory
|
||||
*/
|
||||
private $httpRequestFactory;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $licenseKey;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $proxy;
|
||||
|
||||
/**
|
||||
* @var float|null
|
||||
*/
|
||||
private $timeout;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $userAgentPrefix;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $accountId;
|
||||
|
||||
/**
|
||||
* @param int $accountId your MaxMind account ID
|
||||
* @param string $licenseKey your MaxMind license key
|
||||
* @param array $options an array of options. Possible keys:
|
||||
* * `host` - The host to use when connecting to the web service.
|
||||
* * `useHttps` - A boolean flag for sending the request via https.(True by default)
|
||||
* * `userAgent` - The prefix of the User-Agent to use in the request.
|
||||
* * `caBundle` - The bundle of CA root certificates to use in the request.
|
||||
* * `connectTimeout` - The connect timeout to use for the request.
|
||||
* * `timeout` - The timeout to use for the request.
|
||||
* * `proxy` - The HTTP proxy to use. May include a schema, port,
|
||||
* username, and password, e.g., `http://username:password@127.0.0.1:10`.
|
||||
*/
|
||||
public function __construct(
|
||||
int $accountId,
|
||||
string $licenseKey,
|
||||
array $options = []
|
||||
) {
|
||||
$this->accountId = $accountId;
|
||||
$this->licenseKey = $licenseKey;
|
||||
|
||||
$this->httpRequestFactory = isset($options['httpRequestFactory'])
|
||||
? $options['httpRequestFactory']
|
||||
: new RequestFactory();
|
||||
|
||||
if (isset($options['host'])) {
|
||||
$this->host = $options['host'];
|
||||
}
|
||||
if (isset($options['useHttps'])) {
|
||||
$this->useHttps = $options['useHttps'];
|
||||
}
|
||||
if (isset($options['userAgent'])) {
|
||||
$this->userAgentPrefix = $options['userAgent'] . ' ';
|
||||
}
|
||||
|
||||
$this->caBundle = isset($options['caBundle']) ?
|
||||
$this->caBundle = $options['caBundle'] : $this->getCaBundle();
|
||||
|
||||
if (isset($options['connectTimeout'])) {
|
||||
$this->connectTimeout = $options['connectTimeout'];
|
||||
}
|
||||
if (isset($options['timeout'])) {
|
||||
$this->timeout = $options['timeout'];
|
||||
}
|
||||
|
||||
if (isset($options['proxy'])) {
|
||||
$this->proxy = $options['proxy'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $service name of the service querying
|
||||
* @param string $path the URI path to use
|
||||
* @param array $input the data to be posted as JSON
|
||||
*
|
||||
* @throws InvalidInputException when the request has missing or invalid
|
||||
* data
|
||||
* @throws AuthenticationException when there is an issue authenticating the
|
||||
* request
|
||||
* @throws InsufficientFundsException when your account is out of funds
|
||||
* @throws InvalidRequestException when the request is invalid for some
|
||||
* other reason, e.g., invalid JSON in the POST.
|
||||
* @throws HttpException when an unexpected HTTP error occurs
|
||||
* @throws WebServiceException when some other error occurs. This also
|
||||
* serves as the base class for the above exceptions.
|
||||
*
|
||||
* @return array|null The decoded content of a successful response
|
||||
*/
|
||||
public function post(string $service, string $path, array $input): ?array
|
||||
{
|
||||
$requestBody = json_encode($input);
|
||||
if ($requestBody === false) {
|
||||
throw new InvalidInputException(
|
||||
'Error encoding input as JSON: '
|
||||
. $this->jsonErrorDescription()
|
||||
);
|
||||
}
|
||||
|
||||
$request = $this->createRequest(
|
||||
$path,
|
||||
['Content-Type: application/json']
|
||||
);
|
||||
|
||||
[$statusCode, $contentType, $responseBody] = $request->post($requestBody);
|
||||
|
||||
return $this->handleResponse(
|
||||
$statusCode,
|
||||
$contentType,
|
||||
$responseBody,
|
||||
$service,
|
||||
$path
|
||||
);
|
||||
}
|
||||
|
||||
public function get(string $service, string $path): ?array
|
||||
{
|
||||
$request = $this->createRequest(
|
||||
$path
|
||||
);
|
||||
|
||||
[$statusCode, $contentType, $responseBody] = $request->get();
|
||||
|
||||
return $this->handleResponse(
|
||||
$statusCode,
|
||||
$contentType,
|
||||
$responseBody,
|
||||
$service,
|
||||
$path
|
||||
);
|
||||
}
|
||||
|
||||
private function userAgent(): string
|
||||
{
|
||||
$curlVersion = curl_version();
|
||||
|
||||
return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . \PHP_VERSION .
|
||||
' curl/' . $curlVersion['version'];
|
||||
}
|
||||
|
||||
private function createRequest(string $path, array $headers = []): Http\Request
|
||||
{
|
||||
array_push(
|
||||
$headers,
|
||||
'Authorization: Basic '
|
||||
. base64_encode($this->accountId . ':' . $this->licenseKey),
|
||||
'Accept: application/json'
|
||||
);
|
||||
|
||||
return $this->httpRequestFactory->request(
|
||||
$this->urlFor($path),
|
||||
[
|
||||
'caBundle' => $this->caBundle,
|
||||
'connectTimeout' => $this->connectTimeout,
|
||||
'headers' => $headers,
|
||||
'proxy' => $this->proxy,
|
||||
'timeout' => $this->timeout,
|
||||
'userAgent' => $this->userAgent(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $statusCode the HTTP status code of the response
|
||||
* @param string|null $contentType the Content-Type of the response
|
||||
* @param string|null $responseBody the response body
|
||||
* @param string $service the name of the service
|
||||
* @param string $path the path used in the request
|
||||
*
|
||||
* @throws AuthenticationException when there is an issue authenticating the
|
||||
* request
|
||||
* @throws InsufficientFundsException when your account is out of funds
|
||||
* @throws InvalidRequestException when the request is invalid for some
|
||||
* other reason, e.g., invalid JSON in the POST.
|
||||
* @throws HttpException when an unexpected HTTP error occurs
|
||||
* @throws WebServiceException when some other error occurs. This also
|
||||
* serves as the base class for the above exceptions
|
||||
*
|
||||
* @return array|null The decoded content of a successful response
|
||||
*/
|
||||
private function handleResponse(
|
||||
int $statusCode,
|
||||
?string $contentType,
|
||||
?string $responseBody,
|
||||
string $service,
|
||||
string $path
|
||||
): ?array {
|
||||
if ($statusCode >= 400 && $statusCode <= 499) {
|
||||
$this->handle4xx($statusCode, $contentType, $responseBody, $service, $path);
|
||||
} elseif ($statusCode >= 500) {
|
||||
$this->handle5xx($statusCode, $service, $path);
|
||||
} elseif ($statusCode !== 200 && $statusCode !== 204) {
|
||||
$this->handleUnexpectedStatus($statusCode, $service, $path);
|
||||
}
|
||||
|
||||
return $this->handleSuccess($statusCode, $responseBody, $service);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string describing the JSON error
|
||||
*/
|
||||
private function jsonErrorDescription(): string
|
||||
{
|
||||
$errno = json_last_error();
|
||||
|
||||
switch ($errno) {
|
||||
case \JSON_ERROR_DEPTH:
|
||||
return 'The maximum stack depth has been exceeded.';
|
||||
|
||||
case \JSON_ERROR_STATE_MISMATCH:
|
||||
return 'Invalid or malformed JSON.';
|
||||
|
||||
case \JSON_ERROR_CTRL_CHAR:
|
||||
return 'Control character error.';
|
||||
|
||||
case \JSON_ERROR_SYNTAX:
|
||||
return 'Syntax error.';
|
||||
|
||||
case \JSON_ERROR_UTF8:
|
||||
return 'Malformed UTF-8 characters.';
|
||||
|
||||
default:
|
||||
return "Other JSON error ($errno).";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path the path to use in the URL
|
||||
*
|
||||
* @return string the constructed URL
|
||||
*/
|
||||
private function urlFor(string $path): string
|
||||
{
|
||||
return ($this->useHttps ? 'https://' : 'http://') . $this->host . $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $statusCode the HTTP status code
|
||||
* @param string|null $contentType the response content-type
|
||||
* @param string|null $body the response body
|
||||
* @param string $service the service name
|
||||
* @param string $path the path used in the request
|
||||
*
|
||||
* @throws AuthenticationException
|
||||
* @throws HttpException
|
||||
* @throws InsufficientFundsException
|
||||
* @throws InvalidRequestException
|
||||
*/
|
||||
private function handle4xx(
|
||||
int $statusCode,
|
||||
?string $contentType,
|
||||
?string $body,
|
||||
string $service,
|
||||
string $path
|
||||
): void {
|
||||
if ($body === null || $body === '') {
|
||||
throw new HttpException(
|
||||
"Received a $statusCode error for $service with no body",
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
}
|
||||
if ($contentType === null || !strstr($contentType, 'json')) {
|
||||
throw new HttpException(
|
||||
"Received a $statusCode error for $service with " .
|
||||
'the following body: ' . $body,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
}
|
||||
|
||||
$message = json_decode($body, true);
|
||||
if ($message === null) {
|
||||
throw new HttpException(
|
||||
"Received a $statusCode error for $service but could " .
|
||||
'not decode the response as JSON: '
|
||||
. $this->jsonErrorDescription() . ' Body: ' . $body,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
}
|
||||
|
||||
if (!isset($message['code']) || !isset($message['error'])) {
|
||||
throw new HttpException(
|
||||
'Error response contains JSON but it does not ' .
|
||||
'specify code or error keys: ' . $body,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
}
|
||||
|
||||
$this->handleWebServiceError(
|
||||
$message['error'],
|
||||
$message['code'],
|
||||
$statusCode,
|
||||
$path
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message the error message from the web service
|
||||
* @param string $code the error code from the web service
|
||||
* @param int $statusCode the HTTP status code
|
||||
* @param string $path the path used in the request
|
||||
*
|
||||
* @throws AuthenticationException
|
||||
* @throws InvalidRequestException
|
||||
* @throws InsufficientFundsException
|
||||
*/
|
||||
private function handleWebServiceError(
|
||||
string $message,
|
||||
string $code,
|
||||
int $statusCode,
|
||||
string $path
|
||||
): void {
|
||||
switch ($code) {
|
||||
case 'IP_ADDRESS_NOT_FOUND':
|
||||
case 'IP_ADDRESS_RESERVED':
|
||||
throw new IpAddressNotFoundException(
|
||||
$message,
|
||||
$code,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
|
||||
case 'ACCOUNT_ID_REQUIRED':
|
||||
case 'ACCOUNT_ID_UNKNOWN':
|
||||
case 'AUTHORIZATION_INVALID':
|
||||
case 'LICENSE_KEY_REQUIRED':
|
||||
case 'USER_ID_REQUIRED':
|
||||
case 'USER_ID_UNKNOWN':
|
||||
throw new AuthenticationException(
|
||||
$message,
|
||||
$code,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
|
||||
case 'OUT_OF_QUERIES':
|
||||
case 'INSUFFICIENT_FUNDS':
|
||||
throw new InsufficientFundsException(
|
||||
$message,
|
||||
$code,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
|
||||
case 'PERMISSION_REQUIRED':
|
||||
throw new PermissionRequiredException(
|
||||
$message,
|
||||
$code,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
|
||||
default:
|
||||
throw new InvalidRequestException(
|
||||
$message,
|
||||
$code,
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $statusCode the HTTP status code
|
||||
* @param string $service the service name
|
||||
* @param string $path the URI path used in the request
|
||||
*
|
||||
* @throws HttpException
|
||||
*/
|
||||
private function handle5xx(int $statusCode, string $service, string $path): void
|
||||
{
|
||||
throw new HttpException(
|
||||
"Received a server error ($statusCode) for $service",
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $statusCode the HTTP status code
|
||||
* @param string $service the service name
|
||||
* @param string $path the URI path used in the request
|
||||
*
|
||||
* @throws HttpException
|
||||
*/
|
||||
private function handleUnexpectedStatus(int $statusCode, string $service, string $path): void
|
||||
{
|
||||
throw new HttpException(
|
||||
'Received an unexpected HTTP status ' .
|
||||
"($statusCode) for $service",
|
||||
$statusCode,
|
||||
$this->urlFor($path)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $statusCode the HTTP status code
|
||||
* @param string|null $body the successful request body
|
||||
* @param string $service the service name
|
||||
*
|
||||
* @throws WebServiceException if a response body is included but not
|
||||
* expected, or is not expected but not
|
||||
* included, or is expected and included
|
||||
* but cannot be decoded as JSON
|
||||
*
|
||||
* @return array|null the decoded request body
|
||||
*/
|
||||
private function handleSuccess(int $statusCode, ?string $body, string $service): ?array
|
||||
{
|
||||
// A 204 should have no response body
|
||||
if ($statusCode === 204) {
|
||||
if ($body !== null && $body !== '') {
|
||||
throw new WebServiceException(
|
||||
"Received a 204 response for $service along with an " .
|
||||
"unexpected HTTP body: $body"
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// A 200 should have a valid JSON body
|
||||
if ($body === null || $body === '') {
|
||||
throw new WebServiceException(
|
||||
"Received a 200 response for $service but did not " .
|
||||
'receive a HTTP body.'
|
||||
);
|
||||
}
|
||||
|
||||
$decodedContent = json_decode($body, true);
|
||||
if ($decodedContent === null) {
|
||||
throw new WebServiceException(
|
||||
"Received a 200 response for $service but could " .
|
||||
'not decode the response as JSON: '
|
||||
. $this->jsonErrorDescription() . ' Body: ' . $body
|
||||
);
|
||||
}
|
||||
|
||||
return $decodedContent;
|
||||
}
|
||||
|
||||
private function getCaBundle(): ?string
|
||||
{
|
||||
$curlVersion = curl_version();
|
||||
|
||||
// On OS X, when the SSL version is "SecureTransport", the system's
|
||||
// keychain will be used.
|
||||
if ($curlVersion['ssl_version'] === 'SecureTransport') {
|
||||
return null;
|
||||
}
|
||||
$cert = CaBundle::getSystemCaRootBundlePath();
|
||||
|
||||
// Check if the cert is inside a phar. If so, we need to copy the cert
|
||||
// to a temp file so that curl can see it.
|
||||
if (substr($cert, 0, 7) === 'phar://') {
|
||||
$tempDir = sys_get_temp_dir();
|
||||
$newCert = tempnam($tempDir, 'geoip2-');
|
||||
if ($newCert === false) {
|
||||
throw new \RuntimeException(
|
||||
"Unable to create temporary file in $tempDir"
|
||||
);
|
||||
}
|
||||
if (!copy($cert, $newCert)) {
|
||||
throw new \RuntimeException(
|
||||
"Could not copy $cert to $newCert: "
|
||||
. var_export(error_get_last(), true)
|
||||
);
|
||||
}
|
||||
|
||||
// We use a shutdown function rather than the destructor as the
|
||||
// destructor isn't called on a fatal error such as an uncaught
|
||||
// exception.
|
||||
register_shutdown_function(
|
||||
function () use ($newCert) {
|
||||
unlink($newCert);
|
||||
}
|
||||
);
|
||||
$cert = $newCert;
|
||||
}
|
||||
if (!file_exists($cert)) {
|
||||
throw new \RuntimeException("CA cert does not exist at $cert");
|
||||
}
|
||||
|
||||
return $cert;
|
||||
}
|
||||
}
|
136
includes/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php
vendored
Normal file
136
includes/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\WebService\Http;
|
||||
|
||||
use MaxMind\Exception\HttpException;
|
||||
|
||||
/**
|
||||
* This class is for internal use only. Semantic versioning does not not apply.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class CurlRequest implements Request
|
||||
{
|
||||
/**
|
||||
* @var \CurlHandle
|
||||
*/
|
||||
private $ch;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $url;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $options;
|
||||
|
||||
public function __construct(string $url, array $options)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->options = $options;
|
||||
$this->ch = $options['curlHandle'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws HttpException
|
||||
*/
|
||||
public function post(string $body): array
|
||||
{
|
||||
$curl = $this->createCurl();
|
||||
|
||||
curl_setopt($curl, \CURLOPT_POST, true);
|
||||
curl_setopt($curl, \CURLOPT_POSTFIELDS, $body);
|
||||
|
||||
return $this->execute($curl);
|
||||
}
|
||||
|
||||
public function get(): array
|
||||
{
|
||||
$curl = $this->createCurl();
|
||||
|
||||
curl_setopt($curl, \CURLOPT_HTTPGET, true);
|
||||
|
||||
return $this->execute($curl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \CurlHandle
|
||||
*/
|
||||
private function createCurl()
|
||||
{
|
||||
curl_reset($this->ch);
|
||||
|
||||
$opts = [];
|
||||
$opts[\CURLOPT_URL] = $this->url;
|
||||
|
||||
if (!empty($this->options['caBundle'])) {
|
||||
$opts[\CURLOPT_CAINFO] = $this->options['caBundle'];
|
||||
}
|
||||
|
||||
$opts[\CURLOPT_ENCODING] = '';
|
||||
$opts[\CURLOPT_SSL_VERIFYHOST] = 2;
|
||||
$opts[\CURLOPT_FOLLOWLOCATION] = false;
|
||||
$opts[\CURLOPT_SSL_VERIFYPEER] = true;
|
||||
$opts[\CURLOPT_RETURNTRANSFER] = true;
|
||||
|
||||
$opts[\CURLOPT_HTTPHEADER] = $this->options['headers'];
|
||||
$opts[\CURLOPT_USERAGENT] = $this->options['userAgent'];
|
||||
$opts[\CURLOPT_PROXY] = $this->options['proxy'];
|
||||
|
||||
// The defined()s are here as the *_MS opts are not available on older
|
||||
// cURL versions
|
||||
$connectTimeout = $this->options['connectTimeout'];
|
||||
if (\defined('CURLOPT_CONNECTTIMEOUT_MS')) {
|
||||
$opts[\CURLOPT_CONNECTTIMEOUT_MS] = ceil($connectTimeout * 1000);
|
||||
} else {
|
||||
$opts[\CURLOPT_CONNECTTIMEOUT] = ceil($connectTimeout);
|
||||
}
|
||||
|
||||
$timeout = $this->options['timeout'];
|
||||
if (\defined('CURLOPT_TIMEOUT_MS')) {
|
||||
$opts[\CURLOPT_TIMEOUT_MS] = ceil($timeout * 1000);
|
||||
} else {
|
||||
$opts[\CURLOPT_TIMEOUT] = ceil($timeout);
|
||||
}
|
||||
|
||||
curl_setopt_array($this->ch, $opts);
|
||||
|
||||
return $this->ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \CurlHandle $curl
|
||||
*
|
||||
* @throws HttpException
|
||||
*/
|
||||
private function execute($curl): array
|
||||
{
|
||||
$body = curl_exec($curl);
|
||||
if ($errno = curl_errno($curl)) {
|
||||
$errorMessage = curl_error($curl);
|
||||
|
||||
throw new HttpException(
|
||||
"cURL error ({$errno}): {$errorMessage}",
|
||||
0,
|
||||
$this->url
|
||||
);
|
||||
}
|
||||
|
||||
$statusCode = curl_getinfo($curl, \CURLINFO_HTTP_CODE);
|
||||
$contentType = curl_getinfo($curl, \CURLINFO_CONTENT_TYPE);
|
||||
|
||||
return [
|
||||
$statusCode,
|
||||
// The PHP docs say "Content-Type: of the requested document. NULL
|
||||
// indicates server did not send valid Content-Type: header" for
|
||||
// CURLINFO_CONTENT_TYPE. However, it will return FALSE if no header
|
||||
// is set. To keep our types simple, we return null in this case.
|
||||
($contentType === false ? null : $contentType),
|
||||
$body,
|
||||
];
|
||||
}
|
||||
}
|
19
includes/vendor/maxmind/web-service-common/src/WebService/Http/Request.php
vendored
Normal file
19
includes/vendor/maxmind/web-service-common/src/WebService/Http/Request.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\WebService\Http;
|
||||
|
||||
/**
|
||||
* Interface Request.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface Request
|
||||
{
|
||||
public function __construct(string $url, array $options);
|
||||
|
||||
public function post(string $body): array;
|
||||
|
||||
public function get(): array;
|
||||
}
|
48
includes/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php
vendored
Normal file
48
includes/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MaxMind\WebService\Http;
|
||||
|
||||
/**
|
||||
* Class RequestFactory.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class RequestFactory
|
||||
{
|
||||
/**
|
||||
* Keep the cURL resource here, so that if there are multiple API requests
|
||||
* done the connection is kept alive, SSL resumption can be used
|
||||
* etcetera.
|
||||
*
|
||||
* @var \CurlHandle|null
|
||||
*/
|
||||
private $ch;
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (!empty($this->ch)) {
|
||||
curl_close($this->ch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \CurlHandle
|
||||
*/
|
||||
private function getCurlHandle()
|
||||
{
|
||||
if (empty($this->ch)) {
|
||||
$this->ch = curl_init();
|
||||
}
|
||||
|
||||
return $this->ch;
|
||||
}
|
||||
|
||||
public function request(string $url, array $options): Request
|
||||
{
|
||||
$options['curlHandle'] = $this->getCurlHandle();
|
||||
|
||||
return new CurlRequest($url, $options);
|
||||
}
|
||||
}
|
74
includes/vendor/ozh/bookmarkletgen/README.md
vendored
Normal file
74
includes/vendor/ozh/bookmarkletgen/README.md
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
# Bookmarklet Gen [](https://travis-ci.org/ozh/bookmarkletgen)
|
||||
|
||||
Convert readable Javascript code into bookmarklet links
|
||||
|
||||
## Features
|
||||
|
||||
- removes comments
|
||||
|
||||
- compresses code by removing extraneous spaces, but not within literal strings.
|
||||
Example:
|
||||
```javascript
|
||||
function someName( param ) {
|
||||
alert( "this is a string" )
|
||||
}
|
||||
```
|
||||
will return:
|
||||
```javascript
|
||||
function%20someName(param){alert("this%20is%20a%20string")}
|
||||
```
|
||||
- encodes what needs to be encoded
|
||||
|
||||
- wraps code into a self invoking function ready for bookmarking
|
||||
|
||||
This is basically a slightly enhanced PHP port of the excellent Bookmarklet Crunchinator:
|
||||
http://ted.mielczarek.org/code/mozilla/bookmarklet.html
|
||||
|
||||
## Installation
|
||||
|
||||
If you are using Composer, add this requirement to your `composer.json` file and run `composer install`:
|
||||
|
||||
{
|
||||
"require": {
|
||||
"ozh/phpass": "1.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
Or simply in the command line : `composer install ozh/bookmarkletgen`
|
||||
|
||||
If you're not using composer, download the class file and include it manually.
|
||||
|
||||
## Example
|
||||
|
||||
```php
|
||||
<?php
|
||||
$javascript = <<<CODE
|
||||
var link="http://google.com/"; // destination
|
||||
window.location = link;
|
||||
CODE;
|
||||
|
||||
require 'vendor/autoload.php'; // if you install using Composer
|
||||
require 'path/to/Bookmarkletgen.php'; // otherwise
|
||||
|
||||
$book = new \Ozh\Bookmarkletgen\Bookmarkletgen;
|
||||
$link = $book->crunch( $javascript );
|
||||
|
||||
printf( '<a href="%s">bookmarklet</a>', $link );
|
||||
```
|
||||
|
||||
will print:
|
||||
|
||||
```html
|
||||
<a href="javascript:(function()%7Bvar%20link%3D%22http%3A%2F%2Fgoogle.com%2F%22%3Bwindow.location%3Dlink%3B%7D)()%3B">bookmarklet</a>
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
This library comes with unit tests to make sure the resulting crunched Javascript is valid code.
|
||||
|
||||
This library requires PHP 5.3. Tests are failing on HHVM because of an external binary issue (`phantomjs`) but things should work anyway on HHVM too.
|
||||
|
||||
## License
|
||||
|
||||
Do whatever the hell you want to do with it
|
||||
|
197
includes/vendor/ozh/bookmarkletgen/src/Ozh/Bookmarkletgen/Bookmarkletgen.php
vendored
Normal file
197
includes/vendor/ozh/bookmarkletgen/src/Ozh/Bookmarkletgen/Bookmarkletgen.php
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* BookmarkletGen : converts readable Javascript code into a bookmarklet link
|
||||
*
|
||||
* Features :
|
||||
* - removes comments
|
||||
* - compresses code, not literal strings
|
||||
* Example:
|
||||
* function someName( param ) { alert( "this is a string" ) }
|
||||
* will return:
|
||||
* function%20someName(param){alert("this is a string")}
|
||||
* - wraps code into a self invoking function
|
||||
*
|
||||
* This is basically a slightly enhanced PHP port of the excellent Bookmarklet Crunchinator
|
||||
* http://ted.mielczarek.org/code/mozilla/bookmarklet.html
|
||||
*
|
||||
*/
|
||||
namespace Ozh\Bookmarkletgen;
|
||||
|
||||
class Bookmarkletgen {
|
||||
|
||||
private $literal_strings = array();
|
||||
|
||||
/**
|
||||
* Main function, calls all others
|
||||
*
|
||||
* @param string $code Javascript code to bookmarkletify
|
||||
* @return string Bookmarklet link
|
||||
*/
|
||||
public function crunch( $code ) {
|
||||
$out = "(function() {\n" . $code . "\n})();";
|
||||
|
||||
$out = $this->replace_strings( $out );
|
||||
$out = $this->kill_comments( $out );
|
||||
$out = $this->compress_white_space( $out );
|
||||
$out = $this->combine_strings( $out );
|
||||
$out = $this->restore_strings( $out );
|
||||
$out = $this->encodeURIComponent( $out );
|
||||
$out = 'javascript:' . $out;
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP port of Javascript function encodeURIComponent
|
||||
*
|
||||
* From http://stackoverflow.com/a/1734255/36850
|
||||
*
|
||||
* @since
|
||||
* @param string $str String to encode
|
||||
* @return string Encoded string
|
||||
*/
|
||||
//
|
||||
private function encodeURIComponent( $str ) {
|
||||
$revert = array(
|
||||
'%21'=>'!', '%2A'=>'*', '%28'=>'(', '%29'=>')',
|
||||
);
|
||||
|
||||
return strtr( rawurlencode( $str ), $revert );
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill comment lines and blocks
|
||||
*
|
||||
* @param string $code Commented Javascript code
|
||||
* @return string Commentless code
|
||||
*/
|
||||
private function kill_comments( $code ) {
|
||||
$code = preg_replace( '!\s*//.+$!m', '', $code );
|
||||
$code = preg_replace( '!/\*.+?\*/!sm', '', $code ); // s modifier: dot matches new lines
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress white space
|
||||
*
|
||||
* Remove some extraneous spaces and make the whole script a one liner
|
||||
*
|
||||
* @param string $code Javascript code
|
||||
* @return string Compressed code
|
||||
*/
|
||||
private function compress_white_space( $code ) {
|
||||
// Tabs to space, no more than 1 consecutive space
|
||||
$code = preg_replace( '!\t!m', ' ', $code );
|
||||
$code = preg_replace( '![ ]{2,}!m', ' ', $code );
|
||||
|
||||
// Remove uneccessary white space around operators, braces and brackets.
|
||||
// \xHH sequence is: !%&()*+,-/:;<=>?[]\{|}~
|
||||
$code = preg_replace( '/\s([\x21\x25\x26\x28\x29\x2a\x2b\x2c\x2d\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x5b\x5d\x5c\x7b\x7c\x7d\x7e])/m', "$1", $code );
|
||||
$code = preg_replace( '/([\x21\x25\x26\x28\x29\x2a\x2b\x2c\x2d\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x5b\x5d\x5c\x7b\x7c\x7d\x7e])\s/m', "$1", $code );
|
||||
|
||||
// Split on each line, trim leading/trailing white space, kill empty lines, combine everything in one line
|
||||
$code = preg_split( '/\r\n|\r|\n/', $code );
|
||||
foreach( $code as $i => $line ) {
|
||||
$code[ $i ] = trim( $line );
|
||||
}
|
||||
$code = implode( '', $code );
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine any consecutive strings
|
||||
*
|
||||
* In the case we have two consecutive quoted strings (eg: "hello" + "world"), save a couple more
|
||||
* length and combine them
|
||||
*
|
||||
* @param string $code Javascript code
|
||||
* @return string Javascript code
|
||||
*/
|
||||
private function combine_strings( $code ) {
|
||||
$code = preg_replace('/"\+"/m', "", $code);
|
||||
$code = preg_replace("/'\+'/m", "", $code);
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace all literal strings (eg: "hello world") with a placeholder and collect them in an array
|
||||
*
|
||||
* The idea is that strings cannot be trimmed or white-space optimized: take them out first before uglifying
|
||||
* the code, then we'll reinject them back in later
|
||||
*
|
||||
* @param string $code Javascript code
|
||||
* @return string Javascript code with placeholders (eg "__1__") instead of literal strings
|
||||
*/
|
||||
private function replace_strings( $code ) {
|
||||
$return = "";
|
||||
$literal = "";
|
||||
$quoteChar = "";
|
||||
$escaped = false;
|
||||
|
||||
// Split script into individual lines.
|
||||
$lines = explode("\n", $code);
|
||||
$count = count( $lines );
|
||||
for( $i = 0; $i < $count; $i++ ) {
|
||||
|
||||
$j = 0;
|
||||
$inQuote = false;
|
||||
while ($j < strlen( $lines[$i] ) ) {
|
||||
$c = $lines[ $i ][ $j ];
|
||||
|
||||
// If not already in a string, look for the start of one.
|
||||
if (!$inQuote) {
|
||||
if ($c == '"' || $c == "'") {
|
||||
$inQuote = true;
|
||||
$escaped = false;
|
||||
$quoteChar = $c;
|
||||
$literal = $c;
|
||||
}
|
||||
else {
|
||||
$return .= $c;
|
||||
}
|
||||
}
|
||||
|
||||
// Already in a string, look for end and copy characters.
|
||||
else {
|
||||
if ($c == $quoteChar && !$escaped) {
|
||||
$inQuote = false;
|
||||
$literal .= $quoteChar;
|
||||
$return .= "__" . count( $this->literal_strings ) . "__";
|
||||
$this->literal_strings[ count( $this->literal_strings ) ] = $literal;
|
||||
}
|
||||
else if ($c == "\\" && !$escaped) {
|
||||
$escaped = true;
|
||||
}
|
||||
else {
|
||||
$escaped = false;
|
||||
}
|
||||
$literal .= $c;
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
$return .= "\n";
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore literal strings by replacing their placeholders with actual strings
|
||||
*
|
||||
* @param string $code Javascript code with placeholders
|
||||
* @return string Javascript code with actual strings
|
||||
*/
|
||||
private function restore_strings( $code ) {
|
||||
foreach( $this->literal_strings as $i => $string ) {
|
||||
$code = preg_replace( '/__' . $i . '__/', $string, $code, 1 );
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
}
|
52
includes/vendor/pomo/pomo/README.md
vendored
Normal file
52
includes/vendor/pomo/pomo/README.md
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
POMO
|
||||
====
|
||||
[](https://packagist.org/packages/pomo/pomo)
|
||||
[](https://travis-ci.org/LeoColomb/pomo)
|
||||
[](https://codeclimate.com/github/LeoColomb/pomo)
|
||||
|
||||
**Gettext library to translate with I18n**.
|
||||
[Why use it](http://codex.wordpress.org/I18n_for_WordPress_Developers).
|
||||
|
||||
Usage
|
||||
-----
|
||||
```php
|
||||
<?php
|
||||
use POMO\MO;
|
||||
|
||||
// Create MO object
|
||||
$translations = new MO();
|
||||
|
||||
// Import MO file
|
||||
$translations->import_from_file($the_mo_filepath);
|
||||
|
||||
// Translate
|
||||
$translations->translate($text);
|
||||
```
|
||||
|
||||
Installation
|
||||
------------
|
||||
The easiest way to install POMO is via [composer](http://getcomposer.org/).
|
||||
Create the following `composer.json` file and run the `php composer.phar install` command to install it.
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"pomo/pomo": "*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
<?php
|
||||
require 'vendor/autoload.php';
|
||||
use POMO\MO;
|
||||
...
|
||||
```
|
||||
|
||||
Requirements
|
||||
------------
|
||||
POMO works with PHP 5.3 or above.
|
||||
|
||||
License
|
||||
-------
|
||||
POMO is licensed under the [GPLv2 License](LICENSE).
|
385
includes/vendor/pomo/pomo/src/MO.php
vendored
Normal file
385
includes/vendor/pomo/pomo/src/MO.php
vendored
Normal file
@ -0,0 +1,385 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of the POMO package.
|
||||
*
|
||||
* @copyright 2014 POMO
|
||||
* @license GPL
|
||||
*/
|
||||
|
||||
namespace POMO;
|
||||
|
||||
use POMO\Streams\FileReader;
|
||||
use POMO\Streams\NOOPReader;
|
||||
use POMO\Translations\EntryTranslations;
|
||||
use POMO\Translations\GettextTranslations;
|
||||
|
||||
/**
|
||||
* Class for working with MO files.
|
||||
*/
|
||||
class MO extends GettextTranslations
|
||||
{
|
||||
public $_nplurals = 2;
|
||||
|
||||
/**
|
||||
* Loaded MO file.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $filename = '';
|
||||
|
||||
/**
|
||||
* Returns the loaded MO file.
|
||||
*
|
||||
* @return string The loaded MO file.
|
||||
*/
|
||||
public function get_filename()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills up with the entries from MO file $filename.
|
||||
*
|
||||
* @param string $filename MO file to load
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public function import_from_file($filename)
|
||||
{
|
||||
$reader = new FileReader($filename);
|
||||
if (!$reader->is_resource()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->filename = (string) $filename;
|
||||
|
||||
return $this->import_from_reader($reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function export_to_file($filename)
|
||||
{
|
||||
$fh = fopen($filename, 'wb');
|
||||
if (!$fh) {
|
||||
return false;
|
||||
}
|
||||
$res = $this->export_to_file_handle($fh);
|
||||
fclose($fh);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|false
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
$tmp_fh = fopen('php://temp', 'r+');
|
||||
if (!$tmp_fh) {
|
||||
return false;
|
||||
}
|
||||
$this->export_to_file_handle($tmp_fh);
|
||||
rewind($tmp_fh);
|
||||
|
||||
return stream_get_contents($tmp_fh);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntryTranslations $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_entry_good_for_export(EntryTranslations $entry)
|
||||
{
|
||||
if (empty($entry->translations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!array_filter($entry->translations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $fh
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function export_to_file_handle($fh)
|
||||
{
|
||||
$entries = array_filter(
|
||||
$this->entries,
|
||||
array($this, 'is_entry_good_for_export')
|
||||
);
|
||||
ksort($entries);
|
||||
$magic = 0x950412de;
|
||||
$revision = 0;
|
||||
$total = count($entries) + 1; // all the headers are one entry
|
||||
$originals_lenghts_addr = 28;
|
||||
$translations_lenghts_addr = $originals_lenghts_addr + 8 * $total;
|
||||
$size_of_hash = 0;
|
||||
$hash_addr = $translations_lenghts_addr + 8 * $total;
|
||||
$current_addr = $hash_addr;
|
||||
fwrite($fh, pack(
|
||||
'V*',
|
||||
$magic,
|
||||
$revision,
|
||||
$total,
|
||||
$originals_lenghts_addr,
|
||||
$translations_lenghts_addr,
|
||||
$size_of_hash,
|
||||
$hash_addr
|
||||
));
|
||||
fseek($fh, $originals_lenghts_addr);
|
||||
|
||||
// headers' msgid is an empty string
|
||||
fwrite($fh, pack('VV', 0, $current_addr));
|
||||
$current_addr++;
|
||||
$originals_table = chr(0);
|
||||
|
||||
$reader = new NOOPReader();
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$originals_table .= $this->export_original($entry).chr(0);
|
||||
$length = $reader->strlen($this->export_original($entry));
|
||||
fwrite($fh, pack('VV', $length, $current_addr));
|
||||
$current_addr += $length + 1; // account for the NULL byte after
|
||||
}
|
||||
|
||||
$exported_headers = $this->export_headers();
|
||||
fwrite($fh, pack(
|
||||
'VV',
|
||||
$reader->strlen($exported_headers),
|
||||
$current_addr
|
||||
));
|
||||
$current_addr += strlen($exported_headers) + 1;
|
||||
$translations_table = $exported_headers.chr(0);
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$translations_table .= $this->export_translations($entry).chr(0);
|
||||
$length = $reader->strlen($this->export_translations($entry));
|
||||
fwrite($fh, pack('VV', $length, $current_addr));
|
||||
$current_addr += $length + 1;
|
||||
}
|
||||
|
||||
fwrite($fh, $originals_table);
|
||||
fwrite($fh, $translations_table);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntryTranslations $entry
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function export_original(EntryTranslations $entry)
|
||||
{
|
||||
//TODO: warnings for control characters
|
||||
$exported = $entry->singular;
|
||||
if ($entry->is_plural) {
|
||||
$exported .= chr(0).$entry->plural;
|
||||
}
|
||||
if (!is_null($entry->context)) {
|
||||
$exported = $entry->context.chr(4).$exported;
|
||||
}
|
||||
|
||||
return $exported;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntryTranslations $entry
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function export_translations(EntryTranslations $entry)
|
||||
{
|
||||
//TODO: warnings for control characters
|
||||
return $entry->is_plural ? implode(chr(0), $entry->translations) : $entry->translations[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function export_headers()
|
||||
{
|
||||
$exported = '';
|
||||
foreach ($this->headers as $header => $value) {
|
||||
$exported .= "$header: $value\n";
|
||||
}
|
||||
|
||||
return $exported;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $magic
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function get_byteorder($magic)
|
||||
{
|
||||
// The magic is 0x950412de
|
||||
$magic_little = (int) -1794895138;
|
||||
$magic_little_64 = (int) 2500072158;
|
||||
// 0xde120495
|
||||
$magic_big = ((int) -569244523) & 0xFFFFFFFF;
|
||||
if ($magic_little == $magic || $magic_little_64 == $magic) {
|
||||
return 'little';
|
||||
} elseif ($magic_big == $magic) {
|
||||
return 'big';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FileReader $reader
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function import_from_reader(FileReader $reader)
|
||||
{
|
||||
$endian_string = $this->get_byteorder($reader->readint32());
|
||||
if (false === $endian_string) {
|
||||
return false;
|
||||
}
|
||||
$reader->setEndian($endian_string);
|
||||
|
||||
$endian = ('big' == $endian_string) ? 'N' : 'V';
|
||||
|
||||
$header = $reader->read(24);
|
||||
if ($reader->strlen($header) != 24) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse header
|
||||
$header = unpack("{$endian}revision/{$endian}total/{$endian}originals_lenghts_addr/{$endian}translations_lenghts_addr/{$endian}hash_length/{$endian}hash_addr", $header);
|
||||
if (!is_array($header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// support revision 0 of MO format specs, only
|
||||
if ($header['revision'] != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// seek to data blocks
|
||||
$reader->seekto($header['originals_lenghts_addr']);
|
||||
|
||||
// read originals' indices
|
||||
$originals_lengths_length = $header['translations_lenghts_addr'] - $header['originals_lenghts_addr'];
|
||||
if ($originals_lengths_length != $header['total'] * 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$originals = $reader->read($originals_lengths_length);
|
||||
if ($reader->strlen($originals) != $originals_lengths_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// read translations' indices
|
||||
$translations_lenghts_length = $header['hash_addr'] - $header['translations_lenghts_addr'];
|
||||
if ($translations_lenghts_length != $header['total'] * 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$translations = $reader->read($translations_lenghts_length);
|
||||
if ($reader->strlen($translations) != $translations_lenghts_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// transform raw data into set of indices
|
||||
$originals = $reader->str_split($originals, 8);
|
||||
$translations = $reader->str_split($translations, 8);
|
||||
|
||||
// skip hash table
|
||||
$strings_addr = $header['hash_addr'] + $header['hash_length'] * 4;
|
||||
|
||||
$reader->seekto($strings_addr);
|
||||
|
||||
$strings = $reader->read_all();
|
||||
$reader->close();
|
||||
|
||||
for ($i = 0; $i < $header['total']; $i++) {
|
||||
$o = unpack("{$endian}length/{$endian}pos", $originals[$i]);
|
||||
$t = unpack("{$endian}length/{$endian}pos", $translations[$i]);
|
||||
if (!$o || !$t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// adjust offset due to reading strings to separate space before
|
||||
$o['pos'] -= $strings_addr;
|
||||
$t['pos'] -= $strings_addr;
|
||||
|
||||
$original = $reader->substr($strings, $o['pos'], $o['length']);
|
||||
$translation = $reader->substr($strings, $t['pos'], $t['length']);
|
||||
|
||||
if ('' === $original) {
|
||||
$this->set_headers($this->make_headers($translation));
|
||||
} else {
|
||||
$entry = &static::make_entry($original, $translation);
|
||||
$this->entries[$entry->key()] = &$entry;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a from original string and translation strings,
|
||||
* found in a MO file.
|
||||
*
|
||||
* @param string $original original string to translate from MO file.
|
||||
* Might contain 0x04 as context separator or
|
||||
* 0x00 as singular/plural separator
|
||||
* @param string $translation translation string from MO file.Might contain
|
||||
* 0x00 as a plural translations separator
|
||||
*
|
||||
* @return EntryTranslations New entry
|
||||
*/
|
||||
public static function &make_entry($original, $translation)
|
||||
{
|
||||
$entry = new EntryTranslations();
|
||||
// look for context
|
||||
$parts = explode(chr(4), $original);
|
||||
if (isset($parts[1])) {
|
||||
$original = $parts[1];
|
||||
$entry->context = $parts[0];
|
||||
}
|
||||
// look for plural original
|
||||
$parts = explode(chr(0), $original);
|
||||
$entry->singular = $parts[0];
|
||||
if (isset($parts[1])) {
|
||||
$entry->is_plural = true;
|
||||
$entry->plural = $parts[1];
|
||||
}
|
||||
// plural translations are also separated by \0
|
||||
$entry->translations = explode(chr(0), $translation);
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function select_plural_form($count)
|
||||
{
|
||||
return $this->gettext_select_plural_form($count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_plural_forms_count()
|
||||
{
|
||||
return $this->_nplurals;
|
||||
}
|
||||
}
|
587
includes/vendor/pomo/pomo/src/PO.php
vendored
Normal file
587
includes/vendor/pomo/pomo/src/PO.php
vendored
Normal file
@ -0,0 +1,587 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of the POMO package.
|
||||
*
|
||||
* @copyright 2014 POMO
|
||||
* @license GPL
|
||||
*/
|
||||
|
||||
namespace POMO;
|
||||
|
||||
use POMO\Translations\EntryTranslations;
|
||||
use POMO\Translations\GettextTranslations;
|
||||
|
||||
ini_set('auto_detect_line_endings', 1);
|
||||
|
||||
/**
|
||||
* Class for working with PO files.
|
||||
*/
|
||||
class PO extends GettextTranslations
|
||||
{
|
||||
const MAX_LINE_LEN = 79;
|
||||
|
||||
public $comments_before_headers = '';
|
||||
|
||||
/**
|
||||
* Exports headers to a PO entry.
|
||||
*
|
||||
* @return string msgid/msgstr PO entry for this PO file headers, doesn't
|
||||
* contain newline at the end
|
||||
*/
|
||||
public function export_headers()
|
||||
{
|
||||
$header_string = '';
|
||||
foreach ($this->headers as $header => $value) {
|
||||
$header_string .= "$header: $value\n";
|
||||
}
|
||||
$poified = self::poify($header_string);
|
||||
if ($this->comments_before_headers) {
|
||||
$before_headers = self::prepend_each_line(
|
||||
rtrim($this->comments_before_headers)."\n",
|
||||
'# '
|
||||
);
|
||||
} else {
|
||||
$before_headers = '';
|
||||
}
|
||||
|
||||
return rtrim("{$before_headers}msgid \"\"\nmsgstr $poified");
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports all entries to PO format.
|
||||
*
|
||||
* @return string sequence of mgsgid/msgstr PO strings, doesn't containt
|
||||
* newline at the end
|
||||
*/
|
||||
public function export_entries()
|
||||
{
|
||||
//TODO: sorting
|
||||
return implode("\n\n", array_map(
|
||||
array(__NAMESPACE__.'\PO', 'export_entry'),
|
||||
$this->entries
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the whole PO file as a string.
|
||||
*
|
||||
* @param bool $include_headers whether to include the headers in the
|
||||
* export
|
||||
*
|
||||
* @return string ready for inclusion in PO file string for headers and all
|
||||
* the enrtries
|
||||
*/
|
||||
public function export($include_headers = true)
|
||||
{
|
||||
$res = '';
|
||||
if ($include_headers) {
|
||||
$res .= $this->export_headers();
|
||||
$res .= "\n\n";
|
||||
}
|
||||
$res .= $this->export_entries();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link export}, but writes the result to a file.
|
||||
*
|
||||
* @param string $filename where to write the PO string
|
||||
* @param bool $include_headers whether to include tje headers in the
|
||||
* export
|
||||
*
|
||||
* @return bool true on success, false on error
|
||||
*/
|
||||
public function export_to_file($filename, $include_headers = true)
|
||||
{
|
||||
$fh = fopen($filename, 'w');
|
||||
if (false === $fh) {
|
||||
return false;
|
||||
}
|
||||
$export = $this->export($include_headers);
|
||||
$res = fwrite($fh, $export);
|
||||
if (false === $res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return fclose($fh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Text to include as a comment before the start of the PO contents.
|
||||
*
|
||||
* Doesn't need to include # in the beginning of lines, these are added
|
||||
* automatically
|
||||
*
|
||||
* @param string $text Comment text
|
||||
*/
|
||||
public function set_comment_before_headers($text)
|
||||
{
|
||||
$this->comments_before_headers = $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string in PO-style.
|
||||
*
|
||||
* @param string $string the string to format
|
||||
*
|
||||
* @return string the poified string
|
||||
*/
|
||||
public static function poify($string)
|
||||
{
|
||||
$quote = '"';
|
||||
$slash = '\\';
|
||||
$newline = "\n";
|
||||
|
||||
$replaces = array(
|
||||
"$slash" => "$slash$slash",
|
||||
"$quote" => "$slash$quote",
|
||||
"\t" => '\t',
|
||||
);
|
||||
|
||||
$string = str_replace(
|
||||
array_keys($replaces),
|
||||
array_values($replaces),
|
||||
$string
|
||||
);
|
||||
|
||||
$po = $quote.implode(
|
||||
"${slash}n$quote$newline$quote",
|
||||
explode($newline, $string)
|
||||
).$quote;
|
||||
// add empty string on first line for readbility
|
||||
if (false !== strpos($string, $newline) &&
|
||||
(substr_count($string, $newline) > 1 ||
|
||||
!($newline === substr($string, -strlen($newline))))) {
|
||||
$po = "$quote$quote$newline$po";
|
||||
}
|
||||
// remove empty strings
|
||||
$po = str_replace("$newline$quote$quote", '', $po);
|
||||
|
||||
return $po;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives back the original string from a PO-formatted string.
|
||||
*
|
||||
* @param string $string PO-formatted string
|
||||
*
|
||||
* @return string enascaped string
|
||||
*/
|
||||
public static function unpoify($string)
|
||||
{
|
||||
$escapes = array('t' => "\t", 'n' => "\n", 'r' => "\r", '\\' => '\\');
|
||||
$lines = array_map('trim', explode("\n", $string));
|
||||
$lines = array_map(array(__NAMESPACE__.'\PO', 'trim_quotes'), $lines);
|
||||
$unpoified = '';
|
||||
$previous_is_backslash = false;
|
||||
foreach ($lines as $line) {
|
||||
preg_match_all('/./u', $line, $chars);
|
||||
$chars = $chars[0];
|
||||
foreach ($chars as $char) {
|
||||
if (!$previous_is_backslash) {
|
||||
if ('\\' == $char) {
|
||||
$previous_is_backslash = true;
|
||||
} else {
|
||||
$unpoified .= $char;
|
||||
}
|
||||
} else {
|
||||
$previous_is_backslash = false;
|
||||
$unpoified .= isset($escapes[$char]) ? $escapes[$char] : $char;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Standardise the line endings on imported content, technically PO files shouldn't contain \r
|
||||
$unpoified = str_replace(array("\r\n", "\r"), "\n", $unpoified);
|
||||
|
||||
return $unpoified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts $with in the beginning of every new line of $string and
|
||||
* returns the modified string.
|
||||
*
|
||||
* @param string $string prepend lines in this string
|
||||
* @param string $with prepend lines with this string
|
||||
*
|
||||
* @return string The modified string
|
||||
*/
|
||||
public static function prepend_each_line($string, $with)
|
||||
{
|
||||
$lines = explode("\n", $string);
|
||||
$append = '';
|
||||
if ("\n" === substr($string, -1) && '' === end($lines)) {
|
||||
// Last line might be empty because $string was terminated
|
||||
// with a newline, remove it from the $lines array,
|
||||
// we'll restore state by re-terminating the string at the end
|
||||
array_pop($lines);
|
||||
$append = "\n";
|
||||
}
|
||||
foreach ($lines as &$line) {
|
||||
$line = $with.$line;
|
||||
}
|
||||
unset($line);
|
||||
|
||||
return implode("\n", $lines).$append;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a text as a comment -- wraps the lines and prepends #
|
||||
* and a special character to each line.
|
||||
*
|
||||
* @param string $text the comment text
|
||||
* @param string $char character to denote a special PO comment,
|
||||
* like :, default is a space
|
||||
*
|
||||
* @return string The modified string
|
||||
*/
|
||||
private static function comment_block($text, $char = ' ')
|
||||
{
|
||||
$text = wordwrap($text, self::MAX_LINE_LEN - 3);
|
||||
|
||||
return self::prepend_each_line($text, "#$char ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a string from the entry for inclusion in PO file.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @param EntryTranslations &$entry the entry to convert to po string
|
||||
*
|
||||
* @return false|string PO-style formatted string for the entry or
|
||||
* false if the entry is empty
|
||||
*/
|
||||
public static function export_entry(EntryTranslations &$entry)
|
||||
{
|
||||
if (null === $entry->singular || '' === $entry->singular) {
|
||||
return false;
|
||||
}
|
||||
$po = array();
|
||||
if (!empty($entry->translator_comments)) {
|
||||
$po[] = self::comment_block($entry->translator_comments);
|
||||
}
|
||||
if (!empty($entry->extracted_comments)) {
|
||||
$po[] = self::comment_block($entry->extracted_comments, '.');
|
||||
}
|
||||
if (!empty($entry->references)) {
|
||||
$po[] = self::comment_block(implode(' ', $entry->references), ':');
|
||||
}
|
||||
if (!empty($entry->flags)) {
|
||||
$po[] = self::comment_block(implode(', ', $entry->flags), ',');
|
||||
}
|
||||
if (!is_null($entry->context)) {
|
||||
$po[] = 'msgctxt '.self::poify($entry->context);
|
||||
}
|
||||
$po[] = 'msgid '.self::poify($entry->singular);
|
||||
if (!$entry->is_plural) {
|
||||
$translation = empty($entry->translations) ?
|
||||
'' :
|
||||
$entry->translations[0];
|
||||
$translation = self::match_begin_and_end_newlines($translation, $entry->singular);
|
||||
$po[] = 'msgstr '.self::poify($translation);
|
||||
} else {
|
||||
$po[] = 'msgid_plural '.self::poify($entry->plural);
|
||||
$translations = empty($entry->translations) ?
|
||||
array('', '') :
|
||||
$entry->translations;
|
||||
foreach ($translations as $i => $translation) {
|
||||
$translation = self::match_begin_and_end_newlines($translation, $entry->plural);
|
||||
$po[] = "msgstr[$i] ".self::poify($translation);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $po);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $translation
|
||||
* @param $original
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function match_begin_and_end_newlines($translation, $original)
|
||||
{
|
||||
if ('' === $translation) {
|
||||
return $translation;
|
||||
}
|
||||
|
||||
$original_begin = "\n" === substr($original, 0, 1);
|
||||
$original_end = "\n" === substr($original, -1);
|
||||
$translation_begin = "\n" === substr($translation, 0, 1);
|
||||
$translation_end = "\n" === substr($translation, -1);
|
||||
if ($original_begin) {
|
||||
if (!$translation_begin) {
|
||||
$translation = "\n".$translation;
|
||||
}
|
||||
} elseif ($translation_begin) {
|
||||
$translation = ltrim($translation, "\n");
|
||||
}
|
||||
if ($original_end) {
|
||||
if (!$translation_end) {
|
||||
$translation .= "\n";
|
||||
}
|
||||
} elseif ($translation_end) {
|
||||
$translation = rtrim($translation, "\n");
|
||||
}
|
||||
|
||||
return $translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function import_from_file($filename)
|
||||
{
|
||||
$f = fopen($filename, 'r');
|
||||
if (!$f) {
|
||||
return false;
|
||||
}
|
||||
$lineno = 0;
|
||||
$res = false;
|
||||
while (true) {
|
||||
$res = $this->read_entry($f, $lineno);
|
||||
if (!$res) {
|
||||
break;
|
||||
}
|
||||
if ($res['entry']->singular == '') {
|
||||
$this->set_headers(
|
||||
$this->make_headers($res['entry']->translations[0])
|
||||
);
|
||||
} else {
|
||||
$this->add_entry($res['entry']);
|
||||
}
|
||||
}
|
||||
self::read_line($f, 'clear');
|
||||
if (false === $res) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->headers && !$this->entries) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for read_entry.
|
||||
*
|
||||
* @param string $context
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function is_final($context)
|
||||
{
|
||||
return ($context === 'msgstr') || ($context === 'msgstr_plural');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $f
|
||||
* @param int $lineno
|
||||
*
|
||||
* @return null|false|array
|
||||
*/
|
||||
public function read_entry($f, $lineno = 0)
|
||||
{
|
||||
$entry = new EntryTranslations();
|
||||
// where were we in the last step
|
||||
// can be: comment, msgctxt, msgid, msgid_plural, msgstr, msgstr_plural
|
||||
$context = '';
|
||||
$msgstr_index = 0;
|
||||
while (true) {
|
||||
$lineno++;
|
||||
$line = self::read_line($f);
|
||||
if (!$line) {
|
||||
if (feof($f)) {
|
||||
if (self::is_final($context)) {
|
||||
break;
|
||||
} elseif (!$context) { // we haven't read a line and eof came
|
||||
return;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($line == "\n") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$line = trim($line);
|
||||
if (preg_match('/^#/', $line, $m)) {
|
||||
// the comment is the start of a new entry
|
||||
if (self::is_final($context)) {
|
||||
self::read_line($f, 'put-back');
|
||||
$lineno--;
|
||||
break;
|
||||
}
|
||||
// comments have to be at the beginning
|
||||
if ($context && $context != 'comment') {
|
||||
return false;
|
||||
}
|
||||
// add comment
|
||||
$this->add_comment_to_entry($entry, $line);
|
||||
} elseif (preg_match('/^msgctxt\s+(".*")/', $line, $m)) {
|
||||
if (self::is_final($context)) {
|
||||
self::read_line($f, 'put-back');
|
||||
$lineno--;
|
||||
break;
|
||||
}
|
||||
if ($context && $context != 'comment') {
|
||||
return false;
|
||||
}
|
||||
$context = 'msgctxt';
|
||||
$entry->context .= self::unpoify($m[1]);
|
||||
} elseif (preg_match('/^msgid\s+(".*")/', $line, $m)) {
|
||||
if (self::is_final($context)) {
|
||||
self::read_line($f, 'put-back');
|
||||
$lineno--;
|
||||
break;
|
||||
}
|
||||
if ($context &&
|
||||
$context != 'msgctxt' &&
|
||||
$context != 'comment') {
|
||||
return false;
|
||||
}
|
||||
$context = 'msgid';
|
||||
$entry->singular .= self::unpoify($m[1]);
|
||||
} elseif (preg_match('/^msgid_plural\s+(".*")/', $line, $m)) {
|
||||
if ($context != 'msgid') {
|
||||
return false;
|
||||
}
|
||||
$context = 'msgid_plural';
|
||||
$entry->is_plural = true;
|
||||
$entry->plural .= self::unpoify($m[1]);
|
||||
} elseif (preg_match('/^msgstr\s+(".*")/', $line, $m)) {
|
||||
if ($context != 'msgid') {
|
||||
return false;
|
||||
}
|
||||
$context = 'msgstr';
|
||||
$entry->translations = array(self::unpoify($m[1]));
|
||||
} elseif (preg_match('/^msgstr\[(\d+)\]\s+(".*")/', $line, $m)) {
|
||||
if ($context != 'msgid_plural' && $context != 'msgstr_plural') {
|
||||
return false;
|
||||
}
|
||||
$context = 'msgstr_plural';
|
||||
$msgstr_index = $m[1];
|
||||
$entry->translations[$m[1]] = self::unpoify($m[2]);
|
||||
} elseif (preg_match('/^".*"$/', $line)) {
|
||||
$unpoified = self::unpoify($line);
|
||||
switch ($context) {
|
||||
case 'msgid':
|
||||
$entry->singular .= $unpoified;
|
||||
break;
|
||||
case 'msgctxt':
|
||||
$entry->context .= $unpoified;
|
||||
break;
|
||||
case 'msgid_plural':
|
||||
$entry->plural .= $unpoified;
|
||||
break;
|
||||
case 'msgstr':
|
||||
$entry->translations[0] .= $unpoified;
|
||||
break;
|
||||
case 'msgstr_plural':
|
||||
$entry->translations[$msgstr_index] .= $unpoified;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$have_translations = false;
|
||||
foreach ($entry->translations as $t) {
|
||||
if ($t || ('0' === $t)) {
|
||||
$have_translations = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (false === $have_translations) {
|
||||
$entry->translations = array();
|
||||
}
|
||||
|
||||
return array('entry' => $entry, 'lineno' => $lineno);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $f
|
||||
* @param string $action
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function read_line($f, $action = 'read')
|
||||
{
|
||||
static $last_line = '';
|
||||
static $use_last_line = false;
|
||||
if ('clear' == $action) {
|
||||
$last_line = '';
|
||||
|
||||
return true;
|
||||
}
|
||||
if ('put-back' == $action) {
|
||||
$use_last_line = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
$line = $use_last_line ? $last_line : fgets($f);
|
||||
$line = ("\r\n" == substr($line, -2)) ?
|
||||
rtrim($line, "\r\n")."\n" :
|
||||
$line;
|
||||
$last_line = $line;
|
||||
$use_last_line = false;
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntryTranslations $entry
|
||||
* @param string $po_comment_line
|
||||
*/
|
||||
public function add_comment_to_entry(EntryTranslations &$entry, $po_comment_line)
|
||||
{
|
||||
$first_two = substr($po_comment_line, 0, 2);
|
||||
$comment = trim(substr($po_comment_line, 2));
|
||||
if ('#:' == $first_two) {
|
||||
$entry->references = array_merge(
|
||||
$entry->references,
|
||||
preg_split('/\s+/', $comment)
|
||||
);
|
||||
} elseif ('#.' == $first_two) {
|
||||
$entry->extracted_comments = trim(
|
||||
$entry->extracted_comments."\n".$comment
|
||||
);
|
||||
} elseif ('#,' == $first_two) {
|
||||
$entry->flags = array_merge(
|
||||
$entry->flags,
|
||||
preg_split('/,\s*/', $comment)
|
||||
);
|
||||
} else {
|
||||
$entry->translator_comments = trim(
|
||||
$entry->translator_comments."\n".$comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function trim_quotes($s)
|
||||
{
|
||||
if (substr($s, 0, 1) == '"') {
|
||||
$s = substr($s, 1);
|
||||
}
|
||||
if (substr($s, -1, 1) == '"') {
|
||||
$s = substr($s, 0, -1);
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user