Vendor je po novem v repozitoriju

This commit is contained in:
pero1203 2020-12-05 12:58:56 +01:00
parent 4b7aac2408
commit 31745d95ca
904 changed files with 138235 additions and 62 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
# Vendor folder # Vendor folder
/vendor/ #vendor/
# DEV tools # DEV tools
.vscode/ .vscode/

123
composer.lock generated
View File

@ -1,10 +1,9 @@
{ {
"_readme": [ "_readme": [
"This file locks the dependencies of your project to a known state", "This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "c9fc655cdb58743c38114c03e68c1cc7",
"content-hash": "a150435d7f20bef4fdda8cb6c59eb1a6", "content-hash": "a150435d7f20bef4fdda8cb6c59eb1a6",
"packages": [ "packages": [
{ {
@ -61,7 +60,7 @@
"ssl", "ssl",
"tls" "tls"
], ],
"time": "2020-08-23 12:54:47" "time": "2020-08-23T12:54:47+00:00"
}, },
{ {
"name": "fgrosse/phpasn1", "name": "fgrosse/phpasn1",
@ -132,7 +131,7 @@
"x509", "x509",
"x690" "x690"
], ],
"time": "2020-10-11 16:28:18" "time": "2020-10-11T16:28:18+00:00"
}, },
{ {
"name": "geoip2/geoip2", "name": "geoip2/geoip2",
@ -185,7 +184,7 @@
"geolocation", "geolocation",
"maxmind" "maxmind"
], ],
"time": "2020-10-01 18:48:34" "time": "2020-10-01T18:48:34+00:00"
}, },
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
@ -252,7 +251,7 @@
"rest", "rest",
"web service" "web service"
], ],
"time": "2020-06-16 21:01:06" "time": "2020-06-16T21:01:06+00:00"
}, },
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
@ -303,7 +302,7 @@
"keywords": [ "keywords": [
"promise" "promise"
], ],
"time": "2020-09-30 07:37:28" "time": "2020-09-30T07:37:28+00:00"
}, },
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
@ -374,7 +373,7 @@
"uri", "uri",
"url" "url"
], ],
"time": "2020-09-30 07:37:11" "time": "2020-09-30T07:37:11+00:00"
}, },
{ {
"name": "maxmind-db/reader", "name": "maxmind-db/reader",
@ -434,7 +433,7 @@
"geolocation", "geolocation",
"maxmind" "maxmind"
], ],
"time": "2020-10-01 17:30:21" "time": "2020-10-01T17:30:21+00:00"
}, },
{ {
"name": "maxmind/web-service-common", "name": "maxmind/web-service-common",
@ -480,7 +479,7 @@
], ],
"description": "Internal MaxMind Web Service API", "description": "Internal MaxMind Web Service API",
"homepage": "https://github.com/maxmind/web-service-common-php", "homepage": "https://github.com/maxmind/web-service-common-php",
"time": "2020-11-02 17:00:53" "time": "2020-11-02T17:00:53+00:00"
}, },
{ {
"name": "minishlink/web-push", "name": "minishlink/web-push",
@ -536,7 +535,7 @@
"push", "push",
"web" "web"
], ],
"time": "2020-08-02 08:58:01" "time": "2020-08-02T08:58:01+00:00"
}, },
{ {
"name": "paragonie/random_compat", "name": "paragonie/random_compat",
@ -581,20 +580,20 @@
"pseudorandom", "pseudorandom",
"random" "random"
], ],
"time": "2020-10-15 08:29:30" "time": "2020-10-15T08:29:30+00:00"
}, },
{ {
"name": "paragonie/sodium_compat", "name": "paragonie/sodium_compat",
"version": "v1.13.0", "version": "v1.14.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/paragonie/sodium_compat.git", "url": "https://github.com/paragonie/sodium_compat.git",
"reference": "bbade402cbe84c69b718120911506a3aa2bae653" "reference": "a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/bbade402cbe84c69b718120911506a3aa2bae653", "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3",
"reference": "bbade402cbe84c69b718120911506a3aa2bae653", "reference": "a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -602,7 +601,7 @@
"php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^3|^4|^5|^6|^7" "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9"
}, },
"suggest": { "suggest": {
"ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.",
@ -663,7 +662,7 @@
"secret-key cryptography", "secret-key cryptography",
"side-channel resistant" "side-channel resistant"
], ],
"time": "2020-03-20 21:48:09" "time": "2020-12-03T16:26:19+00:00"
}, },
{ {
"name": "paypal/paypal-checkout-sdk", "name": "paypal/paypal-checkout-sdk",
@ -712,7 +711,7 @@
"rest", "rest",
"sdk" "sdk"
], ],
"time": "2019-11-07 23:16:44" "time": "2019-11-07T23:16:44+00:00"
}, },
{ {
"name": "paypal/paypalhttp", "name": "paypal/paypalhttp",
@ -751,21 +750,20 @@
"homepage": "https://github.com/paypal/paypalhttp_php/contributors" "homepage": "https://github.com/paypal/paypalhttp_php/contributors"
} }
], ],
"abandoned": true, "time": "2019-11-06T21:27:12+00:00"
"time": "2019-11-06 21:27:12"
}, },
{ {
"name": "phpmailer/phpmailer", "name": "phpmailer/phpmailer",
"version": "v6.1.8", "version": "v6.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git", "url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "917ab212fa00dc6eacbb26e8bc387ebe40993bc1" "reference": "e38888a75c070304ca5514197d4847a59a5c853f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/917ab212fa00dc6eacbb26e8bc387ebe40993bc1", "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e38888a75c070304ca5514197d4847a59a5c853f",
"reference": "917ab212fa00dc6eacbb26e8bc387ebe40993bc1", "reference": "e38888a75c070304ca5514197d4847a59a5c853f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -775,9 +773,12 @@
"php": ">=5.5.0" "php": ">=5.5.0"
}, },
"require-dev": { "require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2", "doctrine/annotations": "^1.2",
"friendsofphp/php-cs-fixer": "^2.2", "phpcompatibility/php-compatibility": "^9.3.5",
"phpunit/phpunit": "^4.8 || ^5.7" "roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5.6",
"yoast/phpunit-polyfills": "^0.2.0"
}, },
"suggest": { "suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset", "ext-mbstring": "Needed to send email in multibyte encoding charset",
@ -815,7 +816,7 @@
} }
], ],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP", "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"time": "2020-10-09 14:55:58" "time": "2020-11-25T15:24:57+00:00"
}, },
{ {
"name": "psr/http-message", "name": "psr/http-message",
@ -865,7 +866,7 @@
"request", "request",
"response" "response"
], ],
"time": "2016-08-06 14:39:51" "time": "2016-08-06T14:39:51+00:00"
}, },
{ {
"name": "ralouphie/getallheaders", "name": "ralouphie/getallheaders",
@ -905,7 +906,7 @@
} }
], ],
"description": "A polyfill for getallheaders.", "description": "A polyfill for getallheaders.",
"time": "2019-03-08 08:55:37" "time": "2019-03-08T08:55:37+00:00"
}, },
{ {
"name": "sonata-project/google-authenticator", "name": "sonata-project/google-authenticator",
@ -962,7 +963,7 @@
"keywords": [ "keywords": [
"google authenticator" "google authenticator"
], ],
"time": "2018-07-18 22:08:02" "time": "2018-07-18T22:08:02+00:00"
}, },
{ {
"name": "spomky-labs/base64url", "name": "spomky-labs/base64url",
@ -1013,20 +1014,20 @@
"safe", "safe",
"url" "url"
], ],
"time": "2020-11-03 09:10:25" "time": "2020-11-03T09:10:25+00:00"
}, },
{ {
"name": "stripe/stripe-php", "name": "stripe/stripe-php",
"version": "v7.61.0", "version": "v7.66.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/stripe/stripe-php.git", "url": "https://github.com/stripe/stripe-php.git",
"reference": "51c6cd18cb51740101c940a3fefc876ef7cd8cae" "reference": "a2ebaa272a8797b21e81afaf8d5ba0953ff15e13"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/51c6cd18cb51740101c940a3fefc876ef7cd8cae", "url": "https://api.github.com/repos/stripe/stripe-php/zipball/a2ebaa272a8797b21e81afaf8d5ba0953ff15e13",
"reference": "51c6cd18cb51740101c940a3fefc876ef7cd8cae", "reference": "a2ebaa272a8797b21e81afaf8d5ba0953ff15e13",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1036,7 +1037,7 @@
"php": ">=5.6.0" "php": ">=5.6.0"
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "2.16.1", "friendsofphp/php-cs-fixer": "2.16.5",
"php-coveralls/php-coveralls": "^2.1", "php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5.7", "phpunit/phpunit": "^5.7",
"squizlabs/php_codesniffer": "^3.3", "squizlabs/php_codesniffer": "^3.3",
@ -1070,7 +1071,7 @@
"payment processing", "payment processing",
"stripe" "stripe"
], ],
"time": "2020-10-20 20:01:45" "time": "2020-12-01T18:44:12+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-idn", "name": "symfony/polyfill-intl-idn",
@ -1140,7 +1141,7 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-10-23 14:02:19" "time": "2020-10-23T14:02:19+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-normalizer", "name": "symfony/polyfill-intl-normalizer",
@ -1207,7 +1208,7 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-10-23 14:02:19" "time": "2020-10-23T14:02:19+00:00"
}, },
{ {
"name": "symfony/polyfill-php72", "name": "symfony/polyfill-php72",
@ -1266,7 +1267,7 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-10-23 14:02:19" "time": "2020-10-23T14:02:19+00:00"
}, },
{ {
"name": "web-token/jwt-core", "name": "web-token/jwt-core",
@ -1341,7 +1342,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-key-mgmt", "name": "web-token/jwt-key-mgmt",
@ -1418,7 +1419,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-signature", "name": "web-token/jwt-signature",
@ -1498,7 +1499,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-signature-algorithm-ecdsa", "name": "web-token/jwt-signature-algorithm-ecdsa",
@ -1565,7 +1566,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-signature-algorithm-eddsa", "name": "web-token/jwt-signature-algorithm-eddsa",
@ -1632,7 +1633,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-signature-algorithm-hmac", "name": "web-token/jwt-signature-algorithm-hmac",
@ -1699,7 +1700,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-signature-algorithm-none", "name": "web-token/jwt-signature-algorithm-none",
@ -1766,7 +1767,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-signature-algorithm-rsa", "name": "web-token/jwt-signature-algorithm-rsa",
@ -1833,7 +1834,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
}, },
{ {
"name": "web-token/jwt-util-ecc", "name": "web-token/jwt-util-ecc",
@ -1902,7 +1903,7 @@
"jwt", "jwt",
"symfony" "symfony"
], ],
"time": "2020-03-20 13:29:04" "time": "2020-03-20T13:29:04+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [
@ -1965,7 +1966,7 @@
"throwable", "throwable",
"whoops" "whoops"
], ],
"time": "2020-11-01 12:00:00" "time": "2020-11-01T12:00:00+00:00"
}, },
{ {
"name": "kint-php/kint", "name": "kint-php/kint",
@ -2016,7 +2017,7 @@
"kint", "kint",
"php" "php"
], ],
"time": "2017-01-15 14:23:43" "time": "2017-01-15T14:23:43+00:00"
}, },
{ {
"name": "maximebf/debugbar", "name": "maximebf/debugbar",
@ -2077,7 +2078,7 @@
"debug", "debug",
"debugbar" "debugbar"
], ],
"time": "2020-05-06 07:06:27" "time": "2020-05-06T07:06:27+00:00"
}, },
{ {
"name": "psr/log", "name": "psr/log",
@ -2124,7 +2125,7 @@
"psr", "psr",
"psr-3" "psr-3"
], ],
"time": "2020-03-23 09:12:05" "time": "2020-03-23T09:12:05+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
@ -2187,7 +2188,7 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-10-23 14:02:19" "time": "2020-10-23T14:02:19+00:00"
}, },
{ {
"name": "symfony/polyfill-php80", "name": "symfony/polyfill-php80",
@ -2253,20 +2254,20 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-10-23 14:02:19" "time": "2020-10-23T14:02:19+00:00"
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v4.4.16", "version": "v4.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "3718e18b68d955348ad860e505991802c09f5f73" "reference": "65c6f1e848cda840ef7278686c8e30a7cc353c93"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/3718e18b68d955348ad860e505991802c09f5f73", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/65c6f1e848cda840ef7278686c8e30a7cc353c93",
"reference": "3718e18b68d955348ad860e505991802c09f5f73", "reference": "65c6f1e848cda840ef7278686c8e30a7cc353c93",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2325,7 +2326,7 @@
"debug", "debug",
"dump" "dump"
], ],
"time": "2020-10-26 20:47:51" "time": "2020-11-24T09:55:37+00:00"
} }
], ],
"aliases": [], "aliases": [],

7
vendor/autoload.php vendored Normal file
View File

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit0d06eb1022200eb96b7e4bb652ca3996::getLoader();

445
vendor/composer/ClassLoader.php vendored Normal file
View File

@ -0,0 +1,445 @@
<?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 http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
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 array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
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 array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
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 array|string $paths The PSR-0 base directories
*/
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 array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
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
*/
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
*/
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
*/
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
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* 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;
}
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.
*/
function includeFile($file)
{
include $file;
}

21
vendor/composer/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

1031
vendor/composer/autoload_classmap.php vendored Normal file

File diff suppressed because it is too large Load Diff

24
vendor/composer/autoload_files.php vendored Normal file
View File

@ -0,0 +1,24 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'3109cb1a231dcd04bee1f9f620d46975' => $vendorDir . '/paragonie/sodium_compat/autoload.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'2bf0564df058fbe21b5554296cc8571a' => $baseDir . '/main/survey/class.EvalvacijaMain.php',
'5bc35216aa4f6cb823ce4a5cec52fdce' => $baseDir . '/main/survey/mobile-detect/Mobile_Detect.php',
'22b9df91cd299713e735921c8347a64c' => $baseDir . '/admin/survey/classes/phpqrcode/phpqrcode.php',
'b16a1c1f07a2cd49108ffd9526301d46' => $baseDir . '/admin/survey/classes/htmlpurifier-4.3.0/library/HTMLPurifier.auto.php',
'42ee429c4fc185623d97225cd58c1721' => $baseDir . '/frontend/api/class.ApiLoginController.php',
'5c9b5464443c3e2e223486d66948f183' => $baseDir . '/frontend/api/class.ApiLogin.php',
'35561f6018bff40f363b94411e0141e0' => $baseDir . '/utils/1kaCron/class.CronJobs.php',
);

View File

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

38
vendor/composer/autoload_psr4.php vendored Normal file
View File

