├── msyh.ttf
├── xhxh.jpg
├── composer.json
├── vendor
├── autoload.php
├── composer
│ ├── autoload_classmap.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── ca-bundle
│ │ ├── LICENSE
│ │ ├── composer.json
│ │ ├── README.md
│ │ └── src
│ │ │ └── CaBundle.php
│ ├── LICENSE
│ ├── autoload_static.php
│ ├── autoload_real.php
│ ├── installed.json
│ └── ClassLoader.php
├── ua-parser
│ └── uap-php
│ │ ├── src
│ │ ├── Exception
│ │ │ ├── DomainException.php
│ │ │ ├── ReaderException.php
│ │ │ ├── FetcherException.php
│ │ │ ├── InvalidArgumentException.php
│ │ │ └── FileNotFoundException.php
│ │ ├── Result
│ │ │ ├── Device.php
│ │ │ ├── AbstractSoftware.php
│ │ │ ├── AbstractClient.php
│ │ │ ├── UserAgent.php
│ │ │ ├── OperatingSystem.php
│ │ │ ├── AbstractVersionedSoftware.php
│ │ │ └── Client.php
│ │ ├── Util
│ │ │ ├── Logfile
│ │ │ │ ├── ReaderInterface.php
│ │ │ │ ├── ApacheCommonLogFormatReader.php
│ │ │ │ └── AbstractReader.php
│ │ │ ├── Fetcher.php
│ │ │ └── Converter.php
│ │ ├── Command
│ │ │ ├── ParserCommand.php
│ │ │ ├── FetchCommand.php
│ │ │ ├── UpdateCommand.php
│ │ │ ├── ConvertCommand.php
│ │ │ └── LogfileCommand.php
│ │ ├── DeviceParser.php
│ │ ├── OperatingSystemParser.php
│ │ ├── Parser.php
│ │ ├── UserAgentParser.php
│ │ └── AbstractParser.php
│ │ ├── LICENSE
│ │ ├── update-resources.sh
│ │ ├── bin
│ │ └── uaparser
│ │ ├── composer.json
│ │ ├── README.md
│ │ └── CHANGELOG.md
└── bin
│ └── uaparser
├── README.md
├── index.php
└── composer.lock
/msyh.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xhboke/IP/HEAD/msyh.ttf
--------------------------------------------------------------------------------
/xhxh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xhboke/IP/HEAD/xhxh.jpg
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": {
3 | "ua-parser/uap-php": "^3.9"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/vendor/autoload.php:
--------------------------------------------------------------------------------
1 | array($vendorDir . '/ua-parser/uap-php/src'),
10 | 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
11 | );
12 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Exception/DomainException.php:
--------------------------------------------------------------------------------
1 | /dev/null; cd '../ua-parser/uap-php/bin' && pwd)
4 |
5 | if [ -d /proc/cygdrive ]; then
6 | case $(which php) in
7 | $(readlink -n /proc/cygdrive)/*)
8 | # We are in Cygwin using Windows php, so the path must be translated
9 | dir=$(cygpath -m "$dir");
10 | ;;
11 | esac
12 | fi
13 |
14 | "${dir}/uaparser" "$@"
15 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Result/Device.php:
--------------------------------------------------------------------------------
1 | family;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Util/Logfile/ReaderInterface.php:
--------------------------------------------------------------------------------
1 | toString();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011-2012 Dave Olsen, http://dmolsen.com
2 | Licensed under the MIT license
3 |
4 | ua-parser-php is a PHP-based pseudo-port of the ua-parser project. Learn more about the ua-parser project at:
5 |
6 | http://code.google.com/p/ua-parser/
7 |
8 | The user agents data from the ua-parser project is licensed under the Apache license.
9 | spyc-0.5, for loading the YAML, is licensed under the MIT license.
10 | The initial list of generic feature phones & smartphones came from Mobile Web OSP under the MIT license
11 | The initial list of spiders was taken from Yiibu's profile project under the MIT license.
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Result/UserAgent.php:
--------------------------------------------------------------------------------
1 | formatVersion($this->major, $this->minor, $this->patch);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Result/OperatingSystem.php:
--------------------------------------------------------------------------------
1 | formatVersion($this->major, $this->minor, $this->patch, $this->patchMinor);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/update-resources.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | function try_catch() {
4 | output=`"$@" &>/dev/stdout`
5 | if [ $? -gt 0 ]; then
6 | echo -e "Command $@ failed\n\n$output"
7 | exit 1
8 | fi
9 | }
10 |
11 | try_catch git pull
12 | try_catch git submodule foreach git pull origin master
13 | try_catch bin/uaparser ua-parser:convert uap-core/regexes.yaml
14 | try_catch vendor/bin/phpunit --stop-on-failure
15 | try_catch git commit -a -m "Scheduled resource update"
16 | try_catch git push origin master
17 | new_version=`git tag | sort --version-sort | tail -n 1 | awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{if(length($NF+1)>length($NF))$(NF-1)++; $NF=sprintf("%0*d", length($NF), ($NF+1)%(10^length($NF))); print}'`
18 | try_catch git tag $new_version
19 | git push origin $new_version
20 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Result/AbstractVersionedSoftware.php:
--------------------------------------------------------------------------------
1 | family, $this->toVersion())));
21 | }
22 |
23 | /** @return string */
24 | protected function formatVersion()
25 | {
26 | return join('.', array_filter(func_get_args(), 'is_numeric'));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IP签名档源码
2 |
说在前面
3 | 自从论坛IP签名档开放以来,访问量达到1806287,一百八十多万,由于证书过期和懒得维护。今特开源。
4 | 演示效果
5 |
6 | 原帖地址
7 | https://www.xhboke.com/858.html
8 | 修复
9 | 2020.04.22
10 |
时隔两年,新增天气
11 | 修复部分ua无法解析
12 | 效果:https://xhboke.com/news/?s=6L+Z5piv5ryU56S65pWI5p6c77yM6L+Z6YeM5paH5a2X5Y+v5Lul5pS55Y+Y
13 | 2019.7.16
14 |
修复并发量限制
15 | 测试CentOS+PHP7.2
16 | 2018.6.11
17 | $url="http://ip.taobao.com/service/getIpInfo.php?ip=".$ip;
18 | $country = $data['data']['country'];
19 | $region = $data['data']['region'];
20 | $city = $data['data']['city'];
21 | 感谢
22 | https://github.com/ua-parser/uap-php
23 |
24 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Result/Client.php:
--------------------------------------------------------------------------------
1 | originalUserAgent = $originalUserAgent;
32 | }
33 |
34 | public function toString()
35 | {
36 | return $this->ua->toString() . '/' . $this->os->toString();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Exception/InvalidArgumentException.php:
--------------------------------------------------------------------------------
1 | add(new ConvertCommand($resourceDirectory, $defaultYamlFile));
26 | $application->add(new UpdateCommand($resourceDirectory));
27 | $application->add(new ParserCommand());
28 | $application->add(new LogfileCommand());
29 | $application->add(new FetchCommand($defaultYamlFile));
30 |
31 | $application->run();
32 |
--------------------------------------------------------------------------------
/vendor/composer/autoload_static.php:
--------------------------------------------------------------------------------
1 |
11 | array (
12 | 'UAParser\\' => 9,
13 | ),
14 | 'C' =>
15 | array (
16 | 'Composer\\CaBundle\\' => 18,
17 | ),
18 | );
19 |
20 | public static $prefixDirsPsr4 = array (
21 | 'UAParser\\' =>
22 | array (
23 | 0 => __DIR__ . '/..' . '/ua-parser/uap-php/src',
24 | ),
25 | 'Composer\\CaBundle\\' =>
26 | array (
27 | 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
28 | ),
29 | );
30 |
31 | public static function getInitializer(ClassLoader $loader)
32 | {
33 | return \Closure::bind(function () use ($loader) {
34 | $loader->prefixLengthsPsr4 = ComposerStaticInit94fa57844104d91fdb2d302dc7e75828::$prefixLengthsPsr4;
35 | $loader->prefixDirsPsr4 = ComposerStaticInit94fa57844104d91fdb2d302dc7e75828::$prefixDirsPsr4;
36 |
37 | }, null, ClassLoader::class);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Command/ParserCommand.php:
--------------------------------------------------------------------------------
1 | setName('ua-parser:parse')
23 | ->setDescription('Parses a user agent string and dumps the results.')
24 | ->addArgument(
25 | 'user-agent',
26 | null,
27 | InputArgument::REQUIRED,
28 | 'User agent string to analyze'
29 | )
30 | ;
31 | }
32 |
33 | protected function execute(InputInterface $input, OutputInterface $output)
34 | {
35 | $result = Parser::create()->parse($input->getArgument('user-agent'));
36 |
37 | $output->writeln(json_encode($result, JSON_PRETTY_PRINT));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/DeviceParser.php:
--------------------------------------------------------------------------------
1 | regexes['device_parsers'], $userAgent);
27 |
28 | if ($matches) {
29 | $device->family = self::multiReplace($regex, 'device_replacement', $matches[1], $matches);
30 | $device->brand = self::multiReplace($regex, 'brand_replacement', null, $matches);
31 | $deviceModelDefault = $matches[1] !== 'Other' ? $matches[1] : null;
32 | $device->model = self::multiReplace($regex, 'model_replacement', $deviceModelDefault, $matches);
33 | }
34 |
35 | return $device;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Util/Logfile/ApacheCommonLogFormatReader.php:
--------------------------------------------------------------------------------
1 | .*?)\" # User Agent
35 | $@x';
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/OperatingSystemParser.php:
--------------------------------------------------------------------------------
1 | regexes['os_parsers'], $userAgent);
27 |
28 | if ($matches) {
29 | $os->family = self::multiReplace($regex, 'os_replacement', $matches[1], $matches);
30 | $os->major = self::multiReplace($regex, 'os_v1_replacement', $matches[2], $matches);
31 | $os->minor = self::multiReplace($regex, 'os_v2_replacement', $matches[3], $matches);
32 | $os->patch = self::multiReplace($regex, 'os_v3_replacement', $matches[4], $matches);
33 | $os->patchMinor = self::multiReplace($regex, 'os_v4_replacement', $matches[5], $matches);
34 | }
35 |
36 | return $os;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ua-parser/uap-php",
3 | "description": "A multi-language port of Browserscope's user agent parser.",
4 | "require": {
5 | "php": ">=5.3.0",
6 | "composer/ca-bundle": "^1.1"
7 | },
8 | "require-dev": {
9 | "phpunit/phpunit": "<8",
10 | "symfony/yaml": "^2.0 || ^3.0 || ^4.0",
11 | "symfony/filesystem": "^2.0 || ^3.0 || ^4.0",
12 | "symfony/finder": "^2.0 || ^3.0 || ^4.0",
13 | "symfony/console": "^2.0 || ^3.0 || ^4.0"
14 | },
15 | "suggest": {
16 | "symfony/yaml": "Required for CLI usage - ^4.0 || ^5.0",
17 | "symfony/filesystem": "Required for CLI usage - 2.0 || ^3.0 || ^4.0",
18 | "symfony/finder": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0",
19 | "symfony/console": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0"
20 | },
21 | "prefer-stable": true,
22 | "license": "MIT",
23 | "authors": [
24 | {
25 | "name": "Dave Olsen",
26 | "email": "dmolsen@gmail.com"
27 | },
28 | {
29 | "name": "Lars Strojny",
30 | "email": "lars@strojny.net"
31 | }
32 | ],
33 | "autoload": {
34 | "psr-4": {
35 | "UAParser\\": "src"
36 | }
37 | },
38 | "autoload-dev": {
39 | "psr-4": {
40 | "UAParser\\Test\\": "tests/"
41 | }
42 | },
43 | "bin": ["bin/uaparser"]
44 | }
45 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Command/FetchCommand.php:
--------------------------------------------------------------------------------
1 | defaultYamlFile = $defaultYamlFile;
26 | parent::__construct();
27 | }
28 |
29 | protected function configure()
30 | {
31 | $this
32 | ->setName('ua-parser:fetch')
33 | ->setDescription('Fetches an updated YAML file for ua-parser.')
34 | ->addArgument(
35 | 'file',
36 | InputArgument::OPTIONAL,
37 | 'regexes.yaml output file',
38 | $this->defaultYamlFile
39 | )
40 | ;
41 | }
42 |
43 | protected function execute(InputInterface $input, OutputInterface $output)
44 | {
45 | $fs = new Filesystem();
46 | $fetcher = new Fetcher();
47 | $fs->dumpFile($input->getArgument('file'), $fetcher->fetch());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/vendor/composer/ca-bundle/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "composer/ca-bundle",
3 | "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
4 | "type": "library",
5 | "license": "MIT",
6 | "keywords": [
7 | "cabundle",
8 | "cacert",
9 | "certificate",
10 | "ssl",
11 | "tls"
12 | ],
13 | "authors": [
14 | {
15 | "name": "Jordi Boggiano",
16 | "email": "j.boggiano@seld.be",
17 | "homepage": "http://seld.be"
18 | }
19 | ],
20 | "support": {
21 | "irc": "irc://irc.freenode.org/composer",
22 | "issues": "https://github.com/composer/ca-bundle/issues"
23 | },
24 | "require": {
25 | "ext-openssl": "*",
26 | "ext-pcre": "*",
27 | "php": "^5.3.2 || ^7.0 || ^8.0"
28 | },
29 | "require-dev": {
30 | "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
31 | "psr/log": "^1.0",
32 | "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0"
33 | },
34 | "autoload": {
35 | "psr-4": {
36 | "Composer\\CaBundle\\": "src"
37 | }
38 | },
39 | "autoload-dev": {
40 | "psr-4": {
41 | "Composer\\CaBundle\\": "tests"
42 | }
43 | },
44 | "extra": {
45 | "branch-alias": {
46 | "dev-master": "1.x-dev"
47 | }
48 | },
49 | "config": {
50 | "platform": {
51 | "php": "5.3.9"
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Command/UpdateCommand.php:
--------------------------------------------------------------------------------
1 | resourceDirectory = $resourceDirectory;
26 | parent::__construct();
27 | }
28 |
29 | protected function configure()
30 | {
31 | $this
32 | ->setName('ua-parser:update')
33 | ->setDescription('Fetches an updated YAML file for ua-parser and overwrites the current PHP file.')
34 | ->addOption(
35 | 'no-backup',
36 | null,
37 | InputOption::VALUE_NONE,
38 | 'Do not backup the previously existing file'
39 | )
40 | ;
41 | }
42 |
43 | protected function execute(InputInterface $input, OutputInterface $output)
44 | {
45 | $fetcher = new Fetcher();
46 | $converter = new Converter($this->resourceDirectory);
47 |
48 | $converter->convertString($fetcher->fetch(), !$input->getOption('no-backup'));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Util/Logfile/AbstractReader.php:
--------------------------------------------------------------------------------
1 | test($line)) {
26 | return $reader;
27 | }
28 | }
29 | }
30 |
31 | private static function getReaders()
32 | {
33 | if (static::$readers) {
34 | return static::$readers;
35 | }
36 |
37 | static::$readers[] = new ApacheCommonLogFormatReader();
38 |
39 | return static::$readers;
40 | }
41 |
42 | public function test($line)
43 | {
44 | $matches = $this->match($line);
45 |
46 | return isset($matches['userAgentString']);
47 | }
48 |
49 | public function read($line)
50 | {
51 | $matches = $this->match($line);
52 |
53 | if (!isset($matches['userAgentString'])) {
54 | throw ReaderException::userAgentParserError($line);
55 | }
56 |
57 | return $matches['userAgentString'];
58 | }
59 |
60 | protected function match($line)
61 | {
62 | if (preg_match($this->getRegex(), $line, $matches)) {
63 | return $matches;
64 | }
65 |
66 | return array();
67 | }
68 |
69 | abstract protected function getRegex();
70 | }
71 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Parser.php:
--------------------------------------------------------------------------------
1 | regexes
27 | *
28 | * @param array $regexes
29 | */
30 | public function __construct(array $regexes)
31 | {
32 | parent::__construct($regexes);
33 | $this->deviceParser = new DeviceParser($this->regexes);
34 | $this->operatingSystemParser = new OperatingSystemParser($this->regexes);
35 | $this->userAgentParser = new UserAgentParser($this->regexes);
36 | }
37 |
38 | /**
39 | * Sets up some standard variables as well as starts the user agent parsing process
40 | *
41 | * @param string $userAgent a user agent string to test, defaults to an empty string
42 | * @param array $jsParseBits
43 | * @return Client
44 | */
45 | public function parse($userAgent, array $jsParseBits = array())
46 | {
47 | $client = new Client($userAgent);
48 |
49 | $client->ua = $this->userAgentParser->parseUserAgent($userAgent, $jsParseBits);
50 | $client->os = $this->operatingSystemParser->parseOperatingSystem($userAgent);
51 | $client->device = $this->deviceParser->parseDevice($userAgent);
52 |
53 | return $client;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Util/Fetcher.php:
--------------------------------------------------------------------------------
1 | streamContext = $streamContext;
25 | } else {
26 | $this->streamContext = stream_context_create(
27 | array(
28 | 'ssl' => array(
29 | 'verify_peer' => true,
30 | 'verify_depth' => 10,
31 | 'cafile' => CaBundle::getSystemCaRootBundlePath(),
32 | static::getPeerNameKey() => 'www.github.com',
33 | 'disable_compression' => true,
34 | )
35 | )
36 | );
37 | }
38 | }
39 |
40 | public function fetch()
41 | {
42 | $level = error_reporting(0);
43 | $result = file_get_contents($this->resourceUri, null, $this->streamContext);
44 | error_reporting($level);
45 |
46 | if ($result === false) {
47 | $error = error_get_last();
48 | throw FetcherException::httpError($this->resourceUri, $error['message']);
49 | }
50 |
51 | return $result;
52 | }
53 |
54 | public static function getPeerNameKey()
55 | {
56 | return version_compare(PHP_VERSION, '5.6') === 1 ? 'peer_name' : 'CN_match';
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Command/ConvertCommand.php:
--------------------------------------------------------------------------------
1 | resourceDirectory = $resourceDirectory;
29 | $this->defaultYamlFile = $defaultYamlFile;
30 | parent::__construct();
31 | }
32 |
33 | protected function configure()
34 | {
35 | $this
36 | ->setName('ua-parser:convert')
37 | ->setDescription('Converts an existing regexes.yaml file to a regexes.php file.')
38 | ->addArgument(
39 | 'file',
40 | InputArgument::OPTIONAL,
41 | 'Path to the regexes.yaml file',
42 | $this->defaultYamlFile
43 | )
44 | ->addOption(
45 | 'no-backup',
46 | null,
47 | InputOption::VALUE_NONE,
48 | 'Do not backup the previously existing file'
49 | )
50 | ;
51 | }
52 |
53 | protected function execute(InputInterface $input, OutputInterface $output)
54 | {
55 | $this->getConverter()->convertFile($input->getArgument('file'), $input->getOption('no-backup'));
56 | }
57 |
58 | private function getConverter()
59 | {
60 | return new Converter($this->resourceDirectory);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/vendor/composer/autoload_real.php:
--------------------------------------------------------------------------------
1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30 | if ($useStaticLoader) {
31 | require_once __DIR__ . '/autoload_static.php';
32 |
33 | call_user_func(\Composer\Autoload\ComposerStaticInit94fa57844104d91fdb2d302dc7e75828::getInitializer($loader));
34 | } else {
35 | $map = require __DIR__ . '/autoload_namespaces.php';
36 | foreach ($map as $namespace => $path) {
37 | $loader->set($namespace, $path);
38 | }
39 |
40 | $map = require __DIR__ . '/autoload_psr4.php';
41 | foreach ($map as $namespace => $path) {
42 | $loader->setPsr4($namespace, $path);
43 | }
44 |
45 | $classMap = require __DIR__ . '/autoload_classmap.php';
46 | if ($classMap) {
47 | $loader->addClassMap($classMap);
48 | }
49 | }
50 |
51 | $loader->register(true);
52 |
53 | return $loader;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | parse($ua);
14 | $os = $result->os->toString(); // Mac OS X
15 | $browser = $result->device->family.'-'.$result->ua->family;// Safari 6.0.2
16 | //地址、温度
17 | $data = json_decode(curl_get('https://api.xhboke.com/ip/v1.php?ip='.$ip), true);
18 | $country = $data['site']['country'];
19 | $region = $data['site']['region'];
20 | $adcode = $data['site']['adcode'];
21 | $weather = $data['city']['weather'];
22 | $temperature = $data['city']['temperature'];
23 | //历史上今天
24 | //$data = json_decode(get_curl('https://xhboke.com/mz/today.php'), true);
25 | //$today = $data['cover']['title'];
26 | //定义颜色
27 | $black = ImageColorAllocate($im, 0,0,0);//定义黑色的值
28 | $red = ImageColorAllocate($im, 255,0,0);//红色
29 | $font = 'msyh.ttf';//加载字体
30 | //输出
31 | imagettftext($im, 16, 0, 10, 40, $red, $font,'欢迎您来自'.$country.'-'.$region.'的朋友');
32 | imagettftext($im, 16, 0, 10, 72, $red, $font, '今天是'.date('Y年n月j日').' 星期'.$weekarray[date("w")]);//当前时间添加到图片
33 | imagettftext($im, 16, 0, 10, 104, $red, $font,'您的IP是:'.$ip.' '.$weather." ".$temperature.'℃');//ip
34 | imagettftext($im, 16, 0, 10, 140, $red, $font,'您使用的是'.$os.'操作系统');
35 | imagettftext($im, 16, 0, 10, 175, $red, $font,'您使用的是'.$browser);
36 | imagettftext($im, 13, 0, 10, 200, $black, $font,$get);
37 | ImageGif($im);
38 | ImageDestroy($im);
39 |
40 |
41 | function curl_get($url, array $params = array(), $timeout = 6){
42 | $ch = curl_init();
43 | curl_setopt($ch, CURLOPT_URL, $url);
44 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
45 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
46 | $file_contents = curl_exec($ch);
47 | curl_close($ch);
48 | return $file_contents;
49 | }
50 | ?>
51 |
52 |
53 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/UserAgentParser.php:
--------------------------------------------------------------------------------
1 | family = $jsParseBits['js_user_agent_family'];
30 | $ua->major = $jsParseBits['js_user_agent_v1'];
31 | $ua->minor = $jsParseBits['js_user_agent_v2'];
32 | $ua->patch = $jsParseBits['js_user_agent_v3'];
33 |
34 | } else {
35 |
36 | list($regex, $matches) = self::tryMatch($this->regexes['user_agent_parsers'], $userAgent);
37 |
38 | if ($matches) {
39 | $ua->family = self::multiReplace($regex, 'family_replacement', $matches[1], $matches);
40 | $ua->major = self::multiReplace($regex, 'v1_replacement', $matches[2], $matches);
41 | $ua->minor = self::multiReplace($regex, 'v2_replacement', $matches[3], $matches);
42 | $ua->patch = self::multiReplace($regex, 'v3_replacement', $matches[4], $matches);
43 | }
44 | }
45 |
46 | if (isset($jsParseBits['js_user_agent_string'])) {
47 | $jsUserAgentString = $jsParseBits['js_user_agent_string'];
48 | if (strpos($jsUserAgentString, 'Chrome/') !== false && strpos($userAgent, 'chromeframe') !== false) {
49 | $override = $this->parseUserAgent($jsUserAgentString);
50 | $ua->family = sprintf('Chrome Frame (%s %s)', $ua->family, $ua->major);
51 | $ua->major = $override->major;
52 | $ua->minor = $override->minor;
53 | $ua->patch = $override->patch;
54 | }
55 | }
56 |
57 | return $ua;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/vendor/composer/ca-bundle/README.md:
--------------------------------------------------------------------------------
1 | composer/ca-bundle
2 | ==================
3 |
4 | Small utility library that lets you find a path to the system CA bundle,
5 | and includes a fallback to the Mozilla CA bundle.
6 |
7 | Originally written as part of [composer/composer](https://github.com/composer/composer),
8 | now extracted and made available as a stand-alone library.
9 |
10 |
11 | Installation
12 | ------------
13 |
14 | Install the latest version with:
15 |
16 | ```bash
17 | $ composer require composer/ca-bundle
18 | ```
19 |
20 |
21 | Requirements
22 | ------------
23 |
24 | * PHP 5.3.2 is required but using the latest version of PHP is highly recommended.
25 |
26 |
27 | Basic usage
28 | -----------
29 |
30 | ### `Composer\CaBundle\CaBundle`
31 |
32 | - `CaBundle::getSystemCaRootBundlePath()`: Returns the system CA bundle path, or a path to the bundled one as fallback
33 | - `CaBundle::getBundledCaBundlePath()`: Returns the path to the bundled CA file
34 | - `CaBundle::validateCaFile($filename)`: Validates a CA file using openssl_x509_parse only if it is safe to use
35 | - `CaBundle::isOpensslParseSafe()`: Test if it is safe to use the PHP function openssl_x509_parse()
36 | - `CaBundle::reset()`: Resets the static caches
37 |
38 |
39 | #### To use with curl
40 |
41 | ```php
42 | $curl = curl_init("https://example.org/");
43 |
44 | $caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
45 | if (is_dir($caPathOrFile)) {
46 | curl_setopt($curl, CURLOPT_CAPATH, $caPathOrFile);
47 | } else {
48 | curl_setopt($curl, CURLOPT_CAINFO, $caPathOrFile);
49 | }
50 |
51 | $result = curl_exec($curl);
52 | ```
53 |
54 | #### To use with php streams
55 |
56 | ```php
57 | $opts = array(
58 | 'http' => array(
59 | 'method' => "GET"
60 | )
61 | );
62 |
63 | $caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
64 | if (is_dir($caPathOrFile)) {
65 | $opts['ssl']['capath'] = $caPathOrFile;
66 | } else {
67 | $opts['ssl']['cafile'] = $caPathOrFile;
68 | }
69 |
70 | $context = stream_context_create($opts);
71 | $result = file_get_contents('https://example.com', false, $context);
72 | ```
73 |
74 | #### To use with Guzzle
75 |
76 | ```php
77 | $client = new \GuzzleHttp\Client([
78 | \GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
79 | ]);
80 | ```
81 |
82 | License
83 | -------
84 |
85 | composer/ca-bundle is licensed under the MIT License, see the LICENSE file for details.
86 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Util/Converter.php:
--------------------------------------------------------------------------------
1 | destination = $destination;
30 | $this->fs = $fs ? $fs : new Filesystem();
31 | }
32 |
33 | /**
34 | * @param string $yamlFile
35 | * @param bool $backupBeforeOverride
36 | * @throws FileNotFoundException
37 | */
38 | public function convertFile($yamlFile, $backupBeforeOverride = true)
39 | {
40 | if (!$this->fs->exists($yamlFile)) {
41 | throw FileNotFoundException::fileNotFound($yamlFile);
42 | }
43 |
44 | $this->doConvert(Yaml::parse(file_get_contents($yamlFile)), $backupBeforeOverride);
45 | }
46 |
47 | /**
48 | * @param string $yamlString
49 | * @param bool $backupBeforeOverride
50 | */
51 | public function convertString($yamlString, $backupBeforeOverride = true)
52 | {
53 | $this->doConvert(Yaml::parse($yamlString), $backupBeforeOverride);
54 | }
55 |
56 | /**
57 | * @param array $regexes
58 | * @param bool $backupBeforeOverride
59 | */
60 | protected function doConvert(array $regexes, $backupBeforeOverride = true)
61 | {
62 | $regexes = $this->sanitizeRegexes($regexes);
63 | $data = "destination . '/regexes.php';
66 | if ($backupBeforeOverride && $this->fs->exists($regexesFile)) {
67 |
68 | $currentHash = hash('sha512', file_get_contents($regexesFile));
69 | $futureHash = hash('sha512', $data);
70 |
71 | if ($futureHash === $currentHash) {
72 | return;
73 | }
74 |
75 | $backupFile = $this->destination . '/regexes-' . $currentHash . '.php';
76 | $this->fs->copy($regexesFile, $backupFile);
77 | }
78 |
79 | $this->fs->dumpFile($regexesFile, $data);
80 | }
81 |
82 | private function sanitizeRegexes(array $regexes)
83 | {
84 | foreach ($regexes as $groupName => $group) {
85 | $regexes[$groupName] = array_map(array($this, 'sanitizeRegex'), $group);
86 | }
87 |
88 | return $regexes;
89 | }
90 |
91 | private function sanitizeRegex(array $regex)
92 | {
93 | $regex['regex'] = str_replace('@', '\@', $regex['regex']);
94 |
95 | return $regex;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/AbstractParser.php:
--------------------------------------------------------------------------------
1 | regexes = $regexes;
25 | }
26 |
27 | /**
28 | * Create parser instance
29 | *
30 | * Either pass a custom regexes.php file or leave the argument empty and use the default file.
31 | *
32 | * @param string $file
33 | * @throws FileNotFoundException
34 | * @return static
35 | */
36 | public static function create($file = null)
37 | {
38 | return $file ? static::createCustom($file) : static::createDefault();
39 | }
40 |
41 | /**
42 | * @return static
43 | * @throws FileNotFoundException
44 | */
45 | protected static function createDefault()
46 | {
47 | return static::createInstance(
48 | static::getDefaultFile(),
49 | array('UAParser\Exception\FileNotFoundException', 'defaultFileNotFound')
50 | );
51 | }
52 |
53 | /**
54 | * @return static
55 | * @throws FileNotFoundException
56 | */
57 | protected static function createCustom($file)
58 | {
59 | return static::createInstance(
60 | $file,
61 | array('UAParser\Exception\FileNotFoundException', 'customRegexFileNotFound')
62 | );
63 | }
64 |
65 | private static function createInstance($file, $exceptionFactory)
66 | {
67 | if (!file_exists($file)) {
68 | throw call_user_func($exceptionFactory, $file);
69 | }
70 |
71 | return new static(include $file);
72 | }
73 |
74 | /**
75 | * @param array $regexes
76 | * @param string $userAgent
77 | * @return array
78 | */
79 | protected static function tryMatch(array $regexes, $userAgent)
80 | {
81 | foreach ($regexes as $regex) {
82 | $flag = isset($regex['regex_flag']) ? $regex['regex_flag'] : '';
83 | if (preg_match('@' . $regex['regex'] . '@' . $flag, $userAgent, $matches)) {
84 |
85 | $defaults = array(
86 | 1 => 'Other',
87 | 2 => null,
88 | 3 => null,
89 | 4 => null,
90 | 5 => null,
91 | );
92 |
93 | return array($regex, $matches + $defaults);
94 | }
95 | }
96 |
97 | return array(null, null);
98 | }
99 |
100 | /**
101 | * @param array $regex
102 | * @param string $key
103 | * @param string $default
104 | * @param array $matches
105 | * @return string|null
106 | */
107 | protected static function multiReplace(array $regex, $key, $default, array $matches)
108 | {
109 | if (!isset($regex[$key])) {
110 | return self::emptyStringToNull($default);
111 | }
112 |
113 | $replacement = preg_replace_callback(
114 | '|\$(?P\d)|',
115 | function ($m) use ($matches) {
116 | return isset($matches[$m['key']]) ? $matches[$m['key']] : '';
117 | },
118 | $regex[$key]
119 | );
120 |
121 | return self::emptyStringToNull($replacement);
122 | }
123 |
124 | private static function emptyStringToNull($string)
125 | {
126 | $string = trim($string);
127 |
128 | return $string === '' ? null : $string;
129 | }
130 |
131 | /**
132 | * @return string
133 | */
134 | protected static function getDefaultFile()
135 | {
136 | return static::$defaultFile
137 | ? static::$defaultFile
138 | : realpath(__DIR__ . '/../resources') . DIRECTORY_SEPARATOR . 'regexes.php';
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/vendor/composer/installed.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "composer/ca-bundle",
4 | "version": "1.2.6",
5 | "version_normalized": "1.2.6.0",
6 | "source": {
7 | "type": "git",
8 | "url": "https://github.com/composer/ca-bundle.git",
9 | "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e"
10 | },
11 | "dist": {
12 | "type": "zip",
13 | "url": "https://api.github.com/repos/composer/ca-bundle/zipball/47fe531de31fca4a1b997f87308e7d7804348f7e",
14 | "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e",
15 | "shasum": ""
16 | },
17 | "require": {
18 | "ext-openssl": "*",
19 | "ext-pcre": "*",
20 | "php": "^5.3.2 || ^7.0 || ^8.0"
21 | },
22 | "require-dev": {
23 | "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
24 | "psr/log": "^1.0",
25 | "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0"
26 | },
27 | "time": "2020-01-13T10:02:55+00:00",
28 | "type": "library",
29 | "extra": {
30 | "branch-alias": {
31 | "dev-master": "1.x-dev"
32 | }
33 | },
34 | "installation-source": "dist",
35 | "autoload": {
36 | "psr-4": {
37 | "Composer\\CaBundle\\": "src"
38 | }
39 | },
40 | "notification-url": "https://packagist.org/downloads/",
41 | "license": [
42 | "MIT"
43 | ],
44 | "authors": [
45 | {
46 | "name": "Jordi Boggiano",
47 | "email": "j.boggiano@seld.be",
48 | "homepage": "http://seld.be"
49 | }
50 | ],
51 | "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
52 | "keywords": [
53 | "cabundle",
54 | "cacert",
55 | "certificate",
56 | "ssl",
57 | "tls"
58 | ]
59 | },
60 | {
61 | "name": "ua-parser/uap-php",
62 | "version": "v3.9.7",
63 | "version_normalized": "3.9.7.0",
64 | "source": {
65 | "type": "git",
66 | "url": "https://github.com/ua-parser/uap-php.git",
67 | "reference": "7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a"
68 | },
69 | "dist": {
70 | "type": "zip",
71 | "url": "https://api.github.com/repos/ua-parser/uap-php/zipball/7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a",
72 | "reference": "7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a",
73 | "shasum": ""
74 | },
75 | "require": {
76 | "composer/ca-bundle": "^1.1",
77 | "php": ">=5.3.0"
78 | },
79 | "require-dev": {
80 | "phpunit/phpunit": "<8",
81 | "symfony/console": "^2.0 || ^3.0 || ^4.0",
82 | "symfony/filesystem": "^2.0 || ^3.0 || ^4.0",
83 | "symfony/finder": "^2.0 || ^3.0 || ^4.0",
84 | "symfony/yaml": "^2.0 || ^3.0 || ^4.0"
85 | },
86 | "suggest": {
87 | "symfony/console": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0",
88 | "symfony/filesystem": "Required for CLI usage - 2.0 || ^3.0 || ^4.0",
89 | "symfony/finder": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0",
90 | "symfony/yaml": "Required for CLI usage - ^4.0 || ^5.0"
91 | },
92 | "time": "2020-02-21T09:54:14+00:00",
93 | "bin": [
94 | "bin/uaparser"
95 | ],
96 | "type": "library",
97 | "installation-source": "dist",
98 | "autoload": {
99 | "psr-4": {
100 | "UAParser\\": "src"
101 | }
102 | },
103 | "notification-url": "https://packagist.org/downloads/",
104 | "license": [
105 | "MIT"
106 | ],
107 | "authors": [
108 | {
109 | "name": "Dave Olsen",
110 | "email": "dmolsen@gmail.com"
111 | },
112 | {
113 | "name": "Lars Strojny",
114 | "email": "lars@strojny.net"
115 | }
116 | ],
117 | "description": "A multi-language port of Browserscope's user agent parser."
118 | }
119 | ]
120 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "1d5c899fd1cfa4469bbd76b2735efb15",
8 | "packages": [
9 | {
10 | "name": "composer/ca-bundle",
11 | "version": "1.2.6",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/composer/ca-bundle.git",
15 | "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/composer/ca-bundle/zipball/47fe531de31fca4a1b997f87308e7d7804348f7e",
20 | "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "ext-openssl": "*",
25 | "ext-pcre": "*",
26 | "php": "^5.3.2 || ^7.0 || ^8.0"
27 | },
28 | "require-dev": {
29 | "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
30 | "psr/log": "^1.0",
31 | "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0"
32 | },
33 | "type": "library",
34 | "extra": {
35 | "branch-alias": {
36 | "dev-master": "1.x-dev"
37 | }
38 | },
39 | "autoload": {
40 | "psr-4": {
41 | "Composer\\CaBundle\\": "src"
42 | }
43 | },
44 | "notification-url": "https://packagist.org/downloads/",
45 | "license": [
46 | "MIT"
47 | ],
48 | "authors": [
49 | {
50 | "name": "Jordi Boggiano",
51 | "email": "j.boggiano@seld.be",
52 | "homepage": "http://seld.be"
53 | }
54 | ],
55 | "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
56 | "keywords": [
57 | "cabundle",
58 | "cacert",
59 | "certificate",
60 | "ssl",
61 | "tls"
62 | ],
63 | "time": "2020-01-13T10:02:55+00:00"
64 | },
65 | {
66 | "name": "ua-parser/uap-php",
67 | "version": "v3.9.7",
68 | "source": {
69 | "type": "git",
70 | "url": "https://github.com/ua-parser/uap-php.git",
71 | "reference": "7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a"
72 | },
73 | "dist": {
74 | "type": "zip",
75 | "url": "https://api.github.com/repos/ua-parser/uap-php/zipball/7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a",
76 | "reference": "7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a",
77 | "shasum": ""
78 | },
79 | "require": {
80 | "composer/ca-bundle": "^1.1",
81 | "php": ">=5.3.0"
82 | },
83 | "require-dev": {
84 | "phpunit/phpunit": "<8",
85 | "symfony/console": "^2.0 || ^3.0 || ^4.0",
86 | "symfony/filesystem": "^2.0 || ^3.0 || ^4.0",
87 | "symfony/finder": "^2.0 || ^3.0 || ^4.0",
88 | "symfony/yaml": "^2.0 || ^3.0 || ^4.0"
89 | },
90 | "suggest": {
91 | "symfony/console": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0",
92 | "symfony/filesystem": "Required for CLI usage - 2.0 || ^3.0 || ^4.0",
93 | "symfony/finder": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0",
94 | "symfony/yaml": "Required for CLI usage - ^4.0 || ^5.0"
95 | },
96 | "bin": [
97 | "bin/uaparser"
98 | ],
99 | "type": "library",
100 | "autoload": {
101 | "psr-4": {
102 | "UAParser\\": "src"
103 | }
104 | },
105 | "notification-url": "https://packagist.org/downloads/",
106 | "license": [
107 | "MIT"
108 | ],
109 | "authors": [
110 | {
111 | "name": "Dave Olsen",
112 | "email": "dmolsen@gmail.com"
113 | },
114 | {
115 | "name": "Lars Strojny",
116 | "email": "lars@strojny.net"
117 | }
118 | ],
119 | "description": "A multi-language port of Browserscope's user agent parser.",
120 | "time": "2020-02-21T09:54:14+00:00"
121 | }
122 | ],
123 | "packages-dev": [],
124 | "aliases": [],
125 | "minimum-stability": "stable",
126 | "stability-flags": [],
127 | "prefer-stable": false,
128 | "prefer-lowest": false,
129 | "platform": [],
130 | "platform-dev": [],
131 | "plugin-api-version": "1.1.0"
132 | }
133 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/README.md:
--------------------------------------------------------------------------------
1 | # ua-parser PHP Library #
2 |
3 | [](https://gitter.im/ua-parser/uap-php?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://travis-ci.org/ua-parser/uap-php) [](http://isitmaintained.com/project/ua-parser/uap-php "Average time to resolve an issue") [](http://isitmaintained.com/project/ua-parser/uap-php "Percentage of issues still open")
4 | [](https://packagist.org/packages/ua-parser/uap-php)
5 | [](https://packagist.org/packages/ua-parser/uap-php)
6 | [](https://packagist.org/packages/ua-parser/uap-php)
7 |
8 | This is the PHP library for the [uap-core](https://github.com/ua-parser/uap-core) project.
9 |
10 | ## Installation ##
11 | Add `ua-parser/uap-php` to the require section of your `composer.json` file and run `composer update`.
12 |
13 | ## Usage ##
14 |
15 | Straightforward:
16 |
17 | ```php
18 | require_once 'vendor/autoload.php';
19 | use UAParser\Parser;
20 |
21 | $ua = "Mozilla/5.0 (Macintosh; Intel Ma...";
22 |
23 | $parser = Parser::create();
24 | $result = $parser->parse($ua);
25 |
26 | print $result->ua->family; // Safari
27 | print $result->ua->major; // 6
28 | print $result->ua->minor; // 0
29 | print $result->ua->patch; // 2
30 | print $result->ua->toString(); // Safari 6.0.2
31 | print $result->ua->toVersion(); // 6.0.2
32 |
33 | print $result->os->family; // Mac OS X
34 | print $result->os->major; // 10
35 | print $result->os->minor; // 7
36 | print $result->os->patch; // 5
37 | print $result->os->patchMinor; // [null]
38 | print $result->os->toString(); // Mac OS X 10.7.5
39 | print $result->os->toVersion(); // 10.7.5
40 |
41 | print $result->device->family; // Other
42 |
43 | print $result->toString(); // Safari 6.0.2/Mac OS X 10.7.5
44 | print $result->originalUserAgent; // Mozilla/5.0 (Macintosh; Intel Ma...
45 | ```
46 |
47 | ## Using Your Own Custom regexes.php File ##
48 |
49 | You can use your own `regexes.php` file if you've customized the official file. I *strongly* encourage you to push back any changes you may have so others can benefit. That said, to use your own do the following:
50 |
51 | ```php
52 | require_once 'vendor/autoload.php';
53 | use UAParser\Parser;
54 |
55 | $parser = Parser::create("path/to/custom/regexes.php");
56 | ```
57 |
58 | ## Using ua-parser PHP Library from the Command Line ##
59 |
60 | A command line utility is now included with the PHP library. The following commands are supported:
61 |
62 | ### Get Usage Info
63 |
64 | Provides simple usage information:
65 |
66 | php bin/uaparser
67 |
68 | ### Update the regexes.php File
69 |
70 | Fetches an updated YAML file for `ua-parser` and overwrites the current regexes.php file. You can use the following as part of a cron job that runs nightly.
71 |
72 | php bin/uaparser ua-parser:update [--no-backup]
73 |
74 | By default creates a backup file. Use `--no-backup` to turn that feature off.
75 |
76 | ### Convert an Existing regexes.yaml File to regexes.php
77 |
78 | With the change to v2.0 you may have an existing and customized YAML file for `ua-parser`. Use the following to convert it to JSON.
79 |
80 | php bin/uaparser ua-parser:convert [file]
81 |
82 | ### Grab Just the Latest regexes.yaml File From the Repository
83 |
84 | If you need to add a new UA it's easier to edit the original YAML and then convert it to JSON.
85 |
86 | php bin/uaparser ua-parser:fetch [file]
87 |
88 | Fetches an updated YAML file. *Warning:* This method overwrites any existing `regexes.yaml` file.
89 |
90 | ### Parse a Single User Agent String
91 |
92 | Parses a user agent string and dumps the results as a list.
93 |
94 | php bin/uaparser ua-parser:parse "your user agent string"
95 |
96 | ### Parse a Webserver Log File
97 |
98 | Parses the supplied log file or log directory to test ua-parser. Saves the UA to a file when the UA or OS family aren't recognized or when the UA is listed as a generic smartphone or as a generic feature phone.
99 |
100 | php bin/uaparser ua-parser:logfile [-f /path/to/logfile] [-d /path/to/logdir] [--include "*.gz"] [--exclude "*.gz"] errors.log
101 |
102 | Multiple `--include` and `--exclude` parameters are allowed.
103 |
104 | ## Credits ##
105 |
106 | Thanks to the [original ua-parser team](http://code.google.com/p/ua-parser/people/list) for making the YAML file available for others to build upon.
107 |
108 | Also, many thanks to the following major contributors to the PHP library:
109 |
110 | * Bryan Shelton
111 | * Michael Bond
112 | * @rjd22
113 | * Timo Tijhof
114 | * Marcus Bointon
115 | * Ryan Parman
116 | * Pravin Dahal
117 |
118 | ## Licensing ##
119 | * The library is licensed under the MIT license
120 | * The user agents data from the ua-parser project is licensed under the Apache license
121 | * The initial list of generic feature phones & smartphones came from Mobile Web OSP under the MIT license
122 | * The initial list of spiders was taken from Yiibu's profile project under the MIT license.
123 |
124 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/src/Command/LogfileCommand.php:
--------------------------------------------------------------------------------
1 | setName('ua-parser:log')
31 | ->setDescription('Parses the supplied webserver log file.')
32 | ->addArgument(
33 | 'output',
34 | InputArgument::REQUIRED,
35 | 'Path to output log file'
36 | )
37 | ->addOption(
38 | 'log-file',
39 | 'f',
40 | InputOption::VALUE_REQUIRED,
41 | 'Path to a webserver log file'
42 | )
43 | ->addOption(
44 | 'log-dir',
45 | 'd',
46 | InputOption::VALUE_REQUIRED,
47 | 'Path to webserver log directory'
48 | )
49 | ->addOption(
50 | 'include',
51 | 'i',
52 | InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
53 | 'Include glob expressions for log files in the log directory',
54 | array('*.log', '*.log*.gz', '*.log*.bz2')
55 | )
56 | ->addOption(
57 | 'exclude',
58 | 'e',
59 | InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
60 | 'Exclude glob expressions for log files in the log directory',
61 | array('*error*')
62 | )
63 | ;
64 | }
65 |
66 | protected function execute(InputInterface $input, OutputInterface $output)
67 | {
68 | if (!$input->getOption('log-file') && !$input->getOption('log-dir')) {
69 | throw InvalidArgumentException::oneOfCommandArguments('log-file', 'log-dir');
70 | }
71 |
72 | $parser = Parser::create();
73 | $undefinedClients = array();
74 | /** @var $file SplFileInfo */
75 | foreach ($this->getFiles($input) as $file) {
76 |
77 | $path = $this->getPath($file);
78 | $lines = file($path);
79 |
80 | if (empty($lines)) {
81 | $output->writeln(sprintf('Skipping empty file "%s"', $file->getPathname()));
82 | $output->writeln('');
83 | continue;
84 | }
85 |
86 | $firstLine = reset($lines);
87 |
88 | $reader = AbstractReader::factory($firstLine);
89 | if (!$reader) {
90 | $output->writeln(sprintf('Could not find reader for file "%s"', $file->getPathname()));
91 | $output->writeln('');
92 | continue;
93 | }
94 |
95 | $output->writeln('');
96 | $output->writeln(sprintf('Analyzing "%s"', $file->getPathname()));
97 |
98 | $count = 1;
99 | $totalCount = count($lines);
100 | foreach ($lines as $line) {
101 |
102 | try {
103 | $userAgentString = $reader->read($line);
104 | } catch (ReaderException $e) {
105 | $count = $this->outputProgress($output, 'E', $count, $totalCount);
106 | continue;
107 | }
108 |
109 | $client = $parser->parse($userAgentString);
110 |
111 | $result = $this->getResult($client);
112 | if ($result !== '.') {
113 | $undefinedClients[] = json_encode(
114 | array($client->toString(), $userAgentString),
115 | JSON_UNESCAPED_SLASHES
116 | );
117 | }
118 |
119 | $count = $this->outputProgress($output, $result, $count, $totalCount);
120 | }
121 | $this->outputProgress($output, '', $count - 1, $totalCount, true);
122 | $output->writeln('');
123 | }
124 |
125 | $undefinedClients = $this->filter($undefinedClients);
126 |
127 | $fs = new Filesystem();
128 | $fs->dumpFile($input->getArgument('output'), join(PHP_EOL, $undefinedClients));
129 | }
130 |
131 | private function outputProgress(OutputInterface $output, $result, $count, $totalCount, $end = false)
132 | {
133 | if (($count % 70) === 0 || $end) {
134 | $formatString = '%s %' . strlen($totalCount) . 'd / %-' . strlen($totalCount) . 'd (%3d%%)';
135 | $result = $end ? str_repeat(' ', 70 - ($count % 70)) : $result;
136 | $output->writeln(sprintf($formatString, $result, $count, $totalCount, $count / $totalCount * 100));
137 | } else {
138 | $output->write($result);
139 | }
140 |
141 | return $count + 1;
142 | }
143 |
144 | private function getResult(Client $client)
145 | {
146 | if ($client->device->family === 'Spider') {
147 | return '.';
148 | } elseif ($client->ua->family === 'Other') {
149 | return 'U';
150 | } elseif ($client->os->family === 'Other') {
151 | return 'O';
152 | } elseif ($client->device->family === 'Generic Smartphone') {
153 | return 'S';
154 | } elseif ($client->device->family === 'Generic Feature Phone') {
155 | return 'F';
156 | }
157 |
158 | return '.';
159 | }
160 |
161 | private function getFiles(InputInterface $input)
162 | {
163 | $finder = Finder::create();
164 |
165 | if ($input->getOption('log-file')) {
166 | $file = $input->getOption('log-file');
167 | $finder->append(Finder::create()->in(dirname($file))->name(basename($file)));
168 | }
169 |
170 | if ($input->getOption('log-dir')) {
171 | $dirFinder = Finder::create()
172 | ->in($input->getOption('log-dir'));
173 | array_map(array($dirFinder, 'name'), $input->getOption('include'));
174 | array_map(array($dirFinder, 'notName'), $input->getOption('exclude'));
175 |
176 | $finder->append($dirFinder);
177 | }
178 |
179 | return $finder;
180 | }
181 |
182 | private function filter(array $lines)
183 | {
184 | return array_values(array_unique($lines));
185 | }
186 |
187 | private function getPath(SplFileInfo $file)
188 | {
189 | switch ($file->getExtension()) {
190 | case 'gz':
191 | $path = 'compress.zlib://' . $file->getPathname();
192 | break;
193 |
194 | case 'bz2':
195 | $path = 'compress.bzip2://' . $file->getPathname();
196 | break;
197 |
198 | default:
199 | $path = $file->getPathname();
200 | break;
201 | }
202 |
203 | return $path;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/vendor/ua-parser/uap-php/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 3.4.2
4 | - Update uap-core
5 |
6 | ## 3.4.1
7 | - Fix a regex delimiter issue with uap-core
8 | - Bundle regex.php with uap-php
9 |
10 | ## 3.4.0
11 | - ADD: device Parsing with brand model and case insensitive testing
12 | - Use `peer_name` instead of `CN_match` for PHP >=5.6
13 | - Advertise Gitter chat for support requests
14 | - Include uap-core as a git submodule
15 |
16 | ## 3.3.1
17 | - PSR-4 ready
18 | - Self repository, less useless files
19 |
20 | ## 3.3.0
21 | - Use composer for dependency management
22 | - Introduce namespaces
23 | - Removing legacy library dependencies
24 | - Use PHPUnit for testing
25 | - Make all tests pass, fix all the remaining bugs
26 | - Introduce specific result objects
27 | - Comply with PSR-X coding standards:
28 | * `UAParser` class is now `UAParser\Parser`
29 | * Typed result objects: `Parser::parse()` returns `UAParser\Result\Client`, `Client::$os` is a `UAParser\Result\OperatingSystem` and `Client::$device` is a `UAParser\Result\Device`
30 | * `toString()` and `toVersion()` are now methods
31 | * Properties now use camelCase, not underscore_case.
32 | - Use Travis for CI
33 | - Update README
34 | - Port command line tool to Symfony CLI
35 | - Secure updating: SSL certificate verification, hashing, try to do atomic updates
36 | - Restore fetching YAML file only (without generating JSON)
37 |
38 | ## 2.1.1
39 | - FIX: making sure patch minor is being populated correctly when showing a mismatch
40 |
41 | ## 2.1.0
42 | - ADD: support for custom regexes.json files (via @pravindahal)
43 | - FIX: formerly private vars/functions are now protected (via @pravindahal)
44 | - FIX: command line tool gets 'pretty' option for PHP 5.4 users (via @skyzyx)
45 | - FIX: refactored the regexes.yaml test suite
46 | - FIX: now check to see if allow_url_fopen is set to 'On' before trying to download the YAML file from the command line
47 | - THX: thanks to @pravindahal and @skyzyx for the pull requests
48 |
49 | ## 2.0.1
50 | - FIX: renamed uaParser, osParser, & deviceParser to uaParse, osParse, & deviceParse to address a bug with uaParser being recognized as the contruct function for the overall lib
51 | - FIX: updated the test lib so that device failures are properly formatted
52 |
53 | ## 2.0.0
54 | - Summary:
55 | * the `UAParser` class is now dynamic
56 | * properties are nested _(e.g. $result->family is now $result->ua->family)_
57 | * a user agent string is now required when using `parse()`. the auto-magical "use the server provided UA" is no longer supported.
58 | * `uaParse()`, `osParse()`, and `deviceParse()` are public and can be used to just return those select bits for a given user agent string.
59 | * the `is*` boolean properties _(e.g. isMobile)_ have been dropped. they now exist as part of the `ua-classifier` project.
60 | - ADD: toString() converts the version bits and family into a simple string
61 | - ADD: toVersionString() converts the version bits into a simple string
62 | - ADD: toFullString() combines the UA and OS family and version bits
63 | - ADD: "convert" flag for uaparser-cli.php
64 | - ADD: "pull & save just regexes.yaml" flag for uaparser-cli.php
65 | - FIX: library is now a dynamic class
66 | - FIX: attributes are now nested & populated like the other ua-parser libraries (e.g. $result->family is now $result->ua->family)
67 | - FIX: uaParser(), osParser(), and deviceParser() are now public functions
68 | - FIX: saves regexes.yaml as JSON for better performance
69 | - FIX: removed the __DIR__ "fix"
70 | - FIX: Apache log parsing now returns results when UA or OS families are set to "Other" and the device is listed as a smartphone or generic feature phone
71 | - FIX: all tabs are now spaces
72 | - FIX: a UA is now run against all three parsers
73 | - FIX: renamed $debug var to $log to better reflect what it does
74 | - DEL: is* boolean attributes (e.g. isMobile) have been removed
75 | - DEL: will no longer auto-parse $_SERVER['HTTP_USER_AGENT'] if available
76 | - DEL: tests no longer run against pgts_browser_list.yaml
77 | - THX: thanks to @rjd22 for the dynamic class code/fix
78 |
79 | ## 1.5.0
80 | - ADD: command line interface is now in its own file (via @Synchro)
81 | - ADD: command line utility now supports parsing an Apache log file & recording the results
82 | - ADD: command line utility can now parse a supplied user-agent string and push out a simple list or JSON
83 | - ADD: test suite that uses the ua-parser project's test resources
84 | - FIX: numerous comment & spacing fixes (via @Synchro & @Krinkle)
85 | - FIX: remove PHP4 version of spyc (via @Synchro)
86 | - FIX: remove .svn dirs in spyc (via @lopezdonaque)
87 | - FIX: notes that the PHP 5.2 fix really was for 5.1 (via @Synchro) (knew this, i was lazy)
88 | - FIX: lib now returns an object no matter what. now matches other ua-parser libs (via @Krinkle)
89 | - FIX: checks that $_SERVER attr is set before including it. should be better for command line use.
90 | - FIX: family attr now properly set in an edge case
91 | - FIX: if regexes.yaml picks up bad slashes the PHP lib will account for it (e.g. GoogleTV regex)
92 | - THX: thanks to @Krinkle and @Synchro for the numerous fixes
93 |
94 | ## 1.4.5
95 | - FIX: an embarrassing debug print survived the last edit
96 | - THX: thanks to @memakeit for dropping the bug report
97 |
98 | ## 1.4.4
99 | - FIX: made sure that the regex file is only loaded once if running the library multiple times. performance boost.
100 | - FIX: added support for identifying various game devices as mobile devices
101 | - THX: thanks to @rjd22 for pointing out the perf issue
102 |
103 | ## 1.4.3
104 | - FIX: added support for patch & family attributes to sort of match the other libraries
105 |
106 | ## 1.4.2
107 | - FIX: notice if regexes.yaml is missing parens (e.g. match $1) for device & os names
108 |
109 | ## 1.4.1
110 | - FIX: notice when using UAParser from the command line
111 |
112 | ## 1.4.0
113 | - ADD: silent mode for the UA::get() method
114 | - ADD: nobackup mode for the UA::get() method
115 | - ADD: example of how to do a redirect with ua-parser-php
116 | - The following were changes to regexes.yaml:
117 | * ADD: support for Google Earth browser
118 | * ADD: another regex for Firefox Mobile
119 | * ADD: support for Firefox Alpha builds
120 | * ADD: support for Sogou Explorer
121 | * ADD: support for the Raven for Mac browser
122 | * ADD: support for WebKit Nightly builds (though slightly pointless)
123 | * FIX: better pattern matching for the Pale Moon browser
124 |
125 | ## 1.3.2
126 | - FIX: addressed false "tablet" classification for opera mobile & mini on android
127 | - The following were changes to regexes.yaml:
128 | * ADD: support for Tizen Browser (aka SLP Browser) from Samsung
129 | * FIX: support for a new look Polaris 8.0 user agent string
130 | * FIX: modified where the Epiphany Browser check happens
131 |
132 | ## 1.3.1
133 | - FIX: now doing some sanity cleaning on the user agent strings
134 | - FIX: added a smarter default if the user agent isn't recognized at all
135 |
136 | ## 1.3.0
137 | - FIX: now points to Tobie's ua-parser project for the latest greatest YAML file
138 | - FIX: YAML file is now standardized as regexes.yaml instead of user_agents_regex.yaml
139 | - FIX: minor NOTICE issues resolved for very select UAs
140 |
141 | ## 1.2.2
142 | - The following were changes to user_agents_regex.yaml:
143 | * ADD: support for UC Browser
144 |
145 | ## 1.2.1
146 | - The following were changes to user_agents_regex.yaml:
147 | * ADD: support for android 4 user agents that have a dash in them
148 |
149 | ## 1.2.0
150 | - FIX: should be compatible with PHP 5.2
151 | - FIX: addressed STRICT mode errors
152 | - FIX: addressed NOTICE for a missing variable
153 | - FIX: if isTablet is set to true then isMobile is set to false (mobile to me means phone)
154 | - THX: Thanks to Mike Bond of WVU Libraries for pointing out the 5.2 incompatibility
155 |
156 | ## 1.1.0
157 | - FIX: a number of fixes from bryan shelton
158 | - The following were changes to user_agents_regex.yaml:
159 | * ADD: support for Chrome Mobile
160 |
161 | ## 1.0.0
162 | - just because i don't expect to update this anytime soon and ppl report it's working
163 |
164 | ## 0.3.1
165 | - FIX: swapped nil for null in parse()
166 | - FIX: smarter/saner defaults
167 | - FIX: now using isset() for family_replacement
168 | - THX: thanks to bryan shelton for these fixes
169 |
170 | ## 0.3.0
171 | - ADD: can now supply a specific UA to be checked
172 | - ADD: if the UA contains 'tablet' isTablet is marked true
173 | - ADD: for certain mobile OSs they report a desktop browser. marking them mobile now.
174 | - FIX: tablet listing should now be better
175 | - FIX: the list of mobile browsers was updated
176 | - FIX: made sure that certain checks won't fail as "false" if a version number was a 0
177 | - FIX: for the device check, if it returns spider as a result it no longer marks it as mobile
178 | - FIX: added more mobile browsers to that specific check
179 | - The following were changes to user_agents_regex.yaml:
180 | * ADD: symphony, minimo, teleca, semc, up.browser, bunjaloo, jasmine, & brew browsers supported
181 | * ADD: windows mobile 6.5 os support
182 | * ADD: amoi, asus, bird, dell, docomo, huawei, i-mate, kyocera, lenovo, lg, microsoft kind,
183 | motorola, philips, samsung, softbank, & sony ericsson device checks
184 | * FIX: mobile firefox, opera mobile & mini, obigo, polaris, nokiabrowser, ie mobile,
185 | android, & mobile safari browser checks
186 | * FIX: iOS support
187 | * FIX: htc, android, palm/hp, kindle, ios, generic feature phones & spider device checks
188 |
189 | ## 0.2.0
190 | - ADD: added isMobile support
191 | - ADD: added isTablet support
192 | - ADD: added isComputer support
193 | - ADD: added isSpider support
194 |
195 | ## 0.1.0
196 | - The following were changes to user_agents_regex.yaml:
197 | * expanded support for Symbia & Nokia Devices,
198 | * cleaned up some slashies,
199 | * added Mobile Safari as the family replacement for iOS devices,
200 | * better support for longer HTC device names
201 | * added feature phones to the device check
202 | * added generic smartphones to the device check
203 | * added AvantGo to the ua check
204 | * tweaked a lot of the nokia checks
205 | * added kindle support to the device section
206 | * added a generic catch for android devices.
207 | * added support for blackberry devices
208 | * changed the blackberry family to 'blackberry webkit' when it's a webkit browser
209 |
--------------------------------------------------------------------------------
/vendor/composer/ClassLoader.php:
--------------------------------------------------------------------------------
1 |
7 | * Jordi Boggiano
8 | *
9 | * For the full copyright and license information, please view the LICENSE
10 | * file that was distributed with this source code.
11 | */
12 |
13 | namespace Composer\Autoload;
14 |
15 | /**
16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17 | *
18 | * $loader = new \Composer\Autoload\ClassLoader();
19 | *
20 | * // register classes with namespaces
21 | * $loader->add('Symfony\Component', __DIR__.'/component');
22 | * $loader->add('Symfony', __DIR__.'/framework');
23 | *
24 | * // activate the autoloader
25 | * $loader->register();
26 | *
27 | * // to enable searching the include path (eg. for PEAR packages)
28 | * $loader->setUseIncludePath(true);
29 | *
30 | * In this example, if you try to use a class in the Symfony\Component
31 | * namespace or one of its children (Symfony\Component\Console for instance),
32 | * the autoloader will first look for the class under the component/
33 | * directory, and it will then fallback to the framework/ directory if not
34 | * found before giving up.
35 | *
36 | * This class is loosely based on the Symfony UniversalClassLoader.
37 | *
38 | * @author Fabien Potencier
39 | * @author Jordi Boggiano
40 | * @see http://www.php-fig.org/psr/psr-0/
41 | * @see http://www.php-fig.org/psr/psr-4/
42 | */
43 | class ClassLoader
44 | {
45 | // PSR-4
46 | private $prefixLengthsPsr4 = array();
47 | private $prefixDirsPsr4 = array();
48 | private $fallbackDirsPsr4 = array();
49 |
50 | // PSR-0
51 | private $prefixesPsr0 = array();
52 | private $fallbackDirsPsr0 = array();
53 |
54 | private $useIncludePath = false;
55 | private $classMap = array();
56 | private $classMapAuthoritative = false;
57 | private $missingClasses = array();
58 | private $apcuPrefix;
59 |
60 | public function getPrefixes()
61 | {
62 | if (!empty($this->prefixesPsr0)) {
63 | return call_user_func_array('array_merge', $this->prefixesPsr0);
64 | }
65 |
66 | return array();
67 | }
68 |
69 | public function getPrefixesPsr4()
70 | {
71 | return $this->prefixDirsPsr4;
72 | }
73 |
74 | public function getFallbackDirs()
75 | {
76 | return $this->fallbackDirsPsr0;
77 | }
78 |
79 | public function getFallbackDirsPsr4()
80 | {
81 | return $this->fallbackDirsPsr4;
82 | }
83 |
84 | public function getClassMap()
85 | {
86 | return $this->classMap;
87 | }
88 |
89 | /**
90 | * @param array $classMap Class to filename map
91 | */
92 | public function addClassMap(array $classMap)
93 | {
94 | if ($this->classMap) {
95 | $this->classMap = array_merge($this->classMap, $classMap);
96 | } else {
97 | $this->classMap = $classMap;
98 | }
99 | }
100 |
101 | /**
102 | * Registers a set of PSR-0 directories for a given prefix, either
103 | * appending or prepending to the ones previously set for this prefix.
104 | *
105 | * @param string $prefix The prefix
106 | * @param array|string $paths The PSR-0 root directories
107 | * @param bool $prepend Whether to prepend the directories
108 | */
109 | public function add($prefix, $paths, $prepend = false)
110 | {
111 | if (!$prefix) {
112 | if ($prepend) {
113 | $this->fallbackDirsPsr0 = array_merge(
114 | (array) $paths,
115 | $this->fallbackDirsPsr0
116 | );
117 | } else {
118 | $this->fallbackDirsPsr0 = array_merge(
119 | $this->fallbackDirsPsr0,
120 | (array) $paths
121 | );
122 | }
123 |
124 | return;
125 | }
126 |
127 | $first = $prefix[0];
128 | if (!isset($this->prefixesPsr0[$first][$prefix])) {
129 | $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130 |
131 | return;
132 | }
133 | if ($prepend) {
134 | $this->prefixesPsr0[$first][$prefix] = array_merge(
135 | (array) $paths,
136 | $this->prefixesPsr0[$first][$prefix]
137 | );
138 | } else {
139 | $this->prefixesPsr0[$first][$prefix] = array_merge(
140 | $this->prefixesPsr0[$first][$prefix],
141 | (array) $paths
142 | );
143 | }
144 | }
145 |
146 | /**
147 | * Registers a set of PSR-4 directories for a given namespace, either
148 | * appending or prepending to the ones previously set for this namespace.
149 | *
150 | * @param string $prefix The prefix/namespace, with trailing '\\'
151 | * @param array|string $paths The PSR-4 base directories
152 | * @param bool $prepend Whether to prepend the directories
153 | *
154 | * @throws \InvalidArgumentException
155 | */
156 | public function addPsr4($prefix, $paths, $prepend = false)
157 | {
158 | if (!$prefix) {
159 | // Register directories for the root namespace.
160 | if ($prepend) {
161 | $this->fallbackDirsPsr4 = array_merge(
162 | (array) $paths,
163 | $this->fallbackDirsPsr4
164 | );
165 | } else {
166 | $this->fallbackDirsPsr4 = array_merge(
167 | $this->fallbackDirsPsr4,
168 | (array) $paths
169 | );
170 | }
171 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172 | // Register directories for a new namespace.
173 | $length = strlen($prefix);
174 | if ('\\' !== $prefix[$length - 1]) {
175 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176 | }
177 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
179 | } elseif ($prepend) {
180 | // Prepend directories for an already registered namespace.
181 | $this->prefixDirsPsr4[$prefix] = array_merge(
182 | (array) $paths,
183 | $this->prefixDirsPsr4[$prefix]
184 | );
185 | } else {
186 | // Append directories for an already registered namespace.
187 | $this->prefixDirsPsr4[$prefix] = array_merge(
188 | $this->prefixDirsPsr4[$prefix],
189 | (array) $paths
190 | );
191 | }
192 | }
193 |
194 | /**
195 | * Registers a set of PSR-0 directories for a given prefix,
196 | * replacing any others previously set for this prefix.
197 | *
198 | * @param string $prefix The prefix
199 | * @param array|string $paths The PSR-0 base directories
200 | */
201 | public function set($prefix, $paths)
202 | {
203 | if (!$prefix) {
204 | $this->fallbackDirsPsr0 = (array) $paths;
205 | } else {
206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207 | }
208 | }
209 |
210 | /**
211 | * Registers a set of PSR-4 directories for a given namespace,
212 | * replacing any others previously set for this namespace.
213 | *
214 | * @param string $prefix The prefix/namespace, with trailing '\\'
215 | * @param array|string $paths The PSR-4 base directories
216 | *
217 | * @throws \InvalidArgumentException
218 | */
219 | public function setPsr4($prefix, $paths)
220 | {
221 | if (!$prefix) {
222 | $this->fallbackDirsPsr4 = (array) $paths;
223 | } else {
224 | $length = strlen($prefix);
225 | if ('\\' !== $prefix[$length - 1]) {
226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227 | }
228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
230 | }
231 | }
232 |
233 | /**
234 | * Turns on searching the include path for class files.
235 | *
236 | * @param bool $useIncludePath
237 | */
238 | public function setUseIncludePath($useIncludePath)
239 | {
240 | $this->useIncludePath = $useIncludePath;
241 | }
242 |
243 | /**
244 | * Can be used to check if the autoloader uses the include path to check
245 | * for classes.
246 | *
247 | * @return bool
248 | */
249 | public function getUseIncludePath()
250 | {
251 | return $this->useIncludePath;
252 | }
253 |
254 | /**
255 | * Turns off searching the prefix and fallback directories for classes
256 | * that have not been registered with the class map.
257 | *
258 | * @param bool $classMapAuthoritative
259 | */
260 | public function setClassMapAuthoritative($classMapAuthoritative)
261 | {
262 | $this->classMapAuthoritative = $classMapAuthoritative;
263 | }
264 |
265 | /**
266 | * Should class lookup fail if not found in the current class map?
267 | *
268 | * @return bool
269 | */
270 | public function isClassMapAuthoritative()
271 | {
272 | return $this->classMapAuthoritative;
273 | }
274 |
275 | /**
276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277 | *
278 | * @param string|null $apcuPrefix
279 | */
280 | public function setApcuPrefix($apcuPrefix)
281 | {
282 | $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283 | }
284 |
285 | /**
286 | * The APCu prefix in use, or null if APCu caching is not enabled.
287 | *
288 | * @return string|null
289 | */
290 | public function getApcuPrefix()
291 | {
292 | return $this->apcuPrefix;
293 | }
294 |
295 | /**
296 | * Registers this instance as an autoloader.
297 | *
298 | * @param bool $prepend Whether to prepend the autoloader or not
299 | */
300 | public function register($prepend = false)
301 | {
302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303 | }
304 |
305 | /**
306 | * Unregisters this instance as an autoloader.
307 | */
308 | public function unregister()
309 | {
310 | spl_autoload_unregister(array($this, 'loadClass'));
311 | }
312 |
313 | /**
314 | * Loads the given class or interface.
315 | *
316 | * @param string $class The name of the class
317 | * @return bool|null True if loaded, null otherwise
318 | */
319 | public function loadClass($class)
320 | {
321 | if ($file = $this->findFile($class)) {
322 | includeFile($file);
323 |
324 | return true;
325 | }
326 | }
327 |
328 | /**
329 | * Finds the path to the file where the class is defined.
330 | *
331 | * @param string $class The name of the class
332 | *
333 | * @return string|false The path if found, false otherwise
334 | */
335 | public function findFile($class)
336 | {
337 | // class map lookup
338 | if (isset($this->classMap[$class])) {
339 | return $this->classMap[$class];
340 | }
341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342 | return false;
343 | }
344 | if (null !== $this->apcuPrefix) {
345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346 | if ($hit) {
347 | return $file;
348 | }
349 | }
350 |
351 | $file = $this->findFileWithExtension($class, '.php');
352 |
353 | // Search for Hack files if we are running on HHVM
354 | if (false === $file && defined('HHVM_VERSION')) {
355 | $file = $this->findFileWithExtension($class, '.hh');
356 | }
357 |
358 | if (null !== $this->apcuPrefix) {
359 | apcu_add($this->apcuPrefix.$class, $file);
360 | }
361 |
362 | if (false === $file) {
363 | // Remember that this class does not exist.
364 | $this->missingClasses[$class] = true;
365 | }
366 |
367 | return $file;
368 | }
369 |
370 | private function findFileWithExtension($class, $ext)
371 | {
372 | // PSR-4 lookup
373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374 |
375 | $first = $class[0];
376 | if (isset($this->prefixLengthsPsr4[$first])) {
377 | $subPath = $class;
378 | while (false !== $lastPos = strrpos($subPath, '\\')) {
379 | $subPath = substr($subPath, 0, $lastPos);
380 | $search = $subPath . '\\';
381 | if (isset($this->prefixDirsPsr4[$search])) {
382 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383 | foreach ($this->prefixDirsPsr4[$search] as $dir) {
384 | if (file_exists($file = $dir . $pathEnd)) {
385 | return $file;
386 | }
387 | }
388 | }
389 | }
390 | }
391 |
392 | // PSR-4 fallback dirs
393 | foreach ($this->fallbackDirsPsr4 as $dir) {
394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395 | return $file;
396 | }
397 | }
398 |
399 | // PSR-0 lookup
400 | if (false !== $pos = strrpos($class, '\\')) {
401 | // namespaced class name
402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404 | } else {
405 | // PEAR-like class name
406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407 | }
408 |
409 | if (isset($this->prefixesPsr0[$first])) {
410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411 | if (0 === strpos($class, $prefix)) {
412 | foreach ($dirs as $dir) {
413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414 | return $file;
415 | }
416 | }
417 | }
418 | }
419 | }
420 |
421 | // PSR-0 fallback dirs
422 | foreach ($this->fallbackDirsPsr0 as $dir) {
423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424 | return $file;
425 | }
426 | }
427 |
428 | // PSR-0 include paths.
429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430 | return $file;
431 | }
432 |
433 | return false;
434 | }
435 | }
436 |
437 | /**
438 | * Scope isolated include.
439 | *
440 | * Prevents access to $this/self from included files.
441 | */
442 | function includeFile($file)
443 | {
444 | include $file;
445 | }
446 |
--------------------------------------------------------------------------------
/vendor/composer/ca-bundle/src/CaBundle.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view
9 | * the LICENSE file that was distributed with this source code.
10 | */
11 |
12 | namespace Composer\CaBundle;
13 |
14 | use Psr\Log\LoggerInterface;
15 | use Symfony\Component\Process\PhpProcess;
16 |
17 | /**
18 | * @author Chris Smith
19 | * @author Jordi Boggiano
20 | */
21 | class CaBundle
22 | {
23 | private static $caPath;
24 | private static $caFileValidity = array();
25 | private static $useOpensslParse;
26 |
27 | /**
28 | * Returns the system CA bundle path, or a path to the bundled one
29 | *
30 | * This method was adapted from Sslurp.
31 | * https://github.com/EvanDotPro/Sslurp
32 | *
33 | * (c) Evan Coury
34 | *
35 | * For the full copyright and license information, please see below:
36 | *
37 | * Copyright (c) 2013, Evan Coury
38 | * All rights reserved.
39 | *
40 | * Redistribution and use in source and binary forms, with or without modification,
41 | * are permitted provided that the following conditions are met:
42 | *
43 | * * Redistributions of source code must retain the above copyright notice,
44 | * this list of conditions and the following disclaimer.
45 | *
46 | * * Redistributions in binary form must reproduce the above copyright notice,
47 | * this list of conditions and the following disclaimer in the documentation
48 | * and/or other materials provided with the distribution.
49 | *
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
51 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
54 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
55 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
57 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 | *
61 | * @param LoggerInterface $logger optional logger for information about which CA files were loaded
62 | * @return string path to a CA bundle file or directory
63 | */
64 | public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
65 | {
66 | if (self::$caPath !== null) {
67 | return self::$caPath;
68 | }
69 | $caBundlePaths = array();
70 |
71 |
72 | // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
73 | // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
74 | $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
75 |
76 | // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
77 | // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
78 | $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
79 |
80 | $caBundlePaths[] = ini_get('openssl.cafile');
81 | $caBundlePaths[] = ini_get('openssl.capath');
82 |
83 | $otherLocations = array(
84 | '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
85 | '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
86 | '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
87 | '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
88 | '/usr/ssl/certs/ca-bundle.crt', // Cygwin
89 | '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
90 | '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
91 | '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
92 | '/etc/ssl/cert.pem', // OpenBSD
93 | '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
94 | '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
95 | '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package
96 | );
97 |
98 | foreach($otherLocations as $location) {
99 | $otherLocations[] = dirname($location);
100 | }
101 |
102 | $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
103 |
104 | foreach ($caBundlePaths as $caBundle) {
105 | if (self::caFileUsable($caBundle, $logger)) {
106 | return self::$caPath = $caBundle;
107 | }
108 |
109 | if (self::caDirUsable($caBundle)) {
110 | return self::$caPath = $caBundle;
111 | }
112 | }
113 |
114 | return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
115 | }
116 |
117 | /**
118 | * Returns the path to the bundled CA file
119 | *
120 | * In case you don't want to trust the user or the system, you can use this directly
121 | *
122 | * @return string path to a CA bundle file
123 | */
124 | public static function getBundledCaBundlePath()
125 | {
126 | $caBundleFile = __DIR__.'/../res/cacert.pem';
127 |
128 | // cURL does not understand 'phar://' paths
129 | // see https://github.com/composer/ca-bundle/issues/10
130 | if (0 === strpos($caBundleFile, 'phar://')) {
131 | file_put_contents(
132 | $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
133 | file_get_contents($caBundleFile)
134 | );
135 |
136 | register_shutdown_function(function() use ($tempCaBundleFile) {
137 | @unlink($tempCaBundleFile);
138 | });
139 |
140 | $caBundleFile = $tempCaBundleFile;
141 | }
142 |
143 | return $caBundleFile;
144 | }
145 |
146 | /**
147 | * Validates a CA file using opensl_x509_parse only if it is safe to use
148 | *
149 | * @param string $filename
150 | * @param LoggerInterface $logger optional logger for information about which CA files were loaded
151 | *
152 | * @return bool
153 | */
154 | public static function validateCaFile($filename, LoggerInterface $logger = null)
155 | {
156 | static $warned = false;
157 |
158 | if (isset(self::$caFileValidity[$filename])) {
159 | return self::$caFileValidity[$filename];
160 | }
161 |
162 | $contents = file_get_contents($filename);
163 |
164 | // assume the CA is valid if php is vulnerable to
165 | // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
166 | if (!static::isOpensslParseSafe()) {
167 | if (!$warned && $logger) {
168 | $logger->warning(sprintf(
169 | 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
170 | PHP_VERSION
171 | ));
172 | $warned = true;
173 | }
174 |
175 | $isValid = !empty($contents);
176 | } else {
177 | $isValid = (bool) openssl_x509_parse($contents);
178 | }
179 |
180 | if ($logger) {
181 | $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
182 | }
183 |
184 | return self::$caFileValidity[$filename] = $isValid;
185 | }
186 |
187 | /**
188 | * Test if it is safe to use the PHP function openssl_x509_parse().
189 | *
190 | * This checks if OpenSSL extensions is vulnerable to remote code execution
191 | * via the exploit documented as CVE-2013-6420.
192 | *
193 | * @return bool
194 | */
195 | public static function isOpensslParseSafe()
196 | {
197 | if (null !== self::$useOpensslParse) {
198 | return self::$useOpensslParse;
199 | }
200 |
201 | if (PHP_VERSION_ID >= 50600) {
202 | return self::$useOpensslParse = true;
203 | }
204 |
205 | // Vulnerable:
206 | // PHP 5.3.0 - PHP 5.3.27
207 | // PHP 5.4.0 - PHP 5.4.22
208 | // PHP 5.5.0 - PHP 5.5.6
209 | if (
210 | (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
211 | || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
212 | || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
213 | ) {
214 | // This version of PHP has the fix for CVE-2013-6420 applied.
215 | return self::$useOpensslParse = true;
216 | }
217 |
218 | if (defined('PHP_WINDOWS_VERSION_BUILD')) {
219 | // Windows is probably insecure in this case.
220 | return self::$useOpensslParse = false;
221 | }
222 |
223 | $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
224 | $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
225 |
226 | if (preg_match($regex, PHP_VERSION, $m)) {
227 | return ((int) $m[1]) >= $fixedVersion;
228 | }
229 |
230 | return false;
231 | };
232 |
233 | // Hard coded list of PHP distributions with the fix backported.
234 | if (
235 | $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
236 | || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
237 | || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
238 | ) {
239 | return self::$useOpensslParse = true;
240 | }
241 |
242 | // Symfony Process component is missing so we assume it is unsafe at this point
243 | if (!class_exists('Symfony\Component\Process\PhpProcess')) {
244 | return self::$useOpensslParse = false;
245 | }
246 |
247 | // This is where things get crazy, because distros backport security
248 | // fixes the chances are on NIX systems the fix has been applied but
249 | // it's not possible to verify that from the PHP version.
250 | //
251 | // To verify exec a new PHP process and run the issue testcase with
252 | // known safe input that replicates the bug.
253 |
254 | // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
255 | // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
256 | $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
257 | $script = <<<'EOT'
258 |
259 | error_reporting(-1);
260 | $info = openssl_x509_parse(base64_decode('%s'));
261 | var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
262 |
263 | EOT;
264 | $script = '<'."?php\n".sprintf($script, $cert);
265 |
266 | try {
267 | $process = new PhpProcess($script);
268 | $process->mustRun();
269 | } catch (\Exception $e) {
270 | // In the case of any exceptions just accept it is not possible to
271 | // determine the safety of openssl_x509_parse and bail out.
272 | return self::$useOpensslParse = false;
273 | }
274 |
275 | $output = preg_split('{\r?\n}', trim($process->getOutput()));
276 | $errorOutput = trim($process->getErrorOutput());
277 |
278 | if (
279 | count($output) === 3
280 | && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
281 | && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
282 | && $output[2] === 'int(-1)'
283 | && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
284 | ) {
285 | // This PHP has the fix backported probably by a distro security team.
286 | return self::$useOpensslParse = true;
287 | }
288 |
289 | return self::$useOpensslParse = false;
290 | }
291 |
292 | /**
293 | * Resets the static caches
294 | */
295 | public static function reset()
296 | {
297 | self::$caFileValidity = array();
298 | self::$caPath = null;
299 | self::$useOpensslParse = null;
300 | }
301 |
302 | private static function getEnvVariable($name)
303 | {
304 | if (isset($_SERVER[$name])) {
305 | return (string) $_SERVER[$name];
306 | }
307 |
308 | if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
309 | return (string) $value;
310 | }
311 |
312 | return false;
313 | }
314 |
315 | private static function caFileUsable($certFile, LoggerInterface $logger = null)
316 | {
317 | return $certFile && @is_file($certFile) && @is_readable($certFile) && static::validateCaFile($certFile, $logger);
318 | }
319 |
320 | private static function caDirUsable($certDir)
321 | {
322 | return $certDir && @is_dir($certDir) && @is_readable($certDir) && glob($certDir . '/*');
323 | }
324 | }
325 |
--------------------------------------------------------------------------------