@ -0,0 +1,38 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
'Stripe\\' => array($vendorDir . '/stripe/stripe-php/lib'),
'Sonata\\GoogleAuthenticator\\' => array($vendorDir . '/sonata-project/google-authenticator/src'),
'Sample\\' => array($vendorDir . '/paypal/paypal-checkout-sdk/samples'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'PayPalHttp\\' => array($vendorDir . '/paypal/paypalhttp/lib/PayPalHttp'),
'PayPalCheckoutSdk\\' => array($vendorDir . '/paypal/paypal-checkout-sdk/lib/PayPalCheckoutSdk'),
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
'Minishlink\\WebPush\\' => array($vendorDir . '/minishlink/web-push/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'),
'Jose\\Component\\Signature\\Algorithm\\' => array($vendorDir . '/web-token/jwt-signature-algorithm-ecdsa', $vendorDir . '/web-token/jwt-signature-algorithm-eddsa', $vendorDir . '/web-token/jwt-signature-algorithm-hmac', $vendorDir . '/web-token/jwt-signature-algorithm-none', $vendorDir . '/web-token/jwt-signature-algorithm-rsa'),
'Jose\\Component\\Signature\\' => array($vendorDir . '/web-token/jwt-signature'),
'Jose\\Component\\KeyManagement\\' => array($vendorDir . '/web-token/jwt-key-mgmt'),
'Jose\\Component\\Core\\Util\\Ecc\\' => array($vendorDir . '/web-token/jwt-util-ecc'),
'Jose\\Component\\Core\\' => array($vendorDir . '/web-token/jwt-core'),
'Hierarhija\\' => array($baseDir . '/admin/survey/modules/mod_hierarhija'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
'Google\\Authenticator\\' => array($vendorDir . '/sonata-project/google-authenticator/src'),
'GeoIp2\\' => array($vendorDir . '/geoip2/geoip2/src'),
'FG\\' => array($vendorDir . '/fgrosse/phpasn1/lib'),
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
'Base64Url\\' => array($vendorDir . '/spomky-labs/base64url/src'),
'App\\' => array($baseDir . '/main/survey/app'),
);

70
vendor/composer/autoload_real.php vendored Normal file
View File

@ -0,0 +1,70 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit0d06eb1022200eb96b7e4bb652ca3996
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit0d06eb1022200eb96b7e4bb652ca3996', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit0d06eb1022200eb96b7e4bb652ca3996', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit0d06eb1022200eb96b7e4bb652ca3996::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit0d06eb1022200eb96b7e4bb652ca3996::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire0d06eb1022200eb96b7e4bb652ca3996($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire0d06eb1022200eb96b7e4bb652ca3996($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}
}

1246
vendor/composer/autoload_static.php vendored Normal file

File diff suppressed because it is too large Load Diff

19
vendor/composer/ca-bundle/LICENSE vendored Normal file
View 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
vendor/composer/ca-bundle/README.md vendored Normal file
View 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
vendor/composer/ca-bundle/composer.json vendored Normal file
View 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": {
"phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
"psr/log": "^1.0",
"symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0"
},
"autoload": {
"psr-4": {
"Composer\\CaBundle\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Composer\\CaBundle\\": "tests"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"config": {
"platform": {
"php": "5.3.9"
}
}
}

3447
vendor/composer/ca-bundle/res/cacert.pem vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,325 @@
<?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
{
private static $caPath;
private static $caFileValidity = array();
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 (self::caFileUsable($caBundle, $logger)) {
return self::$caPath = $caBundle;
}
if (self::caDirUsable($caBundle)) {
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://')) {
file_put_contents(
$tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
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);
} else {
$contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
$isValid = (bool) openssl_x509_parse($contents);
}
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 < 50600 && 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 (
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
*/
public static function reset()
{
self::$caFileValidity = array();
self::$caPath = null;
self::$useOpensslParse = null;
}
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;
}
private static function caFileUsable($certFile, LoggerInterface $logger = null)
{
return $certFile && @is_file($certFile) && @is_readable($certFile) && static::validateCaFile($certFile, $logger);
}
private static function caDirUsable($certDir)
{
return $certDir && @is_dir($certDir) && @is_readable($certDir) && glob($certDir . '/*');
}
}

1963
vendor/composer/installed.json vendored Normal file

File diff suppressed because it is too large Load Diff

47
vendor/fgrosse/phpasn1/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,47 @@
#### v2.2.0 (2020-08)
* support polyfills for bcmath and gmp, and add a composer.json
suggestion for the `phpseclib/bcmath_polyfill` for servers unable
to install PHP the gmp or bcmath extensions.
#### v.2.1.1 & &v.2.0.2 (2018-12)
* add stricter validation around some structures, highlighed
by wycheproof test suite
#### v.2.1.0 (2018-03)
* add support for `bcmath` extension (making `gmp` optional)<br>
https://github.com/fgrosse/PHPASN1/pull/68
#### v.2.0.1 & v.1.5.3 (2017-12)
* add .gitattributes file to prevent examples and tests to be installed via composer when --prefer-dist was set
#### v.2.0.0 (2017-08)
* rename `FG\ASN1\Object` to `FG\ASN1\ASNObject` because `Object` is a special class name in the next major PHP release
- when you upgrade you have to adapt all corresponding `use` and `extends` statements as well as type hints and all
usages of `Object::fromBinary(…)`.
* generally drop PHP 5.6 support
#### v.1.5.2 (2016-10-29)
* allow empty octet strings
#### v.1.5.1 (2015-10-02)
* add keywords to composer.json (this is a version on its own so the keywords are found on a stable version at packagist.org)
#### v.1.5.0 (2015-10-30)
* fix a bug that would prevent you from decoding context specific tags on multiple objects [#57](https://github.com/fgrosse/PHPASN1/issues/57)
- `ExplicitlyTaggedObject::__construct` does now accept multiple objects to be tagged with a single tag
- `ExplicitlyTaggedObject::getContent` will now always return an array (even if only one object is tagged)
#### v.1.4.2 (2015-09-29)
* fix a bug that would prevent you from decoding empty tagged objects [#57](https://github.com/fgrosse/PHPASN1/issues/57)
#### v.1.4.1
* improve exception messages and general error handling [#55](https://github.com/fgrosse/PHPASN1/pull/55)
#### v.1.4.0
* **require PHP 5.6**
* support big integers (closes #1 and #37)
* enforce one code style via [styleci.io][9]
* track code coverage via [coveralls.io][10]
* replace obsolete `FG\ASN1\Exception\GeneralException` with `\Exception`
* `Construct` (`Sequence`, `Set`) does now implement `ArrayAccess`, `Countable` and `Iterator` so its easier to use
* add [`TemplateParser`][11]

19
vendor/fgrosse/phpasn1/LICENSE vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2012-2015 Friedrich Große <friedrich.grosse@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

167
vendor/fgrosse/phpasn1/README.md vendored Normal file
View File

@ -0,0 +1,167 @@
PHPASN1
=======
[![Build Status](https://secure.travis-ci.org/fgrosse/PHPASN1.png?branch=master)](http://travis-ci.org/fgrosse/PHPASN1)
[![PHP 7 ready](http://php7ready.timesplinter.ch/fgrosse/PHPASN1/badge.svg)](https://travis-ci.org/fgrosse/PHPASN1)
[![Coverage Status](https://coveralls.io/repos/fgrosse/PHPASN1/badge.svg?branch=master&service=github)](https://coveralls.io/github/fgrosse/PHPASN1?branch=master)
[![Latest Stable Version](https://poser.pugx.org/fgrosse/phpasn1/v/stable.png)](https://packagist.org/packages/fgrosse/phpasn1)
[![Total Downloads](https://poser.pugx.org/fgrosse/phpasn1/downloads.png)](https://packagist.org/packages/fgrosse/phpasn1)
[![Latest Unstable Version](https://poser.pugx.org/fgrosse/phpasn1/v/unstable.png)](https://packagist.org/packages/fgrosse/phpasn1)
[![License](https://poser.pugx.org/fgrosse/phpasn1/license.png)](https://packagist.org/packages/fgrosse/phpasn1)
A PHP Framework that allows you to encode and decode arbitrary [ASN.1][3] structures
using the [ITU-T X.690 Encoding Rules][4].
This encoding is very frequently used in [X.509 PKI environments][5] or the communication between heterogeneous computer systems.
The API allows you to encode ASN.1 structures to create binary data such as certificate
signing requests (CSR), X.509 certificates or certificate revocation lists (CRL).
PHPASN1 can also read [BER encoded][6] binary data into separate PHP objects that can be manipulated by the user and reencoded afterwards.
The **changelog** can now be found at [CHANGELOG.md](CHANGELOG.md).
## Dependencies
PHPASN1 requires at least `PHP 7.0` and either the `gmp` or `bcmath` extension.
Support for older PHP versions (i.e. PHP 5.6) was dropped starting with `v2.0`.
If you must use an outdated PHP version consider using [PHPASN v1.5][13].
For the loading of object identifier names directly from the web [curl][7] is used.
## Installation
The preferred way to install this library is to rely on [Composer][2]:
```bash
$ composer require fgrosse/phpasn1
```
## Usage
### Encoding ASN.1 Structures
PHPASN1 offers you a class for each of the implemented ASN.1 universal types.
The constructors should be pretty self explanatory so you should have no big trouble getting started.
All data will be encoded using [DER encoding][8]
```php
use FG\ASN1\OID;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\Boolean;
use FG\ASN1\Universal\Enumerated;
use FG\ASN1\Universal\IA5String;
use FG\ASN1\Universal\ObjectIdentifier;
use FG\ASN1\Universal\PrintableString;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\Set;
use FG\ASN1\Universal\NullObject;
$integer = new Integer(123456);
$boolean = new Boolean(true);
$enum = new Enumerated(1);
$ia5String = new IA5String('Hello world');
$asnNull = new NullObject();
$objectIdentifier1 = new ObjectIdentifier('1.2.250.1.16.9');
$objectIdentifier2 = new ObjectIdentifier(OID::RSA_ENCRYPTION);
$printableString = new PrintableString('Foo bar');
$sequence = new Sequence($integer, $boolean, $enum, $ia5String);
$set = new Set($sequence, $asnNull, $objectIdentifier1, $objectIdentifier2, $printableString);
$myBinary = $sequence->getBinary();
$myBinary .= $set->getBinary();
echo base64_encode($myBinary);
```
### Decoding binary data
Decoding BER encoded binary data is just as easy as encoding it:
```php
use FG\ASN1\ASNObject;
$base64String = ...
$binaryData = base64_decode($base64String);
$asnObject = ASNObject::fromBinary($binaryData);
// do stuff
```
If you already know exactly how your expected data should look like you can use the `FG\ASN1\TemplateParser`:
```php
use FG\ASN1\TemplateParser;
// first define your template
$template = [
Identifier::SEQUENCE => [
Identifier::SET => [
Identifier::OBJECT_IDENTIFIER,
Identifier::SEQUENCE => [
Identifier::INTEGER,
Identifier::BITSTRING,
]
]
]
];
// if your binary data is not matching the template you provided this will throw an `\Exception`:
$parser = new TemplateParser();
$object = $parser->parseBinary($data, $template);
// there is also a convenience function if you parse binary data from base64:
$object = $parser->parseBase64($data, $template);
```
You can use this function to make sure your data has exactly the format you are expecting.
### Navigating decoded data
All constructed classes (i.e. `Sequence` and `Set`) can be navigated by array access or using an iterator.
You can find examples
[here](https://github.com/fgrosse/PHPASN1/blob/f6442cadda9d36f3518c737e32f28300a588b777/tests/ASN1/Universal/SequenceTest.php#L148-148),
[here](https://github.com/fgrosse/PHPASN1/blob/f6442cadda9d36f3518c737e32f28300a588b777/tests/ASN1/Universal/SequenceTest.php#L121) and
[here](https://github.com/fgrosse/PHPASN1/blob/f6442cadda9d36f3518c737e32f28300a588b777/tests/ASN1/TemplateParserTest.php#L45).
### Give me more examples!
To see some example usage of the API classes or some generated output check out the [examples](https://github.com/fgrosse/PHPASN1/tree/master/examples).
### How do I contribute?
If you found an issue or have a question submit a github issue with detailed information.
In case you already know what caused the issue and feel in the mood to fix it, your code contributions are always welcome. Just fork the repository, implement your changes and make sure that you covered everything with tests.
Afterwards submit a pull request via github and be a little patient :) I usually try to comment and/or merge as soon as possible.
#### Mailing list
New features or questions can be discussed in [this google group/mailing list][12].
### Thanks
To [all contributors][1] so far!
## License
This library is distributed under the [MIT License](LICENSE).
[1]: https://github.com/fgrosse/PHPASN1/graphs/contributors
[2]: https://getcomposer.org/
[3]: http://www.itu.int/ITU-T/asn1/
[4]: http://www.itu.int/ITU-T/recommendations/rec.aspx?rec=x.690
[5]: http://en.wikipedia.org/wiki/X.509
[6]: http://en.wikipedia.org/wiki/X.690#BER_encoding
[7]: http://php.net/manual/en/book.curl.php
[8]: http://en.wikipedia.org/wiki/X.690#DER_encoding
[9]: https://styleci.io
[10]: https://coveralls.io/github/fgrosse/PHPASN1
[11]: https://github.com/fgrosse/PHPASN1/blob/master/tests/ASN1/TemplateParserTest.php#L16
[12]: https://groups.google.com/d/forum/phpasn1
[13]: https://packagist.org/packages/fgrosse/phpasn1#1.5.2

49
vendor/fgrosse/phpasn1/composer.json vendored Normal file
View File

@ -0,0 +1,49 @@
{
"name": "fgrosse/phpasn1",
"description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.",
"type": "library",
"homepage": "https://github.com/FGrosse/PHPASN1",
"license": "MIT",
"authors": [
{
"name": "Friedrich Große",
"email": "friedrich.grosse@gmail.com",
"homepage": "https://github.com/FGrosse",
"role": "Author"
},
{
"name": "All contributors",
"homepage": "https://github.com/FGrosse/PHPASN1/contributors"
}
],
"keywords": [ "x690", "x.690", "x.509", "x509", "asn1", "asn.1", "ber", "der", "binary", "encoding", "decoding" ],
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"phpunit/phpunit": "~6.3",
"satooshi/php-coveralls": "~2.0"
},
"suggest": {
"ext-gmp": "GMP is the preferred extension for big integer calculations",
"ext-bcmath": "BCmath is the fallback extension for big integer calculations",
"phpseclib/bcmath_compat": "BCmath polyfill for servers where neither GMP nor BCmath is available",
"ext-curl": "For loading OID information from the web if they have not bee defined statically"
},
"autoload": {
"psr-4": {
"FG\\": "lib/"
}
},
"autoload-dev": {
"psr-4": {
"FG\\Test\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
}
}

View File

@ -0,0 +1,355 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\Boolean;
use FG\ASN1\Universal\Enumerated;
use FG\ASN1\Universal\GeneralizedTime;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\NullObject;
use FG\ASN1\Universal\ObjectIdentifier;
use FG\ASN1\Universal\RelativeObjectIdentifier;
use FG\ASN1\Universal\OctetString;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\Set;
use FG\ASN1\Universal\UTCTime;
use FG\ASN1\Universal\IA5String;
use FG\ASN1\Universal\PrintableString;
use FG\ASN1\Universal\NumericString;
use FG\ASN1\Universal\UTF8String;
use FG\ASN1\Universal\UniversalString;
use FG\ASN1\Universal\CharacterString;
use FG\ASN1\Universal\GeneralString;
use FG\ASN1\Universal\VisibleString;
use FG\ASN1\Universal\GraphicString;
use FG\ASN1\Universal\BMPString;
use FG\ASN1\Universal\T61String;
use FG\ASN1\Universal\ObjectDescriptor;
use FG\Utility\BigInteger;
use LogicException;
/**
* Class ASNObject is the base class for all concrete ASN.1 objects.
*/
abstract class ASNObject implements Parsable
{
private $contentLength;
private $nrOfLengthOctets;
/**
* Must return the number of octets of the content part.
*
* @return int
*/
abstract protected function calculateContentLength();
/**
* Encode the object using DER encoding.
*
* @see http://en.wikipedia.org/wiki/X.690#DER_encoding
*
* @return string the binary representation of an objects value
*/
abstract protected function getEncodedValue();
/**
* Return the content of this object in a non encoded form.
* This can be used to print the value in human readable form.
*
* @return mixed
*/
abstract public function getContent();
/**
* Return the object type octet.
* This should use the class constants of Identifier.
*
* @see Identifier
*
* @return int
*/
abstract public function getType();
/**
* Returns all identifier octets. If an inheriting class models a tag with
* the long form identifier format, it MUST reimplement this method to
* return all octets of the identifier.
*
* @throws LogicException If the identifier format is long form
*
* @return string Identifier as a set of octets
*/
public function getIdentifier()
{
$firstOctet = $this->getType();
if (Identifier::isLongForm($firstOctet)) {
throw new LogicException(sprintf('Identifier of %s uses the long form and must therefor override "ASNObject::getIdentifier()".', get_class($this)));
}
return chr($firstOctet);
}
/**
* Encode this object using DER encoding.
*
* @return string the full binary representation of the complete object
*/
public function getBinary()
{
$result = $this->getIdentifier();
$result .= $this->createLengthPart();
$result .= $this->getEncodedValue();
return $result;
}
private function createLengthPart()
{
$contentLength = $this->getContentLength();
$nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
if ($nrOfLengthOctets == 1) {
return chr($contentLength);
} else {
// the first length octet determines the number subsequent length octets
$lengthOctets = chr(0x80 | ($nrOfLengthOctets - 1));
for ($shiftLength = 8 * ($nrOfLengthOctets - 2); $shiftLength >= 0; $shiftLength -= 8) {
$lengthOctets .= chr($contentLength >> $shiftLength);
}
return $lengthOctets;
}
}
protected function getNumberOfLengthOctets($contentLength = null)
{
if (!isset($this->nrOfLengthOctets)) {
if ($contentLength == null) {
$contentLength = $this->getContentLength();
}
$this->nrOfLengthOctets = 1;
if ($contentLength > 127) {
do { // long form
$this->nrOfLengthOctets++;
$contentLength = $contentLength >> 8;
} while ($contentLength > 0);
}
}
return $this->nrOfLengthOctets;
}
protected function getContentLength()
{
if (!isset($this->contentLength)) {
$this->contentLength = $this->calculateContentLength();
}
return $this->contentLength;
}
protected function setContentLength($newContentLength)
{
$this->contentLength = $newContentLength;
$this->getNumberOfLengthOctets($newContentLength);
}
/**
* Returns the length of the whole object (including the identifier and length octets).
*/
public function getObjectLength()
{
$nrOfIdentifierOctets = strlen($this->getIdentifier());
$contentLength = $this->getContentLength();
$nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
return $nrOfIdentifierOctets + $nrOfLengthOctets + $contentLength;
}
public function __toString()
{
return $this->getContent();
}
/**
* Returns the name of the ASN.1 Type of this object.
*
* @see Identifier::getName()
*/
public function getTypeName()
{
return Identifier::getName($this->getType());
}
/**
* @param string $binaryData
* @param int $offsetIndex
*
* @throws ParserException
*
* @return \FG\ASN1\ASNObject
*/
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse binary from data: Offset index larger than input size', $offsetIndex);
}
$identifierOctet = ord($binaryData[$offsetIndex]);
if (Identifier::isContextSpecificClass($identifierOctet) && Identifier::isConstructed($identifierOctet)) {
return ExplicitlyTaggedObject::fromBinary($binaryData, $offsetIndex);
}
switch ($identifierOctet) {
case Identifier::BITSTRING:
return BitString::fromBinary($binaryData, $offsetIndex);
case Identifier::BOOLEAN:
return Boolean::fromBinary($binaryData, $offsetIndex);
case Identifier::ENUMERATED:
return Enumerated::fromBinary($binaryData, $offsetIndex);
case Identifier::INTEGER:
return Integer::fromBinary($binaryData, $offsetIndex);
case Identifier::NULL:
return NullObject::fromBinary($binaryData, $offsetIndex);
case Identifier::OBJECT_IDENTIFIER:
return ObjectIdentifier::fromBinary($binaryData, $offsetIndex);
case Identifier::RELATIVE_OID:
return RelativeObjectIdentifier::fromBinary($binaryData, $offsetIndex);
case Identifier::OCTETSTRING:
return OctetString::fromBinary($binaryData, $offsetIndex);
case Identifier::SEQUENCE:
return Sequence::fromBinary($binaryData, $offsetIndex);
case Identifier::SET:
return Set::fromBinary($binaryData, $offsetIndex);
case Identifier::UTC_TIME:
return UTCTime::fromBinary($binaryData, $offsetIndex);
case Identifier::GENERALIZED_TIME:
return GeneralizedTime::fromBinary($binaryData, $offsetIndex);
case Identifier::IA5_STRING:
return IA5String::fromBinary($binaryData, $offsetIndex);
case Identifier::PRINTABLE_STRING:
return PrintableString::fromBinary($binaryData, $offsetIndex);
case Identifier::NUMERIC_STRING:
return NumericString::fromBinary($binaryData, $offsetIndex);
case Identifier::UTF8_STRING:
return UTF8String::fromBinary($binaryData, $offsetIndex);
case Identifier::UNIVERSAL_STRING:
return UniversalString::fromBinary($binaryData, $offsetIndex);
case Identifier::CHARACTER_STRING:
return CharacterString::fromBinary($binaryData, $offsetIndex);
case Identifier::GENERAL_STRING:
return GeneralString::fromBinary($binaryData, $offsetIndex);
case Identifier::VISIBLE_STRING:
return VisibleString::fromBinary($binaryData, $offsetIndex);
case Identifier::GRAPHIC_STRING:
return GraphicString::fromBinary($binaryData, $offsetIndex);
case Identifier::BMP_STRING:
return BMPString::fromBinary($binaryData, $offsetIndex);
case Identifier::T61_STRING:
return T61String::fromBinary($binaryData, $offsetIndex);
case Identifier::OBJECT_DESCRIPTOR:
return ObjectDescriptor::fromBinary($binaryData, $offsetIndex);
default:
// At this point the identifier may be >1 byte.
if (Identifier::isConstructed($identifierOctet)) {
return new UnknownConstructedObject($binaryData, $offsetIndex);
} else {
$identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
$lengthOfUnknownObject = self::parseContentLength($binaryData, $offsetIndex);
$offsetIndex += $lengthOfUnknownObject;
return new UnknownObject($identifier, $lengthOfUnknownObject);
}
}
}
protected static function parseIdentifier($identifierOctet, $expectedIdentifier, $offsetForExceptionHandling)
{
if (is_string($identifierOctet) || is_numeric($identifierOctet) == false) {
$identifierOctet = ord($identifierOctet);
}
if ($identifierOctet != $expectedIdentifier) {
$message = 'Can not create an '.Identifier::getName($expectedIdentifier).' from an '.Identifier::getName($identifierOctet);
throw new ParserException($message, $offsetForExceptionHandling);
}
}
protected static function parseBinaryIdentifier($binaryData, &$offsetIndex)
{
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse identifier from data: Offset index larger than input size', $offsetIndex);
}
$identifier = $binaryData[$offsetIndex++];
if (Identifier::isLongForm(ord($identifier)) == false) {
return $identifier;
}
while (true) {
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse identifier (long form) from data: Offset index larger than input size', $offsetIndex);
}
$nextOctet = $binaryData[$offsetIndex++];
$identifier .= $nextOctet;
if ((ord($nextOctet) & 0x80) === 0) {
// the most significant bit is 0 to we have reached the end of the identifier
break;
}
}
return $identifier;
}
protected static function parseContentLength(&$binaryData, &$offsetIndex, $minimumLength = 0)
{
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse content length from data: Offset index larger than input size', $offsetIndex);
}
$contentLength = ord($binaryData[$offsetIndex++]);
if (($contentLength & 0x80) != 0) {
// bit 8 is set -> this is the long form
$nrOfLengthOctets = $contentLength & 0x7F;
$contentLength = BigInteger::create(0x00);
for ($i = 0; $i < $nrOfLengthOctets; $i++) {
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse content length (long form) from data: Offset index larger than input size', $offsetIndex);
}
$contentLength = $contentLength->shiftLeft(8)->add(ord($binaryData[$offsetIndex++]));
}
if ($contentLength->compare(PHP_INT_MAX) > 0) {
throw new ParserException("Can not parse content length from data: length > maximum integer", $offsetIndex);
}
$contentLength = $contentLength->toInteger();
}
if ($contentLength < $minimumLength) {
throw new ParserException('A '.get_called_class()." should have a content length of at least {$minimumLength}. Extracted length was {$contentLength}", $offsetIndex);
}
$lenDataRemaining = strlen($binaryData) - $offsetIndex;
if ($lenDataRemaining < $contentLength) {
throw new ParserException("Content length {$contentLength} exceeds remaining data length {$lenDataRemaining}", $offsetIndex);
}
return $contentLength;
}
}

View File

@ -0,0 +1,136 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use Exception;
abstract class AbstractString extends ASNObject implements Parsable
{
/** @var string */
protected $value;
private $checkStringForIllegalChars = true;
private $allowedCharacters = [];
/**
* The abstract base class for ASN.1 classes which represent some string of character.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
}
public function getContent()
{
return $this->value;
}
protected function allowCharacter($character)
{
$this->allowedCharacters[] = $character;
}
protected function allowCharacters(...$characters)
{
foreach ($characters as $character) {
$this->allowedCharacters[] = $character;
}
}
protected function allowNumbers()
{
foreach (range('0', '9') as $char) {
$this->allowedCharacters[] = (string) $char;
}
}
protected function allowAllLetters()
{
$this->allowSmallLetters();
$this->allowCapitalLetters();
}
protected function allowSmallLetters()
{
foreach (range('a', 'z') as $char) {
$this->allowedCharacters[] = $char;
}
}
protected function allowCapitalLetters()
{
foreach (range('A', 'Z') as $char) {
$this->allowedCharacters[] = $char;
}
}
protected function allowSpaces()
{
$this->allowedCharacters[] = ' ';
}
protected function allowAll()
{
$this->checkStringForIllegalChars = false;
}
protected function calculateContentLength()
{
return strlen($this->value);
}
protected function getEncodedValue()
{
if ($this->checkStringForIllegalChars) {
$this->checkString();
}
return $this->value;
}
protected function checkString()
{
$stringLength = $this->getContentLength();
for ($i = 0; $i < $stringLength; $i++) {
if (in_array($this->value[$i], $this->allowedCharacters) == false) {
$typeName = Identifier::getName($this->getType());
throw new Exception("Could not create a {$typeName} from the character sequence '{$this->value}'.");
}
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$parsedObject = new static('');
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$string = substr($binaryData, $offsetIndex, $contentLength);
$offsetIndex += $contentLength;
$parsedObject->value = $string;
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
public static function isValid($string)
{
$testObject = new static($string);
try {
$testObject->checkString();
return true;
} catch (Exception $exception) {
return false;
}
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;
abstract class AbstractTime extends ASNObject
{
/** @var DateTime */
protected $value;
public function __construct($dateTime = null, $dateTimeZone = 'UTC')
{
if ($dateTime == null || is_string($dateTime)) {
$timeZone = new DateTimeZone($dateTimeZone);
$dateTimeObject = new DateTime($dateTime, $timeZone);
if ($dateTimeObject == false) {
$errorMessage = $this->getLastDateTimeErrors();
$className = Identifier::getName($this->getType());
throw new Exception(sprintf("Could not create %s from date time string '%s': %s", $className, $dateTime, $errorMessage));
}
$dateTime = $dateTimeObject;
} elseif (!$dateTime instanceof DateTime) {
throw new Exception('Invalid first argument for some instance of AbstractTime constructor');
}
$this->value = $dateTime;
}
public function getContent()
{
return $this->value;
}
protected function getLastDateTimeErrors()
{
$messages = '';
$lastErrors = DateTime::getLastErrors();
foreach ($lastErrors['errors'] as $errorMessage) {
$messages .= "{$errorMessage}, ";
}
return substr($messages, 0, -2);
}
public function __toString()
{
return $this->value->format("Y-m-d\tH:i:s");
}
protected static function extractTimeZoneData(&$binaryData, &$offsetIndex, DateTime $dateTime)
{
$sign = $binaryData[$offsetIndex++];
$timeOffsetHours = intval(substr($binaryData, $offsetIndex, 2));
$timeOffsetMinutes = intval(substr($binaryData, $offsetIndex + 2, 2));
$offsetIndex += 4;
$interval = new DateInterval("PT{$timeOffsetHours}H{$timeOffsetMinutes}M");
if ($sign == '+') {
$dateTime->sub($interval);
} else {
$dateTime->add($interval);
}
return $dateTime;
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace FG\ASN1;
use FG\Utility\BigInteger;
use InvalidArgumentException;
/**
* A base-128 decoder.
*/
class Base128
{
/**
* @param int $value
*
* @return string
*/
public static function encode($value)
{
$value = BigInteger::create($value);
$octets = chr($value->modulus(0x80)->toInteger());
$value = $value->shiftRight(7);
while ($value->compare(0) > 0) {
$octets .= chr(0x80 | $value->modulus(0x80)->toInteger());
$value = $value->shiftRight(7);
}
return strrev($octets);
}
/**
* @param string $octets
*
* @throws InvalidArgumentException if the given octets represent a malformed base-128 value or the decoded value would exceed the the maximum integer length
*
* @return int
*/
public static function decode($octets)
{
$bitsPerOctet = 7;
$value = BigInteger::create(0);
$i = 0;
while (true) {
if (!isset($octets[$i])) {
throw new InvalidArgumentException(sprintf('Malformed base-128 encoded value (0x%s).', strtoupper(bin2hex($octets)) ?: '0'));
}
$octet = ord($octets[$i++]);
$l1 = $value->shiftLeft($bitsPerOctet);
$r1 = $octet & 0x7f;
$value = $l1->add($r1);
if (0 === ($octet & 0x80)) {
break;
}
}
return (string)$value;
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Composite;
use FG\ASN1\ASNObject;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\ObjectIdentifier;
class AttributeTypeAndValue extends Sequence
{
/**
* @param ObjectIdentifier|string $objIdentifier
* @param \FG\ASN1\ASNObject $value
*/
public function __construct($objIdentifier, ASNObject $value)
{
if ($objIdentifier instanceof ObjectIdentifier == false) {
$objIdentifier = new ObjectIdentifier($objIdentifier);
}
parent::__construct($objIdentifier, $value);
}
public function __toString()
{
return $this->children[0].': '.$this->children[1];
}
}

View File

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Composite;
use FG\ASN1\Universal\PrintableString;
use FG\ASN1\Universal\IA5String;
use FG\ASN1\Universal\UTF8String;
class RDNString extends RelativeDistinguishedName
{
/**
* @param string|\FG\ASN1\Universal\ObjectIdentifier $objectIdentifierString
* @param string|\FG\ASN1\ASNObject $value
*/
public function __construct($objectIdentifierString, $value)
{
if (PrintableString::isValid($value)) {
$value = new PrintableString($value);
} else {
if (IA5String::isValid($value)) {
$value = new IA5String($value);
} else {
$value = new UTF8String($value);
}
}
parent::__construct($objectIdentifierString, $value);
}
}

View File

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Composite;
use FG\ASN1\Exception\NotImplementedException;
use FG\ASN1\ASNObject;
use FG\ASN1\Universal\Set;
class RelativeDistinguishedName extends Set
{
/**
* @param string|\FG\ASN1\Universal\ObjectIdentifier $objIdentifierString
* @param \FG\ASN1\ASNObject $value
*/
public function __construct($objIdentifierString, ASNObject $value)
{
// TODO: This does only support one element in the RelativeDistinguishedName Set but it it is defined as follows:
// RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
parent::__construct(new AttributeTypeAndValue($objIdentifierString, $value));
}
public function getContent()
{
/** @var \FG\ASN1\ASNObject $firstObject */
$firstObject = $this->children[0];
return $firstObject->__toString();
}
/**
* At the current version this code can not work since the implementation of Construct requires
* the class to support a constructor without arguments.
*
* @deprecated this function is not yet implemented! Feel free to submit a pull request on github
* @param string $binaryData
* @param int $offsetIndex
* @throws NotImplementedException
*/
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,191 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use ArrayAccess;
use ArrayIterator;
use Countable;
use FG\ASN1\Exception\ParserException;
use Iterator;
abstract class Construct extends ASNObject implements Countable, ArrayAccess, Iterator, Parsable
{
/** @var \FG\ASN1\ASNObject[] */
protected $children;
private $iteratorPosition;
/**
* @param \FG\ASN1\ASNObject[] $children the variadic type hint is commented due to https://github.com/facebook/hhvm/issues/4858
*/
public function __construct(/* HH_FIXME[4858]: variadic + strict */ ...$children)
{
$this->children = $children;
$this->iteratorPosition = 0;
}
public function getContent()
{
return $this->children;
}
public function rewind()
{
$this->iteratorPosition = 0;
}
public function current()
{
return $this->children[$this->iteratorPosition];
}
public function key()
{
return $this->iteratorPosition;
}
public function next()
{
$this->iteratorPosition++;
}
public function valid()
{
return isset($this->children[$this->iteratorPosition]);
}
public function offsetExists($offset)
{
return array_key_exists($offset, $this->children);
}
public function offsetGet($offset)
{
return $this->children[$offset];
}
public function offsetSet($offset, $value)
{
if ($offset === null) {
$offset = count($this->children);
}
$this->children[$offset] = $value;
}
public function offsetUnset($offset)
{
unset($this->children[$offset]);
}
protected function calculateContentLength()
{
$length = 0;
foreach ($this->children as $component) {
$length += $component->getObjectLength();
}
return $length;
}
protected function getEncodedValue()
{
$result = '';
foreach ($this->children as $component) {
$result .= $component->getBinary();
}
return $result;
}
public function addChild(ASNObject $child)
{
$this->children[] = $child;
}
public function addChildren(array $children)
{
foreach ($children as $child) {
$this->addChild($child);
}
}
public function __toString()
{
$nrOfChildren = $this->getNumberOfChildren();
$childString = $nrOfChildren == 1 ? 'child' : 'children';
return "[{$nrOfChildren} {$childString}]";
}
public function getNumberOfChildren()
{
return count($this->children);
}
/**
* @return \FG\ASN1\ASNObject[]
*/
public function getChildren()
{
return $this->children;
}
/**
* @return \FG\ASN1\ASNObject
*/
public function getFirstChild()
{
return $this->children[0];
}
/**
* @param string $binaryData
* @param int $offsetIndex
*
* @throws Exception\ParserException
*
* @return Construct|static
*/
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$parsedObject = new static();
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$startIndex = $offsetIndex;
$children = [];
$octetsToRead = $contentLength;
while ($octetsToRead > 0) {
$newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
$octetsToRead -= $newChild->getObjectLength();
$children[] = $newChild;
}
if ($octetsToRead !== 0) {
throw new ParserException("Sequence length incorrect", $startIndex);
}
$parsedObject->addChildren($children);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
public function count($mode = COUNT_NORMAL)
{
return count($this->children, $mode);
}
public function getIterator()
{
return new ArrayIterator($this->children);
}
}

View File

@ -0,0 +1,15 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Exception;
class NotImplementedException extends \Exception
{
}

View File

@ -0,0 +1,29 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Exception;
class ParserException extends \Exception
{
private $errorMessage;
private $offset;
public function __construct($errorMessage, $offset)
{
$this->errorMessage = $errorMessage;
$this->offset = $offset;
parent::__construct("ASN.1 Parser Exception at offset {$this->offset}: {$this->errorMessage}");
}
public function getOffset()
{
return $this->offset;
}
}

View File

@ -0,0 +1,131 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use FG\ASN1\Exception\ParserException;
/**
* Class ExplicitlyTaggedObject decorate an inner object with an additional tag that gives information about
* its context specific meaning.
*
* Explanation taken from A Layman's Guide to a Subset of ASN.1, BER, and DER:
* >>> An RSA Laboratories Technical Note
* >>> Burton S. Kaliski Jr.
* >>> Revised November 1, 1993
*
* [...]
* Explicitly tagged types are derived from other types by adding an outer tag to the underlying type.
* In effect, explicitly tagged types are structured types consisting of one component, the underlying type.
* Explicit tagging is denoted by the ASN.1 keywords [class number] EXPLICIT (see Section 5.2).
* [...]
*
* @see http://luca.ntop.org/Teaching/Appunti/asn1.html
*/
class ExplicitlyTaggedObject extends ASNObject
{
/** @var \FG\ASN1\ASNObject[] */
private $decoratedObjects;
private $tag;
/**
* @param int $tag
* @param \FG\ASN1\ASNObject $objects,...
*/
public function __construct($tag, /* HH_FIXME[4858]: variadic + strict */ ...$objects)
{
$this->tag = $tag;
$this->decoratedObjects = $objects;
}
protected function calculateContentLength()
{
$length = 0;
foreach ($this->decoratedObjects as $object) {
$length += $object->getObjectLength();
}
return $length;
}
protected function getEncodedValue()
{
$encoded = '';
foreach ($this->decoratedObjects as $object) {
$encoded .= $object->getBinary();
}
return $encoded;
}
public function getContent()
{
return $this->decoratedObjects;
}
public function __toString()
{
switch ($length = count($this->decoratedObjects)) {
case 0:
return "Context specific empty object with tag [{$this->tag}]";
case 1:
$decoratedType = Identifier::getShortName($this->decoratedObjects[0]->getType());
return "Context specific $decoratedType with tag [{$this->tag}]";
default:
return "$length context specific objects with tag [{$this->tag}]";
}
}
public function getType()
{
return ord($this->getIdentifier());
}
public function getIdentifier()
{
$identifier = Identifier::create(Identifier::CLASS_CONTEXT_SPECIFIC, true, $this->tag);
return is_int($identifier) ? chr($identifier) : $identifier;
}
public function getTag()
{
return $this->tag;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
$firstIdentifierOctet = ord($identifier);
assert(Identifier::isContextSpecificClass($firstIdentifierOctet), 'identifier octet should indicate context specific class');
assert(Identifier::isConstructed($firstIdentifierOctet), 'identifier octet should indicate constructed object');
$tag = Identifier::getTagNumber($identifier);
$totalContentLength = self::parseContentLength($binaryData, $offsetIndex);
$remainingContentLength = $totalContentLength;
$offsetIndexOfDecoratedObject = $offsetIndex;
$decoratedObjects = [];
while ($remainingContentLength > 0) {
$nextObject = ASNObject::fromBinary($binaryData, $offsetIndex);
$remainingContentLength -= $nextObject->getObjectLength();
$decoratedObjects[] = $nextObject;
}
if ($remainingContentLength != 0) {
throw new ParserException("Context-Specific explicitly tagged object [$tag] starting at offset $offsetIndexOfDecoratedObject specifies a length of $totalContentLength octets but $remainingContentLength remain after parsing the content", $offsetIndexOfDecoratedObject);
}
$parsedObject = new self($tag, ...$decoratedObjects);
$parsedObject->setContentLength($totalContentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,339 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use Exception;
/**
* The Identifier encodes the ASN.1 tag (class and number) of the type of a data value.
*
* Every identifier whose number is in the range 0 to 30 has the following structure:
*
* Bits: 8 7 6 5 4 3 2 1
* | Class | P/C | Tag number |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Bits 8 and 7 define the class of this type ( Universal, Application, Context-specific or Private).
* Bit 6 encoded whether this type is primitive or constructed
* The remaining bits 5 - 1 encode the tag number
*/
class Identifier
{
const CLASS_UNIVERSAL = 0x00;
const CLASS_APPLICATION = 0x01;
const CLASS_CONTEXT_SPECIFIC = 0x02;
const CLASS_PRIVATE = 0x03;
const EOC = 0x00; // unsupported for now
const BOOLEAN = 0x01;
const INTEGER = 0x02;
const BITSTRING = 0x03;
const OCTETSTRING = 0x04;
const NULL = 0x05;
const OBJECT_IDENTIFIER = 0x06;
const OBJECT_DESCRIPTOR = 0x07;
const EXTERNAL = 0x08; // unsupported for now
const REAL = 0x09; // unsupported for now
const ENUMERATED = 0x0A;
const EMBEDDED_PDV = 0x0B; // unsupported for now
const UTF8_STRING = 0x0C;
const RELATIVE_OID = 0x0D;
// value 0x0E and 0x0F are reserved for future use
const SEQUENCE = 0x30;
const SET = 0x31;
const NUMERIC_STRING = 0x12;
const PRINTABLE_STRING = 0x13;
const T61_STRING = 0x14; // sometimes referred to as TeletextString
const VIDEOTEXT_STRING = 0x15;
const IA5_STRING = 0x16;
const UTC_TIME = 0x17;
const GENERALIZED_TIME = 0x18;
const GRAPHIC_STRING = 0x19;
const VISIBLE_STRING = 0x1A;
const GENERAL_STRING = 0x1B;
const UNIVERSAL_STRING = 0x1C;
const CHARACTER_STRING = 0x1D; // Unrestricted character type
const BMP_STRING = 0x1E;
const LONG_FORM = 0x1F;
const IS_CONSTRUCTED = 0x20;
/**
* Creates an identifier. Short form identifiers are returned as integers
* for BC, long form identifiers will be returned as a string of octets.
*
* @param int $class
* @param bool $isConstructed
* @param int $tagNumber
*
* @throws Exception if the given arguments are invalid
*
* @return int|string
*/
public static function create($class, $isConstructed, $tagNumber)
{
if (!is_numeric($class) || $class < self::CLASS_UNIVERSAL || $class > self::CLASS_PRIVATE) {
throw new Exception(sprintf('Invalid class %d given', $class));
}
if (!is_bool($isConstructed)) {
throw new Exception("\$isConstructed must be a boolean value ($isConstructed given)");
}
$tagNumber = self::makeNumeric($tagNumber);
if ($tagNumber < 0) {
throw new Exception(sprintf('Invalid $tagNumber %d given. You can only use positive integers.', $tagNumber));
}
if ($tagNumber < self::LONG_FORM) {
return ($class << 6) | ($isConstructed << 5) | $tagNumber;
}
$firstOctet = ($class << 6) | ($isConstructed << 5) | self::LONG_FORM;
// Tag numbers formatted in long form are base-128 encoded. See X.609#8.1.2.4
return chr($firstOctet).Base128::encode($tagNumber);
}
public static function isConstructed($identifierOctet)
{
return ($identifierOctet & self::IS_CONSTRUCTED) === self::IS_CONSTRUCTED;
}
public static function isLongForm($identifierOctet)
{
return ($identifierOctet & self::LONG_FORM) === self::LONG_FORM;
}
/**
* Return the name of the mapped ASN.1 type with a preceding "ASN.1 ".
*
* Example: ASN.1 Octet String
*
* @see Identifier::getShortName()
*
* @param int|string $identifier
*
* @return string
*/
public static function getName($identifier)
{
$identifierOctet = self::makeNumeric($identifier);
$typeName = static::getShortName($identifier);
if (($identifierOctet & self::LONG_FORM) < self::LONG_FORM) {
$typeName = "ASN.1 {$typeName}";
}
return $typeName;
}
/**
* Return the short version of the type name.
*
* If the given identifier octet can be mapped to a known universal type this will
* return its name. Else Identifier::getClassDescription() is used to retrieve
* information about the identifier.
*
* @see Identifier::getName()
* @see Identifier::getClassDescription()
*
* @param int|string $identifier
*
* @return string
*/
public static function getShortName($identifier)
{
$identifierOctet = self::makeNumeric($identifier);
switch ($identifierOctet) {
case self::EOC:
return 'End-of-contents octet';
case self::BOOLEAN:
return 'Boolean';
case self::INTEGER:
return 'Integer';
case self::BITSTRING:
return 'Bit String';
case self::OCTETSTRING:
return 'Octet String';
case self::NULL:
return 'NULL';
case self::OBJECT_IDENTIFIER:
return 'Object Identifier';
case self::OBJECT_DESCRIPTOR:
return 'Object Descriptor';
case self::EXTERNAL:
return 'External Type';
case self::REAL:
return 'Real';
case self::ENUMERATED:
return 'Enumerated';
case self::EMBEDDED_PDV:
return 'Embedded PDV';
case self::UTF8_STRING:
return 'UTF8 String';
case self::RELATIVE_OID:
return 'Relative OID';
case self::SEQUENCE:
return 'Sequence';
case self::SET:
return 'Set';
case self::NUMERIC_STRING:
return 'Numeric String';
case self::PRINTABLE_STRING:
return 'Printable String';
case self::T61_STRING:
return 'T61 String';
case self::VIDEOTEXT_STRING:
return 'Videotext String';
case self::IA5_STRING:
return 'IA5 String';
case self::UTC_TIME:
return 'UTC Time';
case self::GENERALIZED_TIME:
return 'Generalized Time';
case self::GRAPHIC_STRING:
return 'Graphic String';
case self::VISIBLE_STRING:
return 'Visible String';
case self::GENERAL_STRING:
return 'General String';
case self::UNIVERSAL_STRING:
return 'Universal String';
case self::CHARACTER_STRING:
return 'Character String';
case self::BMP_STRING:
return 'BMP String';
case 0x0E:
return 'RESERVED (0x0E)';
case 0x0F:
return 'RESERVED (0x0F)';
case self::LONG_FORM:
default:
$classDescription = self::getClassDescription($identifier);
if (is_int($identifier)) {
$identifier = chr($identifier);
}
return "$classDescription (0x".strtoupper(bin2hex($identifier)).')';
}
}
/**
* Returns a textual description of the information encoded in a given identifier octet.
*
* The first three (most significant) bytes are evaluated to determine if this is a
* constructed or primitive type and if it is either universal, application, context-specific or
* private.
*
* Example:
* Constructed context-specific
* Primitive universal
*
* @param int|string $identifier
*
* @return string
*/
public static function getClassDescription($identifier)
{
$identifierOctet = self::makeNumeric($identifier);
if (self::isConstructed($identifierOctet)) {
$classDescription = 'Constructed ';
} else {
$classDescription = 'Primitive ';
}
$classBits = $identifierOctet >> 6;
switch ($classBits) {
case self::CLASS_UNIVERSAL:
$classDescription .= 'universal';
break;
case self::CLASS_APPLICATION:
$classDescription .= 'application';
break;
case self::CLASS_CONTEXT_SPECIFIC:
$tagNumber = self::getTagNumber($identifier);
$classDescription = "[$tagNumber] Context-specific";
break;
case self::CLASS_PRIVATE:
$classDescription .= 'private';
break;
default:
return "INVALID IDENTIFIER OCTET: {$identifierOctet}";
}
return $classDescription;
}
/**
* @param int|string $identifier
*
* @return int
*/
public static function getTagNumber($identifier)
{
$firstOctet = self::makeNumeric($identifier);
$tagNumber = $firstOctet & self::LONG_FORM;
if ($tagNumber < self::LONG_FORM) {
return $tagNumber;
}
if (is_numeric($identifier)) {
$identifier = chr($identifier);
}
return Base128::decode(substr($identifier, 1));
}
public static function isUniversalClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_UNIVERSAL;
}
public static function isApplicationClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_APPLICATION;
}
public static function isContextSpecificClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_CONTEXT_SPECIFIC;
}
public static function isPrivateClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_PRIVATE;
}
private static function makeNumeric($identifierOctet)
{
if (!is_numeric($identifierOctet)) {
return ord($identifierOctet);
} else {
return $identifierOctet;
}
}
}

198
vendor/fgrosse/phpasn1/lib/ASN1/OID.php vendored Normal file
View File

@ -0,0 +1,198 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
class OID
{
const RSA_ENCRYPTION = '1.2.840.113549.1.1.1';
const MD5_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.4';
const SHA1_WITH_RSA_SIGNATURE = '1.2.840.113549.1.1.5';
const PKCS9_EMAIL = '1.2.840.113549.1.9.1';
const PKCS9_UNSTRUCTURED_NAME = '1.2.840.113549.1.9.2';
const PKCS9_CONTENT_TYPE = '1.2.840.113549.1.9.3';
const PKCS9_MESSAGE_DIGEST = '1.2.840.113549.1.9.4';
const PKCS9_SIGNING_TIME = '1.2.840.113549.1.9.5';
const PKCS9_EXTENSION_REQUEST = '1.2.840.113549.1.9.14';
// certificate extension identifier
const CERT_EXT_SUBJECT_DIRECTORY_ATTR = '2.5.29.9';
const CERT_EXT_SUBJECT_KEY_IDENTIFIER = '2.5.29.14';
const CERT_EXT_KEY_USAGE = '2.5.29.15';
const CERT_EXT_PRIVATE_KEY_USAGE_PERIOD = '2.5.29.16';
const CERT_EXT_SUBJECT_ALT_NAME = '2.5.29.17';
const CERT_EXT_ISSUER_ALT_NAME = '2.5.29.18';
const CERT_EXT_BASIC_CONSTRAINTS = '2.5.29.19';
const CERT_EXT_CRL_NUMBER = '2.5.29.20';
const CERT_EXT_REASON_CODE = '2.5.29.21';
const CERT_EXT_INVALIDITY_DATE = '2.5.29.24';
const CERT_EXT_DELTA_CRL_INDICATOR = '2.5.29.27';
const CERT_EXT_ISSUING_DIST_POINT = '2.5.29.28';
const CERT_EXT_CERT_ISSUER = '2.5.29.29';
const CERT_EXT_NAME_CONSTRAINTS = '2.5.29.30';
const CERT_EXT_CRL_DISTRIBUTION_POINTS = '2.5.29.31';
const CERT_EXT_CERT_POLICIES = '2.5.29.32';
const CERT_EXT_AUTHORITY_KEY_IDENTIFIER = '2.5.29.35';
const CERT_EXT_EXTENDED_KEY_USAGE = '2.5.29.37';
// standard certificate files
const COMMON_NAME = '2.5.4.3';
const SURNAME = '2.5.4.4';
const SERIAL_NUMBER = '2.5.4.5';
const COUNTRY_NAME = '2.5.4.6';
const LOCALITY_NAME = '2.5.4.7';
const STATE_OR_PROVINCE_NAME = '2.5.4.8';
const STREET_ADDRESS = '2.5.4.9';
const ORGANIZATION_NAME = '2.5.4.10';
const OU_NAME = '2.5.4.11';
const TITLE = '2.5.4.12';
const DESCRIPTION = '2.5.4.13';
const POSTAL_ADDRESS = '2.5.4.16';
const POSTAL_CODE = '2.5.4.17';
const AUTHORITY_REVOCATION_LIST = '2.5.4.38';
const AUTHORITY_INFORMATION_ACCESS = '1.3.6.1.5.5.7.1.1';
/**
* Returns the name of the given object identifier.
*
* Some OIDs are saved as class constants in this class.
* If the wanted oidString is not among them, this method will
* query http://oid-info.com for the right name.
* This behavior can be suppressed by setting the second method parameter to false.
*
* @param string $oidString
* @param bool $loadFromWeb
*
* @see self::loadFromWeb($oidString)
*
* @return string
*/
public static function getName($oidString, $loadFromWeb = true)
{
switch ($oidString) {
case self::RSA_ENCRYPTION:
return 'RSA Encryption';
case self::MD5_WITH_RSA_ENCRYPTION:
return 'MD5 with RSA Encryption';
case self::SHA1_WITH_RSA_SIGNATURE:
return 'SHA-1 with RSA Signature';
case self::PKCS9_EMAIL:
return 'PKCS #9 Email Address';
case self::PKCS9_UNSTRUCTURED_NAME:
return 'PKCS #9 Unstructured Name';
case self::PKCS9_CONTENT_TYPE:
return 'PKCS #9 Content Type';
case self::PKCS9_MESSAGE_DIGEST:
return 'PKCS #9 Message Digest';
case self::PKCS9_SIGNING_TIME:
return 'PKCS #9 Signing Time';
case self::COMMON_NAME:
return 'Common Name';
case self::SURNAME:
return 'Surname';
case self::SERIAL_NUMBER:
return 'Serial Number';
case self::COUNTRY_NAME:
return 'Country Name';
case self::LOCALITY_NAME:
return 'Locality Name';
case self::STATE_OR_PROVINCE_NAME:
return 'State or Province Name';
case self::STREET_ADDRESS:
return 'Street Address';
case self::ORGANIZATION_NAME:
return 'Organization Name';
case self::OU_NAME:
return 'Organization Unit Name';
case self::TITLE:
return 'Title';
case self::DESCRIPTION:
return 'Description';
case self::POSTAL_ADDRESS:
return 'Postal Address';
case self::POSTAL_CODE:
return 'Postal Code';
case self::AUTHORITY_REVOCATION_LIST:
return 'Authority Revocation List';
case self::CERT_EXT_SUBJECT_DIRECTORY_ATTR:
return 'Subject directory attributes';
case self::CERT_EXT_SUBJECT_KEY_IDENTIFIER:
return 'Subject key identifier';
case self::CERT_EXT_KEY_USAGE:
return 'Key usage certificate extension';
case self::CERT_EXT_PRIVATE_KEY_USAGE_PERIOD:
return 'Private key usage';
case self::CERT_EXT_SUBJECT_ALT_NAME:
return 'Subject alternative name (SAN)';
case self::CERT_EXT_ISSUER_ALT_NAME:
return 'Issuer alternative name';
case self::CERT_EXT_BASIC_CONSTRAINTS:
return 'Basic constraints';
case self::CERT_EXT_CRL_NUMBER:
return 'CRL number';
case self::CERT_EXT_REASON_CODE:
return 'Reason code';
case self::CERT_EXT_INVALIDITY_DATE:
return 'Invalidity code';
case self::CERT_EXT_DELTA_CRL_INDICATOR:
return 'Delta CRL indicator';
case self::CERT_EXT_ISSUING_DIST_POINT:
return 'Issuing distribution point';
case self::CERT_EXT_CERT_ISSUER:
return 'Certificate issuer';
case self::CERT_EXT_NAME_CONSTRAINTS:
return 'Name constraints';
case self::CERT_EXT_CRL_DISTRIBUTION_POINTS:
return 'CRL distribution points';
case self::CERT_EXT_CERT_POLICIES:
return 'Certificate policies ';
case self::CERT_EXT_AUTHORITY_KEY_IDENTIFIER:
return 'Authority key identifier';
case self::CERT_EXT_EXTENDED_KEY_USAGE:
return 'Extended key usage';
case self::AUTHORITY_INFORMATION_ACCESS:
return 'Certificate Authority Information Access (AIA)';
default:
if ($loadFromWeb) {
return self::loadFromWeb($oidString);
} else {
return $oidString;
}
}
}
public static function loadFromWeb($oidString)
{
$ch = curl_init("http://oid-info.com/get/{$oidString}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$contents = curl_exec($ch);
curl_close($ch);
// This pattern needs to be updated as soon as the website layout of oid-info.com changes
preg_match_all('#<tt>(.+)\(\d+\)</tt>#si', $contents, $oidName);
if (empty($oidName[1])) {
return "{$oidString} (unknown)";
}
$oidName = ucfirst(strtolower(preg_replace('/([A-Z][a-z])/', ' $1', $oidName[1][0])));
$oidName = str_replace('-', ' ', $oidName);
return "{$oidName} ({$oidString})";
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use FG\ASN1\Exception\ParserException;
/**
* The Parsable interface describes classes that can be parsed from their binary DER representation.
*/
interface Parsable
{
/**
* Parse an instance of this class from its binary DER encoded representation.
*
* @param string $binaryData
* @param int $offsetIndex the offset at which parsing of the $binaryData is started. This parameter ill be modified
* to contain the offset index of the next object after this object has been parsed
*
* @throws ParserException if the given binary data is either invalid or not currently supported
*
* @return static
*/
public static function fromBinary(&$binaryData, &$offsetIndex = null);
}

View File

@ -0,0 +1,70 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
use Exception;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\Universal\Sequence;
class TemplateParser
{
/**
* @param string $data
* @param array $template
* @return \FG\ASN1\ASNObject|Sequence
* @throws ParserException if there was an issue parsing
*/
public function parseBase64($data, array $template)
{
// TODO test with invalid data
return $this->parseBinary(base64_decode($data), $template);
}
/**
* @param string $binary
* @param array $template
* @return \FG\ASN1\ASNObject|Sequence
* @throws ParserException if there was an issue parsing
*/
public function parseBinary($binary, array $template)
{
$parsedObject = ASNObject::fromBinary($binary);
foreach ($template as $key => $value) {
$this->validate($parsedObject, $key, $value);
}
return $parsedObject;
}
private function validate(ASNObject $object, $key, $value)
{
if (is_array($value)) {
$this->assertTypeId($key, $object);
/* @var Construct $object */
foreach ($value as $key => $child) {
$this->validate($object->current(), $key, $child);
$object->next();
}
} else {
$this->assertTypeId($value, $object);
}
}
private function assertTypeId($expectedTypeId, ASNObject $object)
{
$actualType = $object->getType();
if ($expectedTypeId != $actualType) {
throw new Exception("Expected type ($expectedTypeId) does not match actual type ($actualType");
}
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class BMPString extends AbstractString
{
/**
* Creates a new ASN.1 BMP String.
*
* BMPString is a subtype of UniversalString that has its own
* unique tag and contains only the characters in the
* Basic Multilingual Plane (those corresponding to the first
* 64K-2 cells, less cells whose encoding is used to address
* characters outside the Basic Multilingual Plane) of ISO/IEC 10646-1.
*
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::BMP_STRING;
}
}

View File

@ -0,0 +1,88 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use Exception;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class BitString extends OctetString implements Parsable
{
private $nrOfUnusedBits;
/**
* Creates a new ASN.1 BitString object.
*
* @param string|int $value Either the hexadecimal value as a string (spaces are allowed - leading 0x is optional) or a numeric value
* @param int $nrOfUnusedBits the number of unused bits in the last octet [optional].
*
* @throws Exception if the second parameter is no positive numeric value
*/
public function __construct($value, $nrOfUnusedBits = 0)
{
parent::__construct($value);
if (!is_numeric($nrOfUnusedBits) || $nrOfUnusedBits < 0) {
throw new Exception('BitString: second parameter needs to be a positive number (or zero)!');
}
$this->nrOfUnusedBits = $nrOfUnusedBits;
}
public function getType()
{
return Identifier::BITSTRING;
}
protected function calculateContentLength()
{
// add one to the length for the first octet which encodes the number of unused bits in the last octet
return parent::calculateContentLength() + 1;
}
protected function getEncodedValue()
{
// the first octet determines the number of unused bits
$nrOfUnusedBitsOctet = chr($this->nrOfUnusedBits);
$actualContent = parent::getEncodedValue();
return $nrOfUnusedBitsOctet.$actualContent;
}
public function getNumberOfUnusedBits()
{
return $this->nrOfUnusedBits;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::BITSTRING, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 2);
$nrOfUnusedBits = ord($binaryData[$offsetIndex]);
$value = substr($binaryData, $offsetIndex + 1, $contentLength - 1);
if ($nrOfUnusedBits > 7 || // no less than 1 used, otherwise non-minimal
($contentLength - 1) == 1 && $nrOfUnusedBits > 0 || // content length only 1, no
(ord($value[strlen($value)-1])&((1<<$nrOfUnusedBits)-1)) != 0 // unused bits set
) {
throw new ParserException("Can not parse bit string with invalid padding", $offsetIndex);
}
$offsetIndex += $contentLength;
$parsedObject = new self(bin2hex($value), $nrOfUnusedBits);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,75 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class Boolean extends ASNObject implements Parsable
{
private $value;
/**
* @param bool $value
*/
public function __construct($value)
{
$this->value = $value;
}
public function getType()
{
return Identifier::BOOLEAN;
}
protected function calculateContentLength()
{
return 1;
}
protected function getEncodedValue()
{
if ($this->value == false) {
return chr(0x00);
} else {
return chr(0xFF);
}
}
public function getContent()
{
if ($this->value == true) {
return 'TRUE';
} else {
return 'FALSE';
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::BOOLEAN, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
if ($contentLength != 1) {
throw new ParserException("An ASN.1 Boolean should not have a length other than one. Extracted length was {$contentLength}", $offsetIndex);
}
$value = ord($binaryData[$offsetIndex++]);
$booleanValue = $value == 0xFF ? true : false;
$parsedObject = new self($booleanValue);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class CharacterString extends AbstractString
{
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::CHARACTER_STRING;
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\Identifier;
class Enumerated extends Integer
{
public function getType()
{
return Identifier::ENUMERATED;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class GeneralString extends AbstractString
{
/**
* Creates a new ASN.1 GeneralString.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::GENERAL_STRING;
}
}

View File

@ -0,0 +1,134 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractTime;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
/**
* This ASN.1 universal type contains date and time information according to ISO 8601.
*
* The type consists of values representing:
* a) a calendar date, as defined in ISO 8601; and
* b) a time of day, to any of the precisions defined in ISO 8601, except for the hours value 24 which shall not be used; and
* c) the local time differential factor as defined in ISO 8601.
*
* Decoding of this type will accept the Basic Encoding Rules (BER)
* The encoding will comply with the Distinguished Encoding Rules (DER).
*/
class GeneralizedTime extends AbstractTime implements Parsable
{
private $microseconds;
public function __construct($dateTime = null, $dateTimeZone = 'UTC')
{
parent::__construct($dateTime, $dateTimeZone);
$this->microseconds = $this->value->format('u');
if ($this->containsFractionalSecondsElement()) {
// DER requires us to remove trailing zeros
$this->microseconds = preg_replace('/([1-9]+)0+$/', '$1', $this->microseconds);
}
}
public function getType()
{
return Identifier::GENERALIZED_TIME;
}
protected function calculateContentLength()
{
$contentSize = 15; // YYYYMMDDHHmmSSZ
if ($this->containsFractionalSecondsElement()) {
$contentSize += 1 + strlen($this->microseconds);
}
return $contentSize;
}
public function containsFractionalSecondsElement()
{
return intval($this->microseconds) > 0;
}
protected function getEncodedValue()
{
$encodedContent = $this->value->format('YmdHis');
if ($this->containsFractionalSecondsElement()) {
$encodedContent .= ".{$this->microseconds}";
}
return $encodedContent.'Z';
}
public function __toString()
{
if ($this->containsFractionalSecondsElement()) {
return $this->value->format("Y-m-d\tH:i:s.uP");
} else {
return $this->value->format("Y-m-d\tH:i:sP");
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::GENERALIZED_TIME, $offsetIndex++);
$lengthOfMinimumTimeString = 14; // YYYYMMDDHHmmSS
$contentLength = self::parseContentLength($binaryData, $offsetIndex, $lengthOfMinimumTimeString);
$maximumBytesToRead = $contentLength;
$format = 'YmdGis';
$content = substr($binaryData, $offsetIndex, $contentLength);
$dateTimeString = substr($content, 0, $lengthOfMinimumTimeString);
$offsetIndex += $lengthOfMinimumTimeString;
$maximumBytesToRead -= $lengthOfMinimumTimeString;
if ($contentLength == $lengthOfMinimumTimeString) {
$localTimeZone = new \DateTimeZone(date_default_timezone_get());
$dateTime = \DateTime::createFromFormat($format, $dateTimeString, $localTimeZone);
} else {
if ($binaryData[$offsetIndex] == '.') {
$maximumBytesToRead--; // account for the '.'
$nrOfFractionalSecondElements = 1; // account for the '.'
while ($maximumBytesToRead > 0
&& $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '+'
&& $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '-'
&& $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != 'Z') {
$nrOfFractionalSecondElements++;
$maximumBytesToRead--;
}
$dateTimeString .= substr($binaryData, $offsetIndex, $nrOfFractionalSecondElements);
$offsetIndex += $nrOfFractionalSecondElements;
$format .= '.u';
}
$dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC'));
if ($maximumBytesToRead > 0) {
if ($binaryData[$offsetIndex] == '+'
|| $binaryData[$offsetIndex] == '-') {
$dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime);
} elseif ($binaryData[$offsetIndex++] != 'Z') {
throw new ParserException('Invalid ISO 8601 Time String', $offsetIndex);
}
}
}
$parsedObject = new self($dateTime);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class GraphicString extends AbstractString
{
/**
* Creates a new ASN.1 Graphic String.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::GRAPHIC_STRING;
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
/**
* The International Alphabet No.5 (IA5) references the encoding of the ASCII characters.
*
* Each character in the data is encoded as 1 byte.
*/
class IA5String extends AbstractString
{
public function __construct($string)
{
parent::__construct($string);
for ($i = 1; $i < 128; $i++) {
$this->allowCharacter(chr($i));
}
}
public function getType()
{
return Identifier::IA5_STRING;
}
}

View File

@ -0,0 +1,130 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use Exception;
use FG\Utility\BigInteger;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class Integer extends ASNObject implements Parsable
{
/** @var int */
private $value;
/**
* @param int $value
*
* @throws Exception if the value is not numeric
*/
public function __construct($value)
{
if (is_numeric($value) == false) {
throw new Exception("Invalid VALUE [{$value}] for ASN1_INTEGER");
}
$this->value = $value;
}
public function getType()
{
return Identifier::INTEGER;
}
public function getContent()
{
return $this->value;
}
protected function calculateContentLength()
{
return strlen($this->getEncodedValue());
}
protected function getEncodedValue()
{
$value = BigInteger::create($this->value, 10);
$negative = $value->compare(0) < 0;
if ($negative) {
$value = $value->absoluteValue();
$limit = 0x80;
} else {
$limit = 0x7f;
}
$mod = 0xff+1;
$values = [];
while($value->compare($limit) > 0) {
$values[] = $value->modulus($mod)->toInteger();
$value = $value->shiftRight(8);
}
$values[] = $value->modulus($mod)->toInteger();
$numValues = count($values);
if ($negative) {
for ($i = 0; $i < $numValues; $i++) {
$values[$i] = 0xff - $values[$i];
}
for ($i = 0; $i < $numValues; $i++) {
$values[$i] += 1;
if ($values[$i] <= 0xff) {
break;
}
assert($i != $numValues - 1);
$values[$i] = 0;
}
if ($values[$numValues - 1] == 0x7f) {
$values[] = 0xff;
}
}
$values = array_reverse($values);
$r = pack("C*", ...$values);
return $r;
}
private static function ensureMinimalEncoding($binaryData, $offsetIndex)
{
// All the first nine bits cannot equal 0 or 1, which would
// be non-minimal encoding for positive and negative integers respectively
if ((ord($binaryData[$offsetIndex]) == 0x00 && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0) ||
(ord($binaryData[$offsetIndex]) == 0xff && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0x80)) {
throw new ParserException("Integer not minimally encoded", $offsetIndex);
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$parsedObject = new static(0);
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
if ($contentLength > 1) {
self::ensureMinimalEncoding($binaryData, $offsetIndex);
}
$isNegative = (ord($binaryData[$offsetIndex]) & 0x80) != 0x00;
$number = BigInteger::create(ord($binaryData[$offsetIndex++]) & 0x7F);
for ($i = 0; $i < $contentLength - 1; $i++) {
$number = $number->multiply(0x100)->add(ord($binaryData[$offsetIndex++]));
}
if ($isNegative) {
$number = $number->subtract(BigInteger::create(2)->toPower(8 * $contentLength - 1));
}
$parsedObject = new static((string)$number);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,54 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class NullObject extends ASNObject implements Parsable
{
public function getType()
{
return Identifier::NULL;
}
protected function calculateContentLength()
{
return 0;
}
protected function getEncodedValue()
{
return null;
}
public function getContent()
{
return 'NULL';
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::NULL, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
if ($contentLength != 0) {
throw new ParserException("An ASN.1 Null should not have a length other than zero. Extracted length was {$contentLength}", $offsetIndex);
}
$parsedObject = new self();
$parsedObject->setContentLength(0);
return $parsedObject;
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class NumericString extends AbstractString
{
/**
* Creates a new ASN.1 NumericString.
*
* The following characters are permitted:
* Digits 0,1, ... 9
* SPACE (space)
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowNumbers();
$this->allowSpaces();
}
public function getType()
{
return Identifier::NUMERIC_STRING;
}
}

View File

@ -0,0 +1,26 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\Identifier;
class ObjectDescriptor extends GraphicString
{
public function __construct($objectDescription)
{
parent::__construct($objectDescription);
}
public function getType()
{
return Identifier::OBJECT_DESCRIPTOR;
}
}

View File

@ -0,0 +1,138 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use Exception;
use FG\ASN1\Base128;
use FG\ASN1\OID;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class ObjectIdentifier extends ASNObject implements Parsable
{
protected $subIdentifiers;
protected $value;
public function __construct($value)
{
$this->subIdentifiers = explode('.', $value);
$nrOfSubIdentifiers = count($this->subIdentifiers);
for ($i = 0; $i < $nrOfSubIdentifiers; $i++) {
if (is_numeric($this->subIdentifiers[$i])) {
// enforce the integer type
$this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]);
} else {
throw new Exception("[{$value}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!');
}
}
// Merge the first to arcs of the OID registration tree (per ASN definition!)
if ($nrOfSubIdentifiers >= 2) {
$this->subIdentifiers[1] = ($this->subIdentifiers[0] * 40) + $this->subIdentifiers[1];
unset($this->subIdentifiers[0]);
}
$this->value = $value;
}
public function getContent()
{
return $this->value;
}
public function getType()
{
return Identifier::OBJECT_IDENTIFIER;
}
protected function calculateContentLength()
{
$length = 0;
foreach ($this->subIdentifiers as $subIdentifier) {
do {
$subIdentifier = $subIdentifier >> 7;
$length++;
} while ($subIdentifier > 0);
}
return $length;
}
protected function getEncodedValue()
{
$encodedValue = '';
foreach ($this->subIdentifiers as $subIdentifier) {
$encodedValue .= Base128::encode($subIdentifier);
}
return $encodedValue;
}
public function __toString()
{
return OID::getName($this->value);
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::OBJECT_IDENTIFIER, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
$firstOctet = ord($binaryData[$offsetIndex++]);
$oidString = floor($firstOctet / 40).'.'.($firstOctet % 40);
$oidString .= '.'.self::parseOid($binaryData, $offsetIndex, $contentLength - 1);
$parsedObject = new self($oidString);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
/**
* Parses an object identifier except for the first octet, which is parsed
* differently. This way relative object identifiers can also be parsed
* using this.
*
* @param $binaryData
* @param $offsetIndex
* @param $octetsToRead
*
* @throws ParserException
*
* @return string
*/
protected static function parseOid(&$binaryData, &$offsetIndex, $octetsToRead)
{
$oid = '';
while ($octetsToRead > 0) {
$octets = '';
do {
if (0 === $octetsToRead) {
throw new ParserException('Malformed ASN.1 Object Identifier', $offsetIndex - 1);
}
$octetsToRead--;
$octet = $binaryData[$offsetIndex++];
$octets .= $octet;
} while (ord($octet) & 0x80);
$oid .= sprintf('%d.', Base128::decode($octets));
}
// Remove trailing '.'
return substr($oid, 0, -1) ?: '';
}
}

View File

@ -0,0 +1,91 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use Exception;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class OctetString extends ASNObject implements Parsable
{
protected $value;
public function __construct($value)
{
if (is_string($value)) {
// remove gaps between hex digits
$value = preg_replace('/\s|0x/', '', $value);
} elseif (is_numeric($value)) {
$value = dechex($value);
} elseif ($value === null) {
return;
} else {
throw new Exception('OctetString: unrecognized input type!');
}
if (strlen($value) % 2 != 0) {
// transform values like 1F2 to 01F2
$value = '0'.$value;
}
$this->value = $value;
}
public function getType()
{
return Identifier::OCTETSTRING;
}
protected function calculateContentLength()
{
return strlen($this->value) / 2;
}
protected function getEncodedValue()
{
$value = $this->value;
$result = '';
//Actual content
while (strlen($value) >= 2) {
// get the hex value byte by byte from the string and and add it to binary result
$result .= chr(hexdec(substr($value, 0, 2)));
$value = substr($value, 2);
}
return $result;
}
public function getContent()
{
return strtoupper($this->value);
}
public function getBinaryContent()
{
return $this->getEncodedValue();
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::OCTETSTRING, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$value = substr($binaryData, $offsetIndex, $contentLength);
$offsetIndex += $contentLength;
$parsedObject = new self(bin2hex($value));
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,53 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class PrintableString extends AbstractString
{
/**
* Creates a new ASN.1 PrintableString.
*
* The ITU-T X.680 Table 8 permits the following characters:
* Latin capital letters A,B, ... Z
* Latin small letters a,b, ... z
* Digits 0,1, ... 9
* SPACE (space)
* APOSTROPHE '
* LEFT PARENTHESIS (
* RIGHT PARENTHESIS )
* PLUS SIGN +
* COMMA ,
* HYPHEN-MINUS -
* FULL STOP .
* SOLIDUS /
* COLON :
* EQUALS SIGN =
* QUESTION MARK ?
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowNumbers();
$this->allowAllLetters();
$this->allowSpaces();
$this->allowCharacters("'", '(', ')', '+', '-', '.', ',', '/', ':', '=', '?');
}
public function getType()
{
return Identifier::PRINTABLE_STRING;
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use Exception;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class RelativeObjectIdentifier extends ObjectIdentifier implements Parsable
{
public function __construct($subIdentifiers)
{
$this->value = $subIdentifiers;
$this->subIdentifiers = explode('.', $subIdentifiers);
$nrOfSubIdentifiers = count($this->subIdentifiers);
for ($i = 0; $i < $nrOfSubIdentifiers; $i++) {
if (is_numeric($this->subIdentifiers[$i])) {
// enforce the integer type
$this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]);
} else {
throw new Exception("[{$subIdentifiers}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!');
}
}
}
public function getType()
{
return Identifier::RELATIVE_OID;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::RELATIVE_OID, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
try {
$oidString = self::parseOid($binaryData, $offsetIndex, $contentLength);
} catch (ParserException $e) {
throw new ParserException('Malformed ASN.1 Relative Object Identifier', $e->getOffset());
}
$parsedObject = new self($oidString);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\Construct;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class Sequence extends Construct implements Parsable
{
public function getType()
{
return Identifier::SEQUENCE;
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\Identifier;
class Set extends Sequence
{
public function getType()
{
return Identifier::SET;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class T61String extends AbstractString
{
/**
* Creates a new ASN.1 T61 String.
* TODO The encodable characters of this type are not yet checked.
*
* @see http://en.wikipedia.org/wiki/ITU_T.61
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::T61_STRING;
}
}

View File

@ -0,0 +1,77 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractTime;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
/**
* This ASN.1 universal type contains the calendar date and time.
*
* The precision is one minute or one second and optionally a
* local time differential from coordinated universal time.
*
* Decoding of this type will accept the Basic Encoding Rules (BER)
* The encoding will comply with the Distinguished Encoding Rules (DER).
*/
class UTCTime extends AbstractTime implements Parsable
{
public function getType()
{
return Identifier::UTC_TIME;
}
protected function calculateContentLength()
{
return 13; // Content is a string o the following format: YYMMDDhhmmssZ (13 octets)
}
protected function getEncodedValue()
{
return $this->value->format('ymdHis').'Z';
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::UTC_TIME, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 11);
$format = 'ymdGi';
$dateTimeString = substr($binaryData, $offsetIndex, 10);
$offsetIndex += 10;
// extract optional seconds part
if ($binaryData[$offsetIndex] != 'Z'
&& $binaryData[$offsetIndex] != '+'
&& $binaryData[$offsetIndex] != '-') {
$dateTimeString .= substr($binaryData, $offsetIndex, 2);
$offsetIndex += 2;
$format .= 's';
}
$dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC'));
// extract time zone settings
if ($binaryData[$offsetIndex] == '+'
|| $binaryData[$offsetIndex] == '-') {
$dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime);
} elseif ($binaryData[$offsetIndex++] != 'Z') {
throw new ParserException('Invalid UTC String', $offsetIndex);
}
$parsedObject = new self($dateTime);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class UTF8String extends AbstractString
{
/**
* Creates a new ASN.1 Universal String.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::UTF8_STRING;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class UniversalString extends AbstractString
{
/**
* Creates a new ASN.1 Universal String.
* TODO The encodable characters of this type are not yet checked.
*
* @see http://en.wikipedia.org/wiki/Universal_Character_Set
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::UNIVERSAL_STRING;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class VisibleString extends AbstractString
{
/**
* Creates a new ASN.1 Visible String.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::VISIBLE_STRING;
}
}

View File

@ -0,0 +1,59 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
class UnknownConstructedObject extends Construct
{
private $identifier;
private $contentLength;
/**
* @param string $binaryData
* @param int $offsetIndex
*
* @throws \FG\ASN1\Exception\ParserException
*/
public function __construct($binaryData, &$offsetIndex)
{
$this->identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
$this->contentLength = self::parseContentLength($binaryData, $offsetIndex);
$children = [];
$octetsToRead = $this->contentLength;
while ($octetsToRead > 0) {
$newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
$octetsToRead -= $newChild->getObjectLength();
$children[] = $newChild;
}
parent::__construct(...$children);
}
public function getType()
{
return ord($this->identifier);
}
public function getIdentifier()
{
return $this->identifier;
}
protected function calculateContentLength()
{
return $this->contentLength;
}
protected function getEncodedValue()
{
return '';
}
}

View File

@ -0,0 +1,59 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\ASN1;
class UnknownObject extends ASNObject
{
/** @var string */
private $value;
private $identifier;
/**
* @param string|int $identifier Either the first identifier octet as int or all identifier bytes as a string
* @param int $contentLength
*/
public function __construct($identifier, $contentLength)
{
if (is_int($identifier)) {
$identifier = chr($identifier);
}
$this->identifier = $identifier;
$this->value = "Unparsable Object ({$contentLength} bytes)";
$this->setContentLength($contentLength);
}
public function getContent()
{
return $this->value;
}
public function getType()
{
return ord($this->identifier[0]);
}
public function getIdentifier()
{
return $this->identifier;
}
protected function calculateContentLength()
{
return $this->getContentLength();
}
protected function getEncodedValue()
{
return '';
}
}

View File

@ -0,0 +1,195 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\Utility;
/**
* Class BigInteger
* Utility class to remove dependence on a single large number library. Not intended for external use, this class only
* implements the functionality needed throughout this project.
*
* Instances are immutable, all operations return a new instance with the result.
*
* @package FG\Utility
* @internal
*/
abstract class BigInteger
{
/**
* Force a preference on the underlying big number implementation, useful for testing.
* @var string|null
*/
private static $_prefer;
public static function setPrefer($prefer = null)
{
self::$_prefer = $prefer;
}
/**
* Create a BigInteger instance based off the base 10 string or an integer.
* @param string|int $val
* @return BigInteger
* @throws \InvalidArgumentException
*/
public static function create($val)
{
if (self::$_prefer) {
switch (self::$_prefer) {
case 'gmp':
$ret = new BigIntegerGmp();
break;
case 'bcmath':
$ret = new BigIntegerBcmath();
break;
default:
throw new \UnexpectedValueException('Unknown number implementation: ' . self::$_prefer);
}
}
else {
// autodetect
if (function_exists('gmp_add')) {
$ret = new BigIntegerGmp();
}
elseif (function_exists('bcadd')) {
$ret = new BigIntegerBcmath();
} else {
throw new \RuntimeException('Requires GMP or bcmath extension.');
}
}
if (is_int($val)) {
$ret->_fromInteger($val);
}
else {
// convert to string, if not already one
$val = (string)$val;
// validate string
if (!preg_match('/^-?[0-9]+$/', $val)) {
throw new \InvalidArgumentException('Expects a string representation of an integer.');
}
$ret->_fromString($val);
}
return $ret;
}
/**
* BigInteger constructor.
* Prevent directly instantiating object, use BigInteger::create instead.
*/
protected function __construct()
{
}
/**
* Subclasses must provide clone functionality.
* @return BigInteger
*/
abstract public function __clone();
/**
* Assign the instance value from base 10 string.
* @param string $str
*/
abstract protected function _fromString($str);
/**
* Assign the instance value from an integer type.
* @param int $integer
*/
abstract protected function _fromInteger($integer);
/**
* Must provide string implementation that returns base 10 number.
* @return string
*/
abstract public function __toString();
/* INFORMATIONAL FUNCTIONS */
/**
* Return integer, if possible. Throws an exception if the number can not be represented as a native integer.
* @return int
* @throws \OverflowException
*/
abstract public function toInteger();
/**
* Is represented integer negative?
* @return bool
*/
abstract public function isNegative();
/**
* Compare the integer with $number, returns a negative integer if $this is less than number, returns 0 if $this is
* equal to number and returns a positive integer if $this is greater than number.
* @param BigInteger|string|int $number
* @return int
*/
abstract public function compare($number);
/* MODIFY */
/**
* Add another integer $b and returns the result.
* @param BigInteger|string|int $b
* @return BigInteger
*/
abstract public function add($b);
/**
* Subtract $b from $this and returns the result.
* @param BigInteger|string|int $b
* @return BigInteger
*/
abstract public function subtract($b);
/**
* Multiply value.
* @param BigInteger|string|int $b
* @return BigInteger
*/
abstract public function multiply($b);
/**
* The value $this modulus $b.
* @param BigInteger|string|int $b
* @return BigInteger
*/
abstract public function modulus($b);
/**
* Raise $this to the power of $b and returns the result.
* @param BigInteger|string|int $b
* @return BigInteger
*/
abstract public function toPower($b);
/**
* Shift the value to the right by a set number of bits and returns the result.
* @param int $bits
* @return BigInteger
*/
abstract public function shiftRight($bits = 8);
/**
* Shift the value to the left by a set number of bits and returns the result.
* @param int $bits
* @return BigInteger
*/
abstract public function shiftLeft($bits = 8);
/**
* Returns the absolute value.
* @return BigInteger
*/
abstract public function absoluteValue();
}

View File

@ -0,0 +1,133 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\Utility;
/**
* Class BigIntegerBcmath
* Integer representation of big numbers using the bcmath library to perform large operations.
* @package FG\Utility
* @internal
*/
class BigIntegerBcmath extends BigInteger
{
protected $_str;
public function __clone()
{
// nothing needed to copy
}
protected function _fromString($str)
{
$this->_str = (string)$str;
}
protected function _fromInteger($integer)
{
$this->_str = (string)$integer;
}
public function __toString()
{
return $this->_str;
}
public function toInteger()
{
if ($this->compare(PHP_INT_MAX) > 0 || $this->compare(PHP_INT_MIN) < 0) {
throw new \OverflowException(sprintf('Can not represent %s as integer.', $this->_str));
}
return (int)$this->_str;
}
public function isNegative()
{
return bccomp($this->_str, '0', 0) < 0;
}
protected function _unwrap($number)
{
if ($number instanceof self) {
return $number->_str;
}
return $number;
}
public function compare($number)
{
return bccomp($this->_str, $this->_unwrap($number), 0);
}
public function add($b)
{
$ret = new self();
$ret->_str = bcadd($this->_str, $this->_unwrap($b), 0);
return $ret;
}
public function subtract($b)
{
$ret = new self();
$ret->_str = bcsub($this->_str, $this->_unwrap($b), 0);
return $ret;
}
public function multiply($b)
{
$ret = new self();
$ret->_str = bcmul($this->_str, $this->_unwrap($b), 0);
return $ret;
}
public function modulus($b)
{
$ret = new self();
if ($this->isNegative()) {
// bcmod handles negative numbers differently
$b = $this->_unwrap($b);
$ret->_str = bcsub($b, bcmod(bcsub('0', $this->_str, 0), $b), 0);
}
else {
$ret->_str = bcmod($this->_str, $this->_unwrap($b));
}
return $ret;
}
public function toPower($b)
{
$ret = new self();
$ret->_str = bcpow($this->_str, $this->_unwrap($b), 0);
return $ret;
}
public function shiftRight($bits = 8)
{
$ret = new self();
$ret->_str = bcdiv($this->_str, bcpow('2', $bits));
return $ret;
}
public function shiftLeft($bits = 8) {
$ret = new self();
$ret->_str = bcmul($this->_str, bcpow('2', $bits));
return $ret;
}
public function absoluteValue()
{
$ret = new self();
if (-1 === bccomp($this->_str, '0', 0)) {
$ret->_str = bcsub('0', $this->_str, 0);
}
else {
$ret->_str = $this->_str;
}
return $ret;
}
}

View File

@ -0,0 +1,133 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\Utility;
/**
* Class BigIntegerGmp
* Integer representation of big numbers using the GMP extension to perform operations.
* @package FG\Utility
* @internal
*/
class BigIntegerGmp extends BigInteger
{
/**
* Resource handle.
* @var \GMP
*/
protected $_rh;
public function __clone()
{
$this->_rh = gmp_add($this->_rh, 0);
}
protected function _fromString($str)
{
$this->_rh = gmp_init($str, 10);
}
protected function _fromInteger($integer)
{
$this->_rh = gmp_init($integer, 10);
}
public function __toString()
{
return gmp_strval($this->_rh, 10);
}
public function toInteger()
{
if ($this->compare(PHP_INT_MAX) > 0 || $this->compare(PHP_INT_MIN) < 0) {
throw new \OverflowException(sprintf('Can not represent %s as integer.', $this));
}
return gmp_intval($this->_rh);
}
public function isNegative()
{
return gmp_sign($this->_rh) === -1;
}
protected function _unwrap($number)
{
if ($number instanceof self) {
return $number->_rh;
}
return $number;
}
public function compare($number)
{
return gmp_cmp($this->_rh, $this->_unwrap($number));
}
public function add($b)
{
$ret = new self();
$ret->_rh = gmp_add($this->_rh, $this->_unwrap($b));
return $ret;
}
public function subtract($b)
{
$ret = new self();
$ret->_rh = gmp_sub($this->_rh, $this->_unwrap($b));
return $ret;
}
public function multiply($b)
{
$ret = new self();
$ret->_rh = gmp_mul($this->_rh, $this->_unwrap($b));
return $ret;
}
public function modulus($b)
{
$ret = new self();
$ret->_rh = gmp_mod($this->_rh, $this->_unwrap($b));
return $ret;
}
public function toPower($b)
{
if ($b instanceof self) {
// gmp_pow accepts just an integer
if ($b->compare(PHP_INT_MAX) > 0) {
throw new \UnexpectedValueException('Unable to raise to power greater than PHP_INT_MAX.');
}
$b = gmp_intval($b->_rh);
}
$ret = new self();
$ret->_rh = gmp_pow($this->_rh, $b);
return $ret;
}
public function shiftRight($bits=8)
{
$ret = new self();
$ret->_rh = gmp_div($this->_rh, gmp_pow(2, $bits));
return $ret;
}
public function shiftLeft($bits=8)
{
$ret = new self();
$ret->_rh = gmp_mul($this->_rh, gmp_pow(2, $bits));
return $ret;
}
public function absoluteValue()
{
$ret = new self();
$ret->_rh = gmp_abs($this->_rh);
return $ret;
}
}

View File

@ -0,0 +1,22 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509;
use FG\ASN1\Universal\NullObject;
use FG\ASN1\Composite\AttributeTypeAndValue;
class AlgorithmIdentifier extends AttributeTypeAndValue
{
public function __construct($objectIdentifierString)
{
parent::__construct($objectIdentifierString, new NullObject());
}
}

View File

@ -0,0 +1,68 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509\CSR;
use FG\ASN1\ASNObject;
use FG\X509\CertificateExtensions;
use FG\ASN1\OID;
use FG\ASN1\Parsable;
use FG\ASN1\Construct;
use FG\ASN1\Identifier;
use FG\ASN1\Universal\Set;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\ObjectIdentifier;
class Attributes extends Construct implements Parsable
{
public function getType()
{
return 0xA0;
}
public function addAttribute($objectIdentifier, Set $attribute)
{
if (is_string($objectIdentifier)) {
$objectIdentifier = new ObjectIdentifier($objectIdentifier);
}
$attributeSequence = new Sequence($objectIdentifier, $attribute);
$attributeSequence->getNumberOfLengthOctets(); // length and number of length octets is calculated
$this->addChild($attributeSequence);
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], 0xA0, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$octetsToRead = $contentLength;
$parsedObject = new self();
while ($octetsToRead > 0) {
$initialOffset = $offsetIndex; // used to calculate how much bits have been read
self::parseIdentifier($binaryData[$offsetIndex], Identifier::SEQUENCE, $offsetIndex++);
self::parseContentLength($binaryData, $offsetIndex);
$objectIdentifier = ObjectIdentifier::fromBinary($binaryData, $offsetIndex);
$oidString = $objectIdentifier->getContent();
if ($oidString == OID::PKCS9_EXTENSION_REQUEST) {
$attribute = CertificateExtensions::fromBinary($binaryData, $offsetIndex);
} else {
$attribute = ASNObject::fromBinary($binaryData, $offsetIndex);
}
$parsedObject->addAttribute($objectIdentifier, $attribute);
$octetsToRead -= ($offsetIndex - $initialOffset);
}
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View File

@ -0,0 +1,137 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509\CSR;
use FG\ASN1\OID;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\Sequence;
use FG\X509\CertificateSubject;
use FG\X509\AlgorithmIdentifier;
use FG\X509\PublicKey;
class CSR extends Sequence
{
const CSR_VERSION_NR = 0;
protected $subject;
protected $publicKey;
protected $signature;
protected $signatureAlgorithm;
protected $startSequence;
/**
* @param string $commonName
* @param string $email
* @param string $organization
* @param string $locality
* @param string $state
* @param string $country
* @param string $organizationalUnit
* @param string $publicKey
* @param string $signature
* @param string $signatureAlgorithm
*/
public function __construct($commonName, $email, $organization, $locality, $state, $country, $organizationalUnit, $publicKey, $signature, $signatureAlgorithm = OID::SHA1_WITH_RSA_SIGNATURE)
{
$this->subject = new CertificateSubject(
$commonName,
$email,
$organization,
$locality,
$state,
$country,
$organizationalUnit
);
$this->publicKey = $publicKey;
$this->signature = $signature;
$this->signatureAlgorithm = $signatureAlgorithm;
$this->createCSRSequence();
}
protected function createCSRSequence()
{
$versionNr = new Integer(self::CSR_VERSION_NR);
$publicKey = new PublicKey($this->publicKey);
$signature = new BitString($this->signature);
$signatureAlgorithm = new AlgorithmIdentifier($this->signatureAlgorithm);
$certRequestInfo = new Sequence($versionNr, $this->subject, $publicKey);
$this->addChild($certRequestInfo);
$this->addChild($signatureAlgorithm);
$this->addChild($signature);
}
public function __toString()
{
$tmp = base64_encode($this->getBinary());
for ($i = 0; $i < strlen($tmp); $i++) {
if (($i + 2) % 65 == 0) {
$tmp = substr($tmp, 0, $i + 1)."\n".substr($tmp, $i + 1);
}
}
$result = '-----BEGIN CERTIFICATE REQUEST-----'.PHP_EOL;
$result .= $tmp.PHP_EOL;
$result .= '-----END CERTIFICATE REQUEST-----';
return $result;
}
public function getVersion()
{
return self::CSR_VERSION_NR;
}
public function getOrganizationName()
{
return $this->subject->getOrganization();
}
public function getLocalName()
{
return $this->subject->getLocality();
}
public function getState()
{
return $this->subject->getState();
}
public function getCountry()
{
return $this->subject->getCountry();
}
public function getOrganizationalUnit()
{
return $this->subject->getOrganizationalUnit();
}
public function getPublicKey()
{
return $this->publicKey;
}
public function getSignature()
{
return $this->signature;
}
public function getSignatureAlgorithm()
{
return $this->signatureAlgorithm;
}
}

View File

@ -0,0 +1,100 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\OID;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Universal\OctetString;
use FG\ASN1\Universal\Set;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\ObjectIdentifier;
use FG\X509\SAN\SubjectAlternativeNames;
class CertificateExtensions extends Set implements Parsable
{
private $innerSequence;
private $extensions = [];
public function __construct()
{
$this->innerSequence = new Sequence();
parent::__construct($this->innerSequence);
}
public function addSubjectAlternativeNames(SubjectAlternativeNames $sans)
{
$this->addExtension(OID::CERT_EXT_SUBJECT_ALT_NAME, $sans);
}
private function addExtension($oidString, ASNObject $extension)
{
$sequence = new Sequence();
$sequence->addChild(new ObjectIdentifier($oidString));
$sequence->addChild($extension);
$this->innerSequence->addChild($sequence);
$this->extensions[] = $extension;
}
public function getContent()
{
return $this->extensions;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::SET, $offsetIndex++);
self::parseContentLength($binaryData, $offsetIndex);
$tmpOffset = $offsetIndex;
$extensions = Sequence::fromBinary($binaryData, $offsetIndex);
$tmpOffset += 1 + $extensions->getNumberOfLengthOctets();
$parsedObject = new self();
foreach ($extensions as $extension) {
if ($extension->getType() != Identifier::SEQUENCE) {
//FIXME wrong offset index
throw new ParserException('Could not parse Certificate Extensions: Expected ASN.1 Sequence but got '.$extension->getTypeName(), $offsetIndex);
}
$tmpOffset += 1 + $extension->getNumberOfLengthOctets();
$children = $extension->getChildren();
if (count($children) < 2) {
throw new ParserException('Could not parse Certificate Extensions: Needs at least two child elements per extension sequence (object identifier and octet string)', $tmpOffset);
}
/** @var \FG\ASN1\ASNObject $objectIdentifier */
$objectIdentifier = $children[0];
/** @var OctetString $octetString */
$octetString = $children[1];
if ($objectIdentifier->getType() != Identifier::OBJECT_IDENTIFIER) {
throw new ParserException('Could not parse Certificate Extensions: Expected ASN.1 Object Identifier but got '.$extension->getTypeName(), $tmpOffset);
}
$tmpOffset += $objectIdentifier->getObjectLength();
if ($objectIdentifier->getContent() == OID::CERT_EXT_SUBJECT_ALT_NAME) {
$sans = SubjectAlternativeNames::fromBinary($binaryData, $tmpOffset);
$parsedObject->addSubjectAlternativeNames($sans);
} else {
// can now only parse SANs. There might be more in the future
$tmpOffset += $octetString->getObjectLength();
}
}
$parsedObject->getBinary(); // Determine the number of content octets and object sizes once (just to let the equality unit tests pass :/ )
return $parsedObject;
}
}

View File

@ -0,0 +1,108 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509;
use FG\ASN1\Composite\RelativeDistinguishedName;
use FG\ASN1\Identifier;
use FG\ASN1\OID;
use FG\ASN1\Parsable;
use FG\ASN1\Composite\RDNString;
use FG\ASN1\Universal\Sequence;
class CertificateSubject extends Sequence implements Parsable
{
private $commonName;
private $email;
private $organization;
private $locality;
private $state;
private $country;
private $organizationalUnit;
/**
* @param string $commonName
* @param string $email
* @param string $organization
* @param string $locality
* @param string $state
* @param string $country
* @param string $organizationalUnit
*/
public function __construct($commonName, $email, $organization, $locality, $state, $country, $organizationalUnit)
{
parent::__construct(
new RDNString(OID::COUNTRY_NAME, $country),
new RDNString(OID::STATE_OR_PROVINCE_NAME, $state),
new RDNString(OID::LOCALITY_NAME, $locality),
new RDNString(OID::ORGANIZATION_NAME, $organization),
new RDNString(OID::OU_NAME, $organizationalUnit),
new RDNString(OID::COMMON_NAME, $commonName),
new RDNString(OID::PKCS9_EMAIL, $email)
);
$this->commonName = $commonName;
$this->email = $email;
$this->organization = $organization;
$this->locality = $locality;
$this->state = $state;
$this->country = $country;
$this->organizationalUnit = $organizationalUnit;
}
public function getCommonName()
{
return $this->commonName;
}
public function getEmail()
{
return $this->email;
}
public function getOrganization()
{
return $this->organization;
}
public function getLocality()
{
return $this->locality;
}
public function getState()
{
return $this->state;
}
public function getCountry()
{
return $this->country;
}
public function getOrganizationalUnit()
{
return $this->organizationalUnit;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::SEQUENCE, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$names = [];
$octetsToRead = $contentLength;
while ($octetsToRead > 0) {
$relativeDistinguishedName = RelativeDistinguishedName::fromBinary($binaryData, $offsetIndex);
$octetsToRead -= $relativeDistinguishedName->getObjectLength();
$names[] = $relativeDistinguishedName;
}
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509;
use FG\ASN1\OID;
use FG\ASN1\Universal\NullObject;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\ObjectIdentifier;
class PrivateKey extends Sequence
{
/**
* @param string $hexKey
* @param \FG\ASN1\ASNObject|string $algorithmIdentifierString
*/
public function __construct($hexKey, $algorithmIdentifierString = OID::RSA_ENCRYPTION)
{
parent::__construct(
new Sequence(
new ObjectIdentifier($algorithmIdentifierString),
new NullObject()
),
new BitString($hexKey)
);
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509;
use FG\ASN1\OID;
use FG\ASN1\Universal\NullObject;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\ObjectIdentifier;
class PublicKey extends Sequence
{
/**
* @param string $hexKey
* @param \FG\ASN1\ASNObject|string $algorithmIdentifierString
*/
public function __construct($hexKey, $algorithmIdentifierString = OID::RSA_ENCRYPTION)
{
parent::__construct(
new Sequence(
new ObjectIdentifier($algorithmIdentifierString),
new NullObject()
),
new BitString($hexKey)
);
}
}

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509\SAN;
use FG\ASN1\Universal\GeneralString;
class DNSName extends GeneralString
{
const IDENTIFIER = 0x82; // not sure yet why this is the identifier used in SAN extensions
public function __construct($dnsNameString)
{
parent::__construct($dnsNameString);
}
public function getType()
{
return self::IDENTIFIER;
}
}

View File

@ -0,0 +1,73 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509\SAN;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Exception\ParserException;
class IPAddress extends ASNObject implements Parsable
{
const IDENTIFIER = 0x87; // not sure yet why this is the identifier used in SAN extensions
/** @var string */
private $value;
public function __construct($ipAddressString)
{
$this->value = $ipAddressString;
}
public function getType()
{
return self::IDENTIFIER;
}
public function getContent()
{
return $this->value;
}
protected function calculateContentLength()
{
return 4;
}
protected function getEncodedValue()
{
$ipParts = explode('.', $this->value);
$binary = chr($ipParts[0]);
$binary .= chr($ipParts[1]);
$binary .= chr($ipParts[2]);
$binary .= chr($ipParts[3]);
return $binary;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], self::IDENTIFIER, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
if ($contentLength != 4) {
throw new ParserException("A FG\\X509\SAN\IPAddress should have a content length of 4. Extracted length was {$contentLength}", $offsetIndex);
}
$ipAddressString = ord($binaryData[$offsetIndex++]).'.';
$ipAddressString .= ord($binaryData[$offsetIndex++]).'.';
$ipAddressString .= ord($binaryData[$offsetIndex++]).'.';
$ipAddressString .= ord($binaryData[$offsetIndex++]);
$parsedObject = new self($ipAddressString);
$parsedObject->getObjectLength();
return $parsedObject;
}
}

View File

@ -0,0 +1,96 @@
<?php
/*
* This file is part of the PHPASN1 library.
*
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FG\X509\SAN;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\ASNObject;
use FG\ASN1\OID;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Universal\Sequence;
/**
* See section 8.3.2.1 of ITU-T X.509.
*/
class SubjectAlternativeNames extends ASNObject implements Parsable
{
private $alternativeNamesSequence;
public function __construct()
{
$this->alternativeNamesSequence = new Sequence();
}
protected function calculateContentLength()
{
return $this->alternativeNamesSequence->getObjectLength();
}
public function getType()
{
return Identifier::OCTETSTRING;
}
public function addDomainName(DNSName $domainName)
{
$this->alternativeNamesSequence->addChild($domainName);
}
public function addIP(IPAddress $ip)
{
$this->alternativeNamesSequence->addChild($ip);
}
public function getContent()
{
return $this->alternativeNamesSequence->getContent();
}
protected function getEncodedValue()
{
return $this->alternativeNamesSequence->getBinary();
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::OCTETSTRING, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
if ($contentLength < 2) {
throw new ParserException('Can not parse Subject Alternative Names: The Sequence within the octet string after the Object identifier '.OID::CERT_EXT_SUBJECT_ALT_NAME." is too short ({$contentLength} octets)", $offsetIndex);
}
$offsetOfSequence = $offsetIndex;
$sequence = Sequence::fromBinary($binaryData, $offsetIndex);
$offsetOfSequence += $sequence->getNumberOfLengthOctets() + 1;
if ($sequence->getObjectLength() != $contentLength) {
throw new ParserException('Can not parse Subject Alternative Names: The Sequence length does not match the length of the surrounding octet string', $offsetIndex);
}
$parsedObject = new self();
/** @var \FG\ASN1\ASNObject $object */
foreach ($sequence as $object) {
if ($object->getType() == DNSName::IDENTIFIER) {
$domainName = DNSName::fromBinary($binaryData, $offsetOfSequence);
$parsedObject->addDomainName($domainName);
} elseif ($object->getType() == IPAddress::IDENTIFIER) {
$ip = IPAddress::fromBinary($binaryData, $offsetOfSequence);
$parsedObject->addIP($ip);
} else {
throw new ParserException('Could not parse Subject Alternative Name: Only DNSName and IP SANs are currently supported', $offsetIndex);
}
}
$parsedObject->getBinary(); // Determine the number of content octets and object sizes once (just to let the equality unit tests pass :/ )
return $parsedObject;
}
}

290
vendor/geoip2/geoip2/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,290 @@
CHANGELOG
=========
2.11.0 (2020-10-01)
-------------------
* IMPORTANT: PHP 7.2 or greater is now required.
* Added the `isResidentialProxy` property to `GeoIp2\Model\AnonymousIP` and
`GeoIp2\Record\Traits`.
* Additional type hints have been added.
2.10.0 (2019-12-12)
-------------------
* PHP 5.6 or greater is now required.
* The `network` property was added to `GeoIp2\Record\Traits`,
`GeoIp2\Model\AnonymousIp`, `GeoIp2\Model\Asn`,
`GeoIp2\Model\ConnectionType`, `Geoip2\Model\Domain`,
and `GeoIp2\Model\Isp`. This is a string in CIDR format representing the
largest network where all of the properties besides `ipAddress` have the
same value.
* Updated documentation of anonymizer properties - `isAnonymousVpn`
and `isHostingProvider` - to be more descriptive.
* The `userCount` property was added to `GeoIp2\Record\Traits`. This is an
integer which indicates the estimated number of users sharing the
IP/network during the past 24 hours. This output is available from GeoIP2
Precision Insights.
* The `staticIpScore` property was added to `GeoIp2\Record\Traits`. This is
a float which indicates how static or dynamic an IP address is. This
output is available from GeoIP2 Precision Insights.
2.9.0 (2018-04-10)
------------------
* Refer to account IDs using the terminology "account" rather than "user".
2.8.0 (2018-01-18)
------------------
* The `isInEuropeanUnion` property was added to `GeoIp2\Record\Country`
and `GeoIp2\Record\RepresentedCountry`. This property is `true` if the
country is a member state of the European Union.
2.7.0 (2017-10-27)
------------------
* The following new anonymizer properties were added to `GeoIp2\Record\Traits`
for use with GeoIP2 Precision Insights: `isAnonymous`, `isAnonymousVpn`,
`isHostingProvider`, `isPublicProxy`, and `isTorExitNode`.
2.6.0 (2017-07-10)
-----------------
* Code clean-up and tidying.
* Set minimum required PHP version to 5.4 in `composer.json`. Previously,
5.3 would work but was not tested. Now 5.4 is hard minimum version.
2.5.0 (2017-05-08)
------------------
* Support for PHP 5.3 was dropped.
* Added support for GeoLite2 ASN database.
2.4.5 (2017-01-31)
------------------
* Additional error checking on the data returned from `MaxMind\Db\Reader`
was added to help detect corrupt databases. GitHub #83.
2.4.4 (2016-10-11)
------------------
* `isset()` on `mostSpecificSubdivision` attribute now returns the
correct value. Reported by Juan Francisco Giordana. GitHub #81.
2.4.3 (2016-10-11)
------------------
* `isset()` on `name` attribute now returns the correct value. Reported by
Juan Francisco Giordana. GitHub #79.
2.4.2 (2016-08-17)
------------------
* Updated documentation to clarify what the accuracy radius refers to.
* Upgraded `maxmind/web-service-common` to 0.3.0. This version uses
`composer/ca-bundle` rather than our own CA bundle. GitHub #75.
* Improved PHP documentation generation.
2.4.1 (2016-06-10)
------------------
* Corrected type annotations in documentation. GitHub #66.
* Updated documentation to reflect that the accuracy radius is now included
in City.
* Upgraded web service client, which supports setting a proxy. GitHub #59.
2.4.0 (2016-04-15)
------------------
* Added support for the GeoIP2 Enterprise database.
2.3.3 (2015-09-24)
------------------
* Corrected case on `JsonSerializable` interface. Reported by Axel Etcheverry.
GitHub #56.
2.3.2 (2015-09-23)
------------------
* `JsonSerializable` compatibility interface was moved to `GeoIp2\Compat`
rather than the global namespace to prevent autoloading issues. Reported by
Tomas Buteler. GitHub #54.
* Missing documentation for the `$postal` property was added to the
`GeoIp2\Model\City` class. Fix by Roy Sindre Norangshol. GitHub #51.
* In the Phar distribution, source files for this module no longer have their
documentation stripped, allowing IDE introspection to work properly.
Reported by Dominic Black. GitHub #52.
2.3.1 (2015-06-30)
------------------
* Updated `maxmind/web-service-common` to version with fixes for PHP 5.3 and
5.4.
2.3.0 (2015-06-29)
------------------
* Support for demographics fields `averageIncome` and `populationDensity` in
the `Location` record, returned by the Insights endpoint.
* The `isAnonymousProxy` and `isSatelliteProvider` properties on
`GeoIP2\Record\Traits` have been deprecated. Please use our [GeoIP2
Anonymous IP database](https://www.maxmind.com/en/geoip2-anonymous-ip-database)
to determine whether an IP address is used by an anonymizing service.
2.2.0-beta1 (2015-06-09)
------------------------
* Typo fix in documentation.
2.2.0-alpha2 (2015-06-01)
-------------------------
* `maxmind-ws/web-service-common` was renamed to `maxmind/web-service-common`.
2.2.0-alpha1 (2015-05-22)
-------------------------
* The library no longer uses Guzzle and instead uses curl directly.
* Support for `timeout` and `connectTimout` were added to the `$options` array
passed to the `GeoIp2\WebService\Client` constructor. Pull request by Will
Bradley. GitHub #36.
2.1.1 (2014-12-03)
------------------
* The 2.1.0 Phar builds included a shebang line, causing issues when loading
it as a library. This has been corrected. GitHub #33.
2.1.0 (2014-10-29)
------------------
* Update ApiGen dependency to version that isn't broken on case sensitive
file systems.
* Added support for the GeoIP2 Anonymous IP database. The
`GeoIP2\Database\Reader` class now has an `anonymousIp` method which returns
a `GeoIP2\Model\AnonymousIp` object.
* Boolean attributes like those in the `GeoIP2\Record\Traits` class now return
`false` instead of `null` when they were not true.
2.0.0 (2014-09-22)
------------------
* First production release.
0.9.0 (2014-09-15)
------------------
* IMPORTANT: The deprecated `omni()` and `cityIspOrg()` methods have been
removed from `GeoIp2\WebService\Client`.
0.8.1 (2014-09-12)
------------------
* The check added to the `GeoIP2\Database\Reader` lookup methods in 0.8.0 did
not work with the GeoIP2 City Database Subset by Continent with World
Countries. This has been fixed. Fixes GitHub issue #23.
0.8.0 (2014-09-10)
------------------
* The `GeoIp2\Database\Reader` lookup methods (e.g., `city()`, `isp()`) now
throw a `BadMethodCallException` if they are used with a database that
does not match the method. In particular, doing a `city()` lookup on a
GeoIP2 Country database will result in an exception, and vice versa.
* A `metadata()` method has been added to the `GeoIP2\Database\Reader` class.
This returns a `MaxMind\Db\Reader\Metadata` class with information about the
database.
* The name attribute was missing from the RepresentedCountry class.
0.7.0 (2014-07-22)
------------------
* The web service client API has been updated for the v2.1 release of the web
service. In particular, the `cityIspOrg` and `omni` methods on
`GeoIp2\WebService\Client` should be considered deprecated. The `city`
method now provides all of the data formerly provided by `cityIspOrg`, and
the `omni` method has been replaced by the `insights` method.
* Support was added for GeoIP2 Connection Type, Domain and ISP databases.
0.6.3 (2014-05-12)
------------------
* With the previous Phar builds, some users received `phar error: invalid url
or non-existent phar` errors. The correct alias is now used for the Phar,
and this should no longer be an issue.
0.6.2 (2014-05-08)
------------------
* The Phar build was broken with Guzzle 3.9.0+. This has been fixed.
0.6.1 (2014-05-01)
------------------
* This API now officially supports HHVM.
* The `maxmind-db/reader` dependency was updated to a version that does not
require BC Math.
* The Composer compatibility autoload rules are now targeted more narrowly.
* A `box.json` file is included to build a Phar package.
0.6.0 (2014-02-19)
------------------
* This API is now licensed under the Apache License, Version 2.0.
* Model and record classes now implement `JsonSerializable`.
* `isset` now works with model and record classes.
0.5.0 (2013-10-21)
------------------
* Renamed $languages constructor parameters to $locales for both the Client
and Reader classes.
* Documentation and code clean-up (Ben Morel).
* Added the interface `GeoIp2\ProviderInterface`, which is implemented by both
`\GeoIp2\Database\Reader` and `\GeoIp2\WebService\Client`.
0.4.0 (2013-07-16)
------------------
* This is the first release with the GeoIP2 database reader. Please see the
`README.md` file and the `\GeoIp2\Database\Reader` class.
* The general exception classes were replaced with specific exception classes
representing particular types of errors, such as an authentication error.
0.3.0 (2013-07-12)
------------------
* In namespaces and class names, "GeoIP2" was renamed to "GeoIp2" to improve
consistency.
0.2.1 (2013-06-10)
------------------
* First official beta release.
* Documentation updates and corrections.
0.2.0 (2013-05-29)
------------------
* `GenericException` was renamed to `GeoIP2Exception`.
* We now support more languages. The new languages are de, es, fr, and pt-BR.
* The REST API now returns a record with data about your account. There is
a new `GeoIP\Records\MaxMind` class for this data.
* The `continentCode` attribute on `Continent` was renamed to `code`.
* Documentation updates.
0.1.1 (2013-05-14)
------------------
* Updated Guzzle version requirement.
* Fixed Composer example in README.md.
0.1.0 (2013-05-13)
------------------
* Initial release.

202
vendor/geoip2/geoip2/LICENSE vendored Normal file
View File

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

409
vendor/geoip2/geoip2/README.md vendored Normal file
View File

@ -0,0 +1,409 @@
# GeoIP2 PHP API #
## Description ##
This package provides an API for the GeoIP2
[web services](https://dev.maxmind.com/geoip/geoip2/web-services) and
[databases](https://dev.maxmind.com/geoip/geoip2/downloadable). The API also
works with the free
[GeoLite2 databases](https://dev.maxmind.com/geoip/geoip2/geolite2/).
## 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:
```
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`, 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 end
point 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.
$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/geoip2/web-services)
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 5.6 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-2019 by MaxMind, Inc.
This is free software, licensed under the Apache License, Version 2.0.

31
vendor/geoip2/geoip2/composer.json vendored Normal file
View File

@ -0,0 +1,31 @@
{
"name": "geoip2/geoip2",
"description": "MaxMind GeoIP2 PHP API",
"keywords": ["geoip", "geoip2", "geolocation", "ip", "maxmind"],
"homepage": "https://github.com/maxmind/GeoIP2-php",
"type": "library",
"license": "Apache-2.0",
"authors": [
{
"name": "Gregory J. Oschwald",
"email": "goschwald@maxmind.com",
"homepage": "https://www.maxmind.com/"
}
],
"require": {
"maxmind-db/reader": "~1.8",
"maxmind/web-service-common": "~0.8",
"php": ">=7.2",
"ext-json": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "2.*",
"phpunit/phpunit": "^8.0 || ^9.0",
"squizlabs/php_codesniffer": "3.*"
},
"autoload": {
"psr-4": {
"GeoIp2\\": "src"
}
}
}

View File

@ -0,0 +1,25 @@
<?php
require __DIR__ . '/../vendor/autoload.php';
use GeoIp2\Database\Reader;
srand(0);
$reader = new Reader('GeoIP2-City.mmdb');
$count = 500000;
$startTime = microtime(true);
for ($i = 0; $i < $count; ++$i) {
$ip = long2ip(rand(0, pow(2, 32) - 1));
try {
$t = $reader->city($ip);
} catch (\GeoIp2\Exception\AddressNotFoundException $e) {
}
if ($i % 10000 === 0) {
echo $i . ' ' . $ip . "\n";
}
}
$endTime = microtime(true);
$duration = $endTime - $startTime;
echo 'Requests per second: ' . $count / $duration . "\n";

View File

@ -0,0 +1,273 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Database;
use GeoIp2\Exception\AddressNotFoundException;
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
{
private $dbReader;
private $dbType;
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
{
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
{
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
{
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
{
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
{
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
{
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
{
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
{
return $this->flatModelFor(
'Isp',
'GeoIP2-ISP',
$ipAddress
);
}
private function modelFor(string $class, string $type, string $ipAddress)
{
list($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)
{
list($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"
);
}
list($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(): \MaxMind\Db\Reader\Metadata
{
return $this->dbReader->metadata();
}
/**
* Closes the GeoIP2 database and returns the resources to the system.
*/
public function close(): void
{
$this->dbReader->close();
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Exception;
/**
* This class represents a generic error.
*/
class AddressNotFoundException extends GeoIp2Exception
{
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Exception;
/**
* This class represents a generic error.
*/
class AuthenticationException extends GeoIp2Exception
{
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Exception;
/**
* This class represents a generic error.
*/
class GeoIp2Exception extends \Exception
{
}

View File

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Exception;
/**
* This class represents an HTTP transport error.
*/
class HttpException extends GeoIp2Exception
{
/**
* The URI queried.
*/
public $uri;
public function __construct(
string $message,
int $httpStatus,
string $uri,
\Exception $previous = null
) {
$this->uri = $uri;
parent::__construct($message, $httpStatus, $previous);
}
}

View File

@ -0,0 +1,28 @@
<?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.
*/
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);
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Exception;
/**
* This class represents a generic error.
*/
class OutOfQueriesException extends GeoIp2Exception
{
}

View File

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Model;
/**
* @ignore
*/
abstract class AbstractModel implements \JsonSerializable
{
protected $raw;
/**
* @ignore
*/
public function __construct(array $raw)
{
$this->raw = $raw;
}
/**
* @ignore
*/
protected function get(string $field)
{
if (isset($this->raw[$field])) {
return $this->raw[$field];
}
if (preg_match('/^is_/', $field)) {
return false;
}
return null;
}
/**
* @ignore
*/
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;
}
}

View File

@ -0,0 +1,60 @@
<?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
{
protected $isAnonymous;
protected $isAnonymousVpn;
protected $isHostingProvider;
protected $isPublicProxy;
protected $isResidentialProxy;
protected $isTorExitNode;
protected $ipAddress;
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'));
}
}

43
vendor/geoip2/geoip2/src/Model/Asn.php vendored Normal file
View File

@ -0,0 +1,43 @@
<?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
{
protected $autonomousSystemNumber;
protected $autonomousSystemOrganization;
protected $ipAddress;
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'));
}
}

111
vendor/geoip2/geoip2/src/Model/City.php vendored Normal file
View File

@ -0,0 +1,111 @@
<?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/geoip2/web-services 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
*/
protected $city;
/**
* @ignore
*/
protected $location;
/**
* @ignore
*/
protected $postal;
/**
* @ignore
*/
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) {
array_push(
$this->subdivisions,
new \GeoIp2\Record\Subdivision($sub, $locales)
);
}
}
/**
* @ignore
*/
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);
}
}

View File

@ -0,0 +1,39 @@
<?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
{
protected $connectionType;
protected $ipAddress;
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'));
}
}

View File

@ -0,0 +1,70 @@
<?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/geoip2/web-services 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.
*/
class Country extends AbstractModel
{
protected $continent;
protected $country;
protected $locales;
protected $maxmind;
protected $registeredCountry;
protected $representedCountry;
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;
}
}

View File

@ -0,0 +1,39 @@
<?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
{
protected $domain;
protected $ipAddress;
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'));
}
}

View 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/geoip2/web-services for more details.
*/
class Enterprise extends City
{
}

View 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/geoip2/web-services for more details.
*/
class Insights extends City
{
}

52
vendor/geoip2/geoip2/src/Model/Isp.php vendored Normal file
View File

@ -0,0 +1,52 @@
<?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 $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
{
protected $autonomousSystemNumber;
protected $autonomousSystemOrganization;
protected $isp;
protected $organization;
protected $ipAddress;
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->organization = $this->get('organization');
$ipAddress = $this->get('ip_address');
$this->ipAddress = $ipAddress;
$this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
}
}

View 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): \GeoIp2\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): \GeoIp2\Model\City;
}

View File

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Record;
abstract class AbstractPlaceRecord extends AbstractRecord
{
private $locales;
/**
* @ignore
*/
public function __construct(?array $record, array $locales = ['en'])
{
$this->locales = $locales;
parent::__construct($record);
}
/**
* @ignore
*/
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();
return $locale === null ? null : $this->names[$locale];
}
private function firstSetNameLocale(): ?string
{
foreach ($this->locales as $locale) {
if (isset($this->names[$locale])) {
return $locale;
}
}
return null;
}
}

View File

@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Record;
abstract class AbstractRecord implements \JsonSerializable
{
private $record;
/**
* @ignore
*/
public function __construct(?array $record)
{
$this->record = isset($record) ? $record : [];
}
/**
* @ignore
*/
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];
} elseif ($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
{
return \in_array($attr, $this->validAttributes, true);
}
public function jsonSerialize(): ?array
{
return $this->record;
}
}

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