Version Description
- Improved: Some issues in php v5.4
Download this release
Release Info
Developer | mostafa.s1990 |
Plugin | WP Statistics |
Version | 12.5.2 |
Comparing to | |
See all releases |
Code changes from version 12.5.1 to 12.5.2
- composer.json +1 -0
- includes/classes/class-wp-statistics-admin-pages.php +2 -2
- includes/classes/class-wp-statistics-admin.php +2 -2
- includes/classes/class-wp-statistics-rest.php +1 -1
- includes/classes/class-wp-statistics-tinymce.php +15 -17
- includes/vendor/autoload.php +7 -7
- includes/vendor/composer/LICENSE +21 -21
- includes/vendor/composer/autoload_classmap.php +9 -9
- includes/vendor/composer/autoload_namespaces.php +10 -10
- includes/vendor/composer/autoload_psr4.php +18 -18
- includes/vendor/composer/autoload_real.php +52 -52
- includes/vendor/composer/autoload_static.php +101 -101
- includes/vendor/composer/ca-bundle/LICENSE +19 -19
- includes/vendor/composer/ca-bundle/README.md +85 -85
- includes/vendor/composer/ca-bundle/composer.json +54 -54
- includes/vendor/composer/ca-bundle/src/CaBundle.php +308 -308
- includes/vendor/composer/installed.json +481 -481
- includes/vendor/erusev/parsedown/LICENSE.txt +20 -20
- includes/vendor/erusev/parsedown/Parsedown.php +1679 -1679
- includes/vendor/erusev/parsedown/README.md +86 -86
- includes/vendor/erusev/parsedown/composer.json +33 -33
- includes/vendor/geoip2/geoip2/.gitmodules +3 -3
- includes/vendor/geoip2/geoip2/.php_cs +35 -35
- includes/vendor/geoip2/geoip2/CHANGELOG.md +262 -262
- includes/vendor/geoip2/geoip2/LICENSE +202 -202
- includes/vendor/geoip2/geoip2/README.md +401 -401
- includes/vendor/geoip2/geoip2/composer.json +30 -30
- includes/vendor/geoip2/geoip2/src/Database/Reader.php +283 -283
- includes/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php +10 -10
- includes/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php +10 -10
- includes/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php +10 -10
- includes/vendor/geoip2/geoip2/src/Exception/HttpException.php +24 -24
- includes/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php +26 -26
- includes/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php +10 -10
- includes/vendor/geoip2/geoip2/src/Model/AbstractModel.php +67 -67
- includes/vendor/geoip2/geoip2/src/Model/AnonymousIp.php +46 -46
- includes/vendor/geoip2/geoip2/src/Model/Asn.php +35 -35
- includes/vendor/geoip2/geoip2/src/Model/City.php +133 -133
- includes/vendor/geoip2/geoip2/src/Model/ConnectionType.php +31 -31
- includes/vendor/geoip2/geoip2/src/Model/Country.php +71 -71
- includes/vendor/geoip2/geoip2/src/Model/Domain.php +31 -31
- includes/vendor/geoip2/geoip2/src/Model/Enterprise.php +47 -47
- includes/vendor/geoip2/geoip2/src/Model/Insights.php +47 -47
- includes/vendor/geoip2/geoip2/src/Model/Isp.php +44 -44
- includes/vendor/geoip2/geoip2/src/ProviderInterface.php +20 -20
- includes/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php +66 -66
- includes/vendor/geoip2/geoip2/src/Record/AbstractRecord.php +61 -61
- includes/vendor/geoip2/geoip2/src/Record/City.php +29 -29
- includes/vendor/geoip2/geoip2/src/Record/Continent.php +32 -32
- includes/vendor/geoip2/geoip2/src/Record/Country.php +41 -41
- includes/vendor/geoip2/geoip2/src/Record/Location.php +52 -52
- includes/vendor/geoip2/geoip2/src/Record/MaxMind.php +19 -19
- includes/vendor/geoip2/geoip2/src/Record/Postal.php +26 -26
- includes/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php +39 -39
- includes/vendor/geoip2/geoip2/src/Record/Subdivision.php +40 -40
- includes/vendor/geoip2/geoip2/src/Record/Traits.php +114 -114
- includes/vendor/geoip2/geoip2/src/WebService/Client.php +239 -239
- includes/vendor/maxmind-db/reader/CHANGELOG.md +121 -121
- includes/vendor/maxmind-db/reader/LICENSE +202 -202
- includes/vendor/maxmind-db/reader/README.md +156 -156
- includes/vendor/maxmind-db/reader/autoload.php +44 -44
- includes/vendor/maxmind-db/reader/composer.json +34 -34
- includes/vendor/maxmind-db/reader/ext/config.m4 +19 -19
- includes/vendor/maxmind-db/reader/ext/maxminddb.c +564 -564
- includes/vendor/maxmind-db/reader/ext/php_maxminddb.h +24 -24
- includes/vendor/maxmind-db/reader/ext/tests/001-load.phpt +12 -12
- includes/vendor/maxmind-db/reader/ext/tests/002-final.phpt +13 -13
- includes/vendor/maxmind-db/reader/ext/tests/003-open-basedir.phpt +12 -12
- includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php +309 -309
- includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php +311 -311
- includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php +10 -10
- includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php +69 -69
- includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php +26 -26
- includes/vendor/maxmind/web-service-common/CHANGELOG.md +79 -79
- includes/vendor/maxmind/web-service-common/LICENSE +202 -202
- includes/vendor/maxmind/web-service-common/README.md +26 -26
- includes/vendor/maxmind/web-service-common/composer.json +31 -31
- includes/vendor/maxmind/web-service-common/dev-bin/release.sh +60 -60
- includes/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php +10 -10
- includes/vendor/maxmind/web-service-common/src/Exception/HttpException.php +40 -40
- includes/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php +10 -10
- includes/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php +12 -12
- includes/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php +37 -37
- includes/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php +7 -7
- includes/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php +10 -10
- includes/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php +10 -10
- includes/vendor/maxmind/web-service-common/src/WebService/Client.php +472 -472
- includes/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php +110 -110
- includes/vendor/maxmind/web-service-common/src/WebService/Http/Request.php +29 -29
- includes/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php +26 -26
- readme.txt +5 -2
- wp-statistics.php +1 -1
composer.json
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
{
|
2 |
"require": {
|
|
|
3 |
"geoip2/geoip2": "^2.9.0",
|
4 |
"s1lentium/iptools": "^1.1.0",
|
5 |
"whichbrowser/parser": "2.0.37",
|
1 |
{
|
2 |
"require": {
|
3 |
+
"php": ">=5.4",
|
4 |
"geoip2/geoip2": "^2.9.0",
|
5 |
"s1lentium/iptools": "^1.1.0",
|
6 |
"whichbrowser/parser": "2.0.37",
|
includes/classes/class-wp-statistics-admin-pages.php
CHANGED
@@ -145,9 +145,9 @@ class WP_Statistics_Admin_Pages {
|
|
145 |
}
|
146 |
|
147 |
//Set Default Hidden MetaBox
|
148 |
-
add_filter( 'default_hidden_meta_boxes', array(
|
149 |
}
|
150 |
-
|
151 |
/*
|
152 |
* Default Hidden Meta Box
|
153 |
*/
|
145 |
}
|
146 |
|
147 |
//Set Default Hidden MetaBox
|
148 |
+
add_filter( 'default_hidden_meta_boxes', array( 'WP_Statistics_Admin_Pages', 'default_hide_meta_box') );
|
149 |
}
|
150 |
+
|
151 |
/*
|
152 |
* Default Hidden Meta Box
|
153 |
*/
|
includes/classes/class-wp-statistics-admin.php
CHANGED
@@ -74,8 +74,8 @@ class WP_Statistics_Admin {
|
|
74 |
// Runs some scripts at the end of the admin panel inside the body tag
|
75 |
add_action( 'admin_footer', array( $this, 'admin_footer_scripts' ) );
|
76 |
|
77 |
-
//Load TinyMce Function
|
78 |
-
WP_Statistics_TinyMCE
|
79 |
|
80 |
//Add Notice Use cache plugin
|
81 |
add_action( 'admin_notices', array( $this, 'notification_use_cache_plugin' ) );
|
74 |
// Runs some scripts at the end of the admin panel inside the body tag
|
75 |
add_action( 'admin_footer', array( $this, 'admin_footer_scripts' ) );
|
76 |
|
77 |
+
// Load TinyMce Function
|
78 |
+
new WP_Statistics_TinyMCE();
|
79 |
|
80 |
//Add Notice Use cache plugin
|
81 |
add_action( 'admin_notices', array( $this, 'notification_use_cache_plugin' ) );
|
includes/classes/class-wp-statistics-rest.php
CHANGED
@@ -40,7 +40,7 @@ class WP_Statistics_Rest {
|
|
40 |
}
|
41 |
|
42 |
/*
|
43 |
-
* Hit
|
44 |
*/
|
45 |
public function hit() {
|
46 |
global $WP_Statistics;
|
40 |
}
|
41 |
|
42 |
/*
|
43 |
+
* Wp Statistic Hit Save
|
44 |
*/
|
45 |
public function hit() {
|
46 |
global $WP_Statistics;
|
includes/classes/class-wp-statistics-tinymce.php
CHANGED
@@ -8,17 +8,15 @@ class WP_Statistics_TinyMCE {
|
|
8 |
/**
|
9 |
* Setup an TinyMCE action to close the notice on the overview page.
|
10 |
*/
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
add_action('admin_head', array(self::class, 'wp_statistic_add_my_tc_button'));
|
15 |
|
16 |
//Load Text Widget Button
|
17 |
-
add_action( 'admin_enqueue_scripts', array(
|
18 |
-
|
19 |
-
//Add TextLang
|
20 |
-
add_action( 'admin_footer-widgets.php', array(self::class, 'my_post_edit_page_footer'), 999 );
|
21 |
|
|
|
|
|
22 |
}
|
23 |
|
24 |
/*
|
@@ -74,7 +72,7 @@ class WP_Statistics_TinyMCE {
|
|
74 |
/*
|
75 |
* Add Filter TinyMCE
|
76 |
*/
|
77 |
-
|
78 |
{
|
79 |
global $typenow;
|
80 |
|
@@ -89,16 +87,16 @@ class WP_Statistics_TinyMCE {
|
|
89 |
|
90 |
// check if WYSIWYG is enabled
|
91 |
if ( get_user_option('rich_editing') == 'true') {
|
92 |
-
add_filter("mce_external_plugins", array(
|
93 |
-
add_filter('mce_buttons', array(
|
94 |
-
add_filter('mce_external_languages', array(
|
95 |
}
|
96 |
}
|
97 |
|
98 |
/*
|
99 |
* Add Js Bottun to Editor
|
100 |
*/
|
101 |
-
|
102 |
$plugin_array['wp_statistic_tc_button'] = WP_Statistics::$reg['plugin-url'].'assets/js/tinymce.js';
|
103 |
return $plugin_array;
|
104 |
}
|
@@ -106,7 +104,7 @@ class WP_Statistics_TinyMCE {
|
|
106 |
/*
|
107 |
* Push Button to TinyMCE Advance
|
108 |
*/
|
109 |
-
|
110 |
array_push($buttons, "wp_statistic_tc_button");
|
111 |
return $buttons;
|
112 |
}
|
@@ -114,7 +112,7 @@ class WP_Statistics_TinyMCE {
|
|
114 |
/*
|
115 |
* Add Lang Text Domain
|
116 |
*/
|
117 |
-
|
118 |
$locales ['wp-statistic-tinymce-plugin'] = WP_Statistics::$reg['plugin-dir'].'includes/functions/tinymce.php';
|
119 |
return $locales;
|
120 |
}
|
@@ -122,7 +120,7 @@ class WP_Statistics_TinyMCE {
|
|
122 |
/*
|
123 |
* Add Button For Text Widget
|
124 |
*/
|
125 |
-
|
126 |
global $pagenow;
|
127 |
if($pagenow =="widgets.php") {
|
128 |
wp_enqueue_script( 'add_wp_statistic_button_for_widget_text', WP_Statistics::$reg['plugin-url'].'assets/js/tinymce.js' );
|
@@ -132,7 +130,7 @@ class WP_Statistics_TinyMCE {
|
|
132 |
/*
|
133 |
* Add Lang for Text Widget
|
134 |
*/
|
135 |
-
|
136 |
echo '
|
137 |
<script type="text/javascript">
|
138 |
jQuery( document ).on( \'tinymce-editor-setup\', function( event, editor ) {
|
8 |
/**
|
9 |
* Setup an TinyMCE action to close the notice on the overview page.
|
10 |
*/
|
11 |
+
public function __construct() {
|
12 |
+
// Add Filter TinyMce Editor
|
13 |
+
add_action('admin_head', array($this, 'wp_statistic_add_my_tc_button'));
|
|
|
14 |
|
15 |
//Load Text Widget Button
|
16 |
+
add_action( 'admin_enqueue_scripts', array($this, 'load_tinymcejs_widget_wp_admin_style') );
|
|
|
|
|
|
|
17 |
|
18 |
+
// Add TextLang
|
19 |
+
add_action( 'admin_footer-widgets.php', array($this, 'my_post_edit_page_footer'), 999 );
|
20 |
}
|
21 |
|
22 |
/*
|
72 |
/*
|
73 |
* Add Filter TinyMCE
|
74 |
*/
|
75 |
+
public function wp_statistic_add_my_tc_button()
|
76 |
{
|
77 |
global $typenow;
|
78 |
|
87 |
|
88 |
// check if WYSIWYG is enabled
|
89 |
if ( get_user_option('rich_editing') == 'true') {
|
90 |
+
add_filter("mce_external_plugins", array($this, 'wp_statistic_add_tinymce_plugin'));
|
91 |
+
add_filter('mce_buttons', array($this, 'wp_statistic_register_my_tc_button'));
|
92 |
+
add_filter('mce_external_languages', array($this, 'wp_statistic_tinymce_plugin_add_locale'));
|
93 |
}
|
94 |
}
|
95 |
|
96 |
/*
|
97 |
* Add Js Bottun to Editor
|
98 |
*/
|
99 |
+
public function wp_statistic_add_tinymce_plugin($plugin_array) {
|
100 |
$plugin_array['wp_statistic_tc_button'] = WP_Statistics::$reg['plugin-url'].'assets/js/tinymce.js';
|
101 |
return $plugin_array;
|
102 |
}
|
104 |
/*
|
105 |
* Push Button to TinyMCE Advance
|
106 |
*/
|
107 |
+
public function wp_statistic_register_my_tc_button($buttons) {
|
108 |
array_push($buttons, "wp_statistic_tc_button");
|
109 |
return $buttons;
|
110 |
}
|
112 |
/*
|
113 |
* Add Lang Text Domain
|
114 |
*/
|
115 |
+
public function wp_statistic_tinymce_plugin_add_locale($locales) {
|
116 |
$locales ['wp-statistic-tinymce-plugin'] = WP_Statistics::$reg['plugin-dir'].'includes/functions/tinymce.php';
|
117 |
return $locales;
|
118 |
}
|
120 |
/*
|
121 |
* Add Button For Text Widget
|
122 |
*/
|
123 |
+
public function load_tinymcejs_widget_wp_admin_style(){
|
124 |
global $pagenow;
|
125 |
if($pagenow =="widgets.php") {
|
126 |
wp_enqueue_script( 'add_wp_statistic_button_for_widget_text', WP_Statistics::$reg['plugin-url'].'assets/js/tinymce.js' );
|
130 |
/*
|
131 |
* Add Lang for Text Widget
|
132 |
*/
|
133 |
+
public function my_post_edit_page_footer(){
|
134 |
echo '
|
135 |
<script type="text/javascript">
|
136 |
jQuery( document ).on( \'tinymce-editor-setup\', function( event, editor ) {
|
includes/vendor/autoload.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload.php @generated by Composer
|
4 |
-
|
5 |
-
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
-
|
7 |
-
return ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7::getLoader();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload.php @generated by Composer
|
4 |
+
|
5 |
+
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
+
|
7 |
+
return ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7::getLoader();
|
includes/vendor/composer/LICENSE
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
|
2 |
-
Copyright (c) Nils Adermann, Jordi Boggiano
|
3 |
-
|
4 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
-
of this software and associated documentation files (the "Software"), to deal
|
6 |
-
in the Software without restriction, including without limitation the rights
|
7 |
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 |
-
copies of the Software, and to permit persons to whom the Software is furnished
|
9 |
-
to do so, subject to the following conditions:
|
10 |
-
|
11 |
-
The above copyright notice and this permission notice shall be included in all
|
12 |
-
copies or substantial portions of the Software.
|
13 |
-
|
14 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 |
-
THE SOFTWARE.
|
21 |
-
|
1 |
+
|
2 |
+
Copyright (c) Nils Adermann, Jordi Boggiano
|
3 |
+
|
4 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
+
of this software and associated documentation files (the "Software"), to deal
|
6 |
+
in the Software without restriction, including without limitation the rights
|
7 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
9 |
+
to do so, subject to the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included in all
|
12 |
+
copies or substantial portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 |
+
THE SOFTWARE.
|
21 |
+
|
includes/vendor/composer/autoload_classmap.php
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload_classmap.php @generated by Composer
|
4 |
-
|
5 |
-
$vendorDir = dirname(dirname(__FILE__));
|
6 |
-
$baseDir = dirname(dirname($vendorDir));
|
7 |
-
|
8 |
-
return array(
|
9 |
-
);
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_classmap.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname(dirname($vendorDir));
|
7 |
+
|
8 |
+
return array(
|
9 |
+
);
|
includes/vendor/composer/autoload_namespaces.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload_namespaces.php @generated by Composer
|
4 |
-
|
5 |
-
$vendorDir = dirname(dirname(__FILE__));
|
6 |
-
$baseDir = dirname(dirname($vendorDir));
|
7 |
-
|
8 |
-
return array(
|
9 |
-
'Parsedown' => array($vendorDir . '/erusev/parsedown'),
|
10 |
-
);
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_namespaces.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname(dirname($vendorDir));
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'Parsedown' => array($vendorDir . '/erusev/parsedown'),
|
10 |
+
);
|
includes/vendor/composer/autoload_psr4.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload_psr4.php @generated by Composer
|
4 |
-
|
5 |
-
$vendorDir = dirname(dirname(__FILE__));
|
6 |
-
$baseDir = dirname(dirname($vendorDir));
|
7 |
-
|
8 |
-
return array(
|
9 |
-
'WhichBrowser\\' => array($vendorDir . '/whichbrowser/parser/src', $vendorDir . '/whichbrowser/parser/tests/src'),
|
10 |
-
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
11 |
-
'MaxMind\\WebService\\' => array($vendorDir . '/maxmind/web-service-common/src/WebService'),
|
12 |
-
'MaxMind\\Exception\\' => array($vendorDir . '/maxmind/web-service-common/src/Exception'),
|
13 |
-
'MaxMind\\Db\\' => array($vendorDir . '/maxmind-db/reader/src/MaxMind/Db'),
|
14 |
-
'Jaybizzle\\CrawlerDetect\\' => array($vendorDir . '/jaybizzle/crawler-detect/src'),
|
15 |
-
'IPTools\\' => array($vendorDir . '/s1lentium/iptools/src'),
|
16 |
-
'GeoIp2\\' => array($vendorDir . '/geoip2/geoip2/src'),
|
17 |
-
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
|
18 |
-
);
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_psr4.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname(dirname($vendorDir));
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'WhichBrowser\\' => array($vendorDir . '/whichbrowser/parser/src', $vendorDir . '/whichbrowser/parser/tests/src'),
|
10 |
+
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
11 |
+
'MaxMind\\WebService\\' => array($vendorDir . '/maxmind/web-service-common/src/WebService'),
|
12 |
+
'MaxMind\\Exception\\' => array($vendorDir . '/maxmind/web-service-common/src/Exception'),
|
13 |
+
'MaxMind\\Db\\' => array($vendorDir . '/maxmind-db/reader/src/MaxMind/Db'),
|
14 |
+
'Jaybizzle\\CrawlerDetect\\' => array($vendorDir . '/jaybizzle/crawler-detect/src'),
|
15 |
+
'IPTools\\' => array($vendorDir . '/s1lentium/iptools/src'),
|
16 |
+
'GeoIp2\\' => array($vendorDir . '/geoip2/geoip2/src'),
|
17 |
+
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
|
18 |
+
);
|
includes/vendor/composer/autoload_real.php
CHANGED
@@ -1,52 +1,52 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload_real.php @generated by Composer
|
4 |
-
|
5 |
-
class ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7
|
6 |
-
{
|
7 |
-
private static $loader;
|
8 |
-
|
9 |
-
public static function loadClassLoader($class)
|
10 |
-
{
|
11 |
-
if ('Composer\Autoload\ClassLoader' === $class) {
|
12 |
-
require __DIR__ . '/ClassLoader.php';
|
13 |
-
}
|
14 |
-
}
|
15 |
-
|
16 |
-
public static function getLoader()
|
17 |
-
{
|
18 |
-
if (null !== self::$loader) {
|
19 |
-
return self::$loader;
|
20 |
-
}
|
21 |
-
|
22 |
-
spl_autoload_register(array('ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7', 'loadClassLoader'), true, true);
|
23 |
-
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7', 'loadClassLoader'));
|
25 |
-
|
26 |
-
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
-
if ($useStaticLoader) {
|
28 |
-
require_once __DIR__ . '/autoload_static.php';
|
29 |
-
|
30 |
-
call_user_func(\Composer\Autoload\ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::getInitializer($loader));
|
31 |
-
} else {
|
32 |
-
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
-
foreach ($map as $namespace => $path) {
|
34 |
-
$loader->set($namespace, $path);
|
35 |
-
}
|
36 |
-
|
37 |
-
$map = require __DIR__ . '/autoload_psr4.php';
|
38 |
-
foreach ($map as $namespace => $path) {
|
39 |
-
$loader->setPsr4($namespace, $path);
|
40 |
-
}
|
41 |
-
|
42 |
-
$classMap = require __DIR__ . '/autoload_classmap.php';
|
43 |
-
if ($classMap) {
|
44 |
-
$loader->addClassMap($classMap);
|
45 |
-
}
|
46 |
-
}
|
47 |
-
|
48 |
-
$loader->register(true);
|
49 |
-
|
50 |
-
return $loader;
|
51 |
-
}
|
52 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_real.php @generated by Composer
|
4 |
+
|
5 |
+
class ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7
|
6 |
+
{
|
7 |
+
private static $loader;
|
8 |
+
|
9 |
+
public static function loadClassLoader($class)
|
10 |
+
{
|
11 |
+
if ('Composer\Autoload\ClassLoader' === $class) {
|
12 |
+
require __DIR__ . '/ClassLoader.php';
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
public static function getLoader()
|
17 |
+
{
|
18 |
+
if (null !== self::$loader) {
|
19 |
+
return self::$loader;
|
20 |
+
}
|
21 |
+
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7', 'loadClassLoader'), true, true);
|
23 |
+
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInite38eff48d6e6d75cf438d3ef850d45a7', 'loadClassLoader'));
|
25 |
+
|
26 |
+
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
+
if ($useStaticLoader) {
|
28 |
+
require_once __DIR__ . '/autoload_static.php';
|
29 |
+
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::getInitializer($loader));
|
31 |
+
} else {
|
32 |
+
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
+
foreach ($map as $namespace => $path) {
|
34 |
+
$loader->set($namespace, $path);
|
35 |
+
}
|
36 |
+
|
37 |
+
$map = require __DIR__ . '/autoload_psr4.php';
|
38 |
+
foreach ($map as $namespace => $path) {
|
39 |
+
$loader->setPsr4($namespace, $path);
|
40 |
+
}
|
41 |
+
|
42 |
+
$classMap = require __DIR__ . '/autoload_classmap.php';
|
43 |
+
if ($classMap) {
|
44 |
+
$loader->addClassMap($classMap);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
$loader->register(true);
|
49 |
+
|
50 |
+
return $loader;
|
51 |
+
}
|
52 |
+
}
|
includes/vendor/composer/autoload_static.php
CHANGED
@@ -1,101 +1,101 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload_static.php @generated by Composer
|
4 |
-
|
5 |
-
namespace Composer\Autoload;
|
6 |
-
|
7 |
-
class ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7
|
8 |
-
{
|
9 |
-
public static $prefixLengthsPsr4 = array (
|
10 |
-
'W' =>
|
11 |
-
array (
|
12 |
-
'WhichBrowser\\' => 13,
|
13 |
-
),
|
14 |
-
'P' =>
|
15 |
-
array (
|
16 |
-
'Psr\\Cache\\' => 10,
|
17 |
-
),
|
18 |
-
'M' =>
|
19 |
-
array (
|
20 |
-
'MaxMind\\WebService\\' => 19,
|
21 |
-
'MaxMind\\Exception\\' => 18,
|
22 |
-
'MaxMind\\Db\\' => 11,
|
23 |
-
),
|
24 |
-
'J' =>
|
25 |
-
array (
|
26 |
-
'Jaybizzle\\CrawlerDetect\\' => 24,
|
27 |
-
),
|
28 |
-
'I' =>
|
29 |
-
array (
|
30 |
-
'IPTools\\' => 8,
|
31 |
-
),
|
32 |
-
'G' =>
|
33 |
-
array (
|
34 |
-
'GeoIp2\\' => 7,
|
35 |
-
),
|
36 |
-
'C' =>
|
37 |
-
array (
|
38 |
-
'Composer\\CaBundle\\' => 18,
|
39 |
-
),
|
40 |
-
);
|
41 |
-
|
42 |
-
public static $prefixDirsPsr4 = array (
|
43 |
-
'WhichBrowser\\' =>
|
44 |
-
array (
|
45 |
-
0 => __DIR__ . '/..' . '/whichbrowser/parser/src',
|
46 |
-
1 => __DIR__ . '/..' . '/whichbrowser/parser/tests/src',
|
47 |
-
),
|
48 |
-
'Psr\\Cache\\' =>
|
49 |
-
array (
|
50 |
-
0 => __DIR__ . '/..' . '/psr/cache/src',
|
51 |
-
),
|
52 |
-
'MaxMind\\WebService\\' =>
|
53 |
-
array (
|
54 |
-
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService',
|
55 |
-
),
|
56 |
-
'MaxMind\\Exception\\' =>
|
57 |
-
array (
|
58 |
-
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception',
|
59 |
-
),
|
60 |
-
'MaxMind\\Db\\' =>
|
61 |
-
array (
|
62 |
-
0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db',
|
63 |
-
),
|
64 |
-
'Jaybizzle\\CrawlerDetect\\' =>
|
65 |
-
array (
|
66 |
-
0 => __DIR__ . '/..' . '/jaybizzle/crawler-detect/src',
|
67 |
-
),
|
68 |
-
'IPTools\\' =>
|
69 |
-
array (
|
70 |
-
0 => __DIR__ . '/..' . '/s1lentium/iptools/src',
|
71 |
-
),
|
72 |
-
'GeoIp2\\' =>
|
73 |
-
array (
|
74 |
-
0 => __DIR__ . '/..' . '/geoip2/geoip2/src',
|
75 |
-
),
|
76 |
-
'Composer\\CaBundle\\' =>
|
77 |
-
array (
|
78 |
-
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
|
79 |
-
),
|
80 |
-
);
|
81 |
-
|
82 |
-
public static $prefixesPsr0 = array (
|
83 |
-
'P' =>
|
84 |
-
array (
|
85 |
-
'Parsedown' =>
|
86 |
-
array (
|
87 |
-
0 => __DIR__ . '/..' . '/erusev/parsedown',
|
88 |
-
),
|
89 |
-
),
|
90 |
-
);
|
91 |
-
|
92 |
-
public static function getInitializer(ClassLoader $loader)
|
93 |
-
{
|
94 |
-
return \Closure::bind(function () use ($loader) {
|
95 |
-
$loader->prefixLengthsPsr4 = ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::$prefixLengthsPsr4;
|
96 |
-
$loader->prefixDirsPsr4 = ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::$prefixDirsPsr4;
|
97 |
-
$loader->prefixesPsr0 = ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::$prefixesPsr0;
|
98 |
-
|
99 |
-
}, null, ClassLoader::class);
|
100 |
-
}
|
101 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_static.php @generated by Composer
|
4 |
+
|
5 |
+
namespace Composer\Autoload;
|
6 |
+
|
7 |
+
class ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7
|
8 |
+
{
|
9 |
+
public static $prefixLengthsPsr4 = array (
|
10 |
+
'W' =>
|
11 |
+
array (
|
12 |
+
'WhichBrowser\\' => 13,
|
13 |
+
),
|
14 |
+
'P' =>
|
15 |
+
array (
|
16 |
+
'Psr\\Cache\\' => 10,
|
17 |
+
),
|
18 |
+
'M' =>
|
19 |
+
array (
|
20 |
+
'MaxMind\\WebService\\' => 19,
|
21 |
+
'MaxMind\\Exception\\' => 18,
|
22 |
+
'MaxMind\\Db\\' => 11,
|
23 |
+
),
|
24 |
+
'J' =>
|
25 |
+
array (
|
26 |
+
'Jaybizzle\\CrawlerDetect\\' => 24,
|
27 |
+
),
|
28 |
+
'I' =>
|
29 |
+
array (
|
30 |
+
'IPTools\\' => 8,
|
31 |
+
),
|
32 |
+
'G' =>
|
33 |
+
array (
|
34 |
+
'GeoIp2\\' => 7,
|
35 |
+
),
|
36 |
+
'C' =>
|
37 |
+
array (
|
38 |
+
'Composer\\CaBundle\\' => 18,
|
39 |
+
),
|
40 |
+
);
|
41 |
+
|
42 |
+
public static $prefixDirsPsr4 = array (
|
43 |
+
'WhichBrowser\\' =>
|
44 |
+
array (
|
45 |
+
0 => __DIR__ . '/..' . '/whichbrowser/parser/src',
|
46 |
+
1 => __DIR__ . '/..' . '/whichbrowser/parser/tests/src',
|
47 |
+
),
|
48 |
+
'Psr\\Cache\\' =>
|
49 |
+
array (
|
50 |
+
0 => __DIR__ . '/..' . '/psr/cache/src',
|
51 |
+
),
|
52 |
+
'MaxMind\\WebService\\' =>
|
53 |
+
array (
|
54 |
+
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService',
|
55 |
+
),
|
56 |
+
'MaxMind\\Exception\\' =>
|
57 |
+
array (
|
58 |
+
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception',
|
59 |
+
),
|
60 |
+
'MaxMind\\Db\\' =>
|
61 |
+
array (
|
62 |
+
0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db',
|
63 |
+
),
|
64 |
+
'Jaybizzle\\CrawlerDetect\\' =>
|
65 |
+
array (
|
66 |
+
0 => __DIR__ . '/..' . '/jaybizzle/crawler-detect/src',
|
67 |
+
),
|
68 |
+
'IPTools\\' =>
|
69 |
+
array (
|
70 |
+
0 => __DIR__ . '/..' . '/s1lentium/iptools/src',
|
71 |
+
),
|
72 |
+
'GeoIp2\\' =>
|
73 |
+
array (
|
74 |
+
0 => __DIR__ . '/..' . '/geoip2/geoip2/src',
|
75 |
+
),
|
76 |
+
'Composer\\CaBundle\\' =>
|
77 |
+
array (
|
78 |
+
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
|
79 |
+
),
|
80 |
+
);
|
81 |
+
|
82 |
+
public static $prefixesPsr0 = array (
|
83 |
+
'P' =>
|
84 |
+
array (
|
85 |
+
'Parsedown' =>
|
86 |
+
array (
|
87 |
+
0 => __DIR__ . '/..' . '/erusev/parsedown',
|
88 |
+
),
|
89 |
+
),
|
90 |
+
);
|
91 |
+
|
92 |
+
public static function getInitializer(ClassLoader $loader)
|
93 |
+
{
|
94 |
+
return \Closure::bind(function () use ($loader) {
|
95 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::$prefixLengthsPsr4;
|
96 |
+
$loader->prefixDirsPsr4 = ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::$prefixDirsPsr4;
|
97 |
+
$loader->prefixesPsr0 = ComposerStaticInite38eff48d6e6d75cf438d3ef850d45a7::$prefixesPsr0;
|
98 |
+
|
99 |
+
}, null, ClassLoader::class);
|
100 |
+
}
|
101 |
+
}
|
includes/vendor/composer/ca-bundle/LICENSE
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
Copyright (C) 2016 Composer
|
2 |
-
|
3 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4 |
-
this software and associated documentation files (the "Software"), to deal in
|
5 |
-
the Software without restriction, including without limitation the rights to
|
6 |
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7 |
-
of the Software, and to permit persons to whom the Software is furnished to do
|
8 |
-
so, subject to the following conditions:
|
9 |
-
|
10 |
-
The above copyright notice and this permission notice shall be included in all
|
11 |
-
copies or substantial portions of the Software.
|
12 |
-
|
13 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19 |
-
SOFTWARE.
|
1 |
+
Copyright (C) 2016 Composer
|
2 |
+
|
3 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4 |
+
this software and associated documentation files (the "Software"), to deal in
|
5 |
+
the Software without restriction, including without limitation the rights to
|
6 |
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7 |
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8 |
+
so, subject to the following conditions:
|
9 |
+
|
10 |
+
The above copyright notice and this permission notice shall be included in all
|
11 |
+
copies or substantial portions of the Software.
|
12 |
+
|
13 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19 |
+
SOFTWARE.
|
includes/vendor/composer/ca-bundle/README.md
CHANGED
@@ -1,85 +1,85 @@
|
|
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 opensl_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) || (is_link($caPathOrFile) && is_dir(readlink($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) || (is_link($caPathOrFile) && is_dir(readlink($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.
|
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 opensl_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) || (is_link($caPathOrFile) && is_dir(readlink($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) || (is_link($caPathOrFile) && is_dir(readlink($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.
|
includes/vendor/composer/ca-bundle/composer.json
CHANGED
@@ -1,54 +1,54 @@
|
|
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"
|
28 |
-
},
|
29 |
-
"require-dev": {
|
30 |
-
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
31 |
-
"psr/log": "^1.0",
|
32 |
-
"symfony/process": "^2.5 || ^3.0 || ^4.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 |
-
}
|
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"
|
28 |
+
},
|
29 |
+
"require-dev": {
|
30 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
31 |
+
"psr/log": "^1.0",
|
32 |
+
"symfony/process": "^2.5 || ^3.0 || ^4.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 |
+
}
|
includes/vendor/composer/ca-bundle/src/CaBundle.php
CHANGED
@@ -1,308 +1,308 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of composer/ca-bundle.
|
5 |
-
*
|
6 |
-
* (c) Composer <https://github.com/composer>
|
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 <chris@cs278.org>
|
19 |
-
* @author Jordi Boggiano <j.boggiano@seld.be>
|
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 <me@evancoury.com>
|
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 |
-
|
70 |
-
// If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
|
71 |
-
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
72 |
-
$envCertFile = getenv('SSL_CERT_FILE');
|
73 |
-
if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
|
74 |
-
return self::$caPath = $envCertFile;
|
75 |
-
}
|
76 |
-
|
77 |
-
// If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
|
78 |
-
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
79 |
-
$envCertDir = getenv('SSL_CERT_DIR');
|
80 |
-
if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
|
81 |
-
return self::$caPath = $envCertDir;
|
82 |
-
}
|
83 |
-
|
84 |
-
$configured = ini_get('openssl.cafile');
|
85 |
-
if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
|
86 |
-
return self::$caPath = $configured;
|
87 |
-
}
|
88 |
-
|
89 |
-
$configured = ini_get('openssl.capath');
|
90 |
-
if ($configured && is_dir($configured) && is_readable($configured)) {
|
91 |
-
return self::$caPath = $configured;
|
92 |
-
}
|
93 |
-
|
94 |
-
$caBundlePaths = array(
|
95 |
-
'/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
|
96 |
-
'/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
|
97 |
-
'/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
|
98 |
-
'/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
|
99 |
-
'/usr/ssl/certs/ca-bundle.crt', // Cygwin
|
100 |
-
'/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
|
101 |
-
'/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
|
102 |
-
'/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
|
103 |
-
'/etc/ssl/cert.pem', // OpenBSD
|
104 |
-
'/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
|
105 |
-
'/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
|
106 |
-
);
|
107 |
-
|
108 |
-
foreach ($caBundlePaths as $caBundle) {
|
109 |
-
if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
|
110 |
-
return self::$caPath = $caBundle;
|
111 |
-
}
|
112 |
-
}
|
113 |
-
|
114 |
-
foreach ($caBundlePaths as $caBundle) {
|
115 |
-
$caBundle = dirname($caBundle);
|
116 |
-
if (@is_dir($caBundle) && glob($caBundle.'/*')) {
|
117 |
-
return self::$caPath = $caBundle;
|
118 |
-
}
|
119 |
-
}
|
120 |
-
|
121 |
-
return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
|
122 |
-
}
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Returns the path to the bundled CA file
|
126 |
-
*
|
127 |
-
* In case you don't want to trust the user or the system, you can use this directly
|
128 |
-
*
|
129 |
-
* @return string path to a CA bundle file
|
130 |
-
*/
|
131 |
-
public static function getBundledCaBundlePath()
|
132 |
-
{
|
133 |
-
$caBundleFile = __DIR__.'/../res/cacert.pem';
|
134 |
-
|
135 |
-
// cURL does not understand 'phar://' paths
|
136 |
-
// see https://github.com/composer/ca-bundle/issues/10
|
137 |
-
if (0 === strpos($caBundleFile, 'phar://')) {
|
138 |
-
file_put_contents(
|
139 |
-
$tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
|
140 |
-
file_get_contents($caBundleFile)
|
141 |
-
);
|
142 |
-
|
143 |
-
register_shutdown_function(function() use ($tempCaBundleFile) {
|
144 |
-
@unlink($tempCaBundleFile);
|
145 |
-
});
|
146 |
-
|
147 |
-
$caBundleFile = $tempCaBundleFile;
|
148 |
-
}
|
149 |
-
|
150 |
-
return $caBundleFile;
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Validates a CA file using opensl_x509_parse only if it is safe to use
|
155 |
-
*
|
156 |
-
* @param string $filename
|
157 |
-
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
158 |
-
*
|
159 |
-
* @return bool
|
160 |
-
*/
|
161 |
-
public static function validateCaFile($filename, LoggerInterface $logger = null)
|
162 |
-
{
|
163 |
-
static $warned = false;
|
164 |
-
|
165 |
-
if (isset(self::$caFileValidity[$filename])) {
|
166 |
-
return self::$caFileValidity[$filename];
|
167 |
-
}
|
168 |
-
|
169 |
-
$contents = file_get_contents($filename);
|
170 |
-
|
171 |
-
// assume the CA is valid if php is vulnerable to
|
172 |
-
// https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
|
173 |
-
if (!static::isOpensslParseSafe()) {
|
174 |
-
if (!$warned && $logger) {
|
175 |
-
$logger->warning(sprintf(
|
176 |
-
'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
|
177 |
-
PHP_VERSION
|
178 |
-
));
|
179 |
-
$warned = true;
|
180 |
-
}
|
181 |
-
|
182 |
-
$isValid = !empty($contents);
|
183 |
-
} else {
|
184 |
-
$isValid = (bool) openssl_x509_parse($contents);
|
185 |
-
}
|
186 |
-
|
187 |
-
if ($logger) {
|
188 |
-
$logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
|
189 |
-
}
|
190 |
-
|
191 |
-
return self::$caFileValidity[$filename] = $isValid;
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* Test if it is safe to use the PHP function openssl_x509_parse().
|
196 |
-
*
|
197 |
-
* This checks if OpenSSL extensions is vulnerable to remote code execution
|
198 |
-
* via the exploit documented as CVE-2013-6420.
|
199 |
-
*
|
200 |
-
* @return bool
|
201 |
-
*/
|
202 |
-
public static function isOpensslParseSafe()
|
203 |
-
{
|
204 |
-
if (null !== self::$useOpensslParse) {
|
205 |
-
return self::$useOpensslParse;
|
206 |
-
}
|
207 |
-
|
208 |
-
if (PHP_VERSION_ID >= 50600) {
|
209 |
-
return self::$useOpensslParse = true;
|
210 |
-
}
|
211 |
-
|
212 |
-
// Vulnerable:
|
213 |
-
// PHP 5.3.0 - PHP 5.3.27
|
214 |
-
// PHP 5.4.0 - PHP 5.4.22
|
215 |
-
// PHP 5.5.0 - PHP 5.5.6
|
216 |
-
if (
|
217 |
-
(PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
|
218 |
-
|| (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
|
219 |
-
|| (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
|
220 |
-
) {
|
221 |
-
// This version of PHP has the fix for CVE-2013-6420 applied.
|
222 |
-
return self::$useOpensslParse = true;
|
223 |
-
}
|
224 |
-
|
225 |
-
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
226 |
-
// Windows is probably insecure in this case.
|
227 |
-
return self::$useOpensslParse = false;
|
228 |
-
}
|
229 |
-
|
230 |
-
$compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
|
231 |
-
$regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
|
232 |
-
|
233 |
-
if (preg_match($regex, PHP_VERSION, $m)) {
|
234 |
-
return ((int) $m[1]) >= $fixedVersion;
|
235 |
-
}
|
236 |
-
|
237 |
-
return false;
|
238 |
-
};
|
239 |
-
|
240 |
-
// Hard coded list of PHP distributions with the fix backported.
|
241 |
-
if (
|
242 |
-
$compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
|
243 |
-
|| $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
|
244 |
-
|| $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
|
245 |
-
) {
|
246 |
-
return self::$useOpensslParse = true;
|
247 |
-
}
|
248 |
-
|
249 |
-
// Symfony Process component is missing so we assume it is unsafe at this point
|
250 |
-
if (!class_exists('Symfony\Component\Process\PhpProcess')) {
|
251 |
-
return self::$useOpensslParse = false;
|
252 |
-
}
|
253 |
-
|
254 |
-
// This is where things get crazy, because distros backport security
|
255 |
-
// fixes the chances are on NIX systems the fix has been applied but
|
256 |
-
// it's not possible to verify that from the PHP version.
|
257 |
-
//
|
258 |
-
// To verify exec a new PHP process and run the issue testcase with
|
259 |
-
// known safe input that replicates the bug.
|
260 |
-
|
261 |
-
// Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
|
262 |
-
// changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
|
263 |
-
$cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
|
264 |
-
$script = <<<'EOT'
|
265 |
-
|
266 |
-
error_reporting(-1);
|
267 |
-
$info = openssl_x509_parse(base64_decode('%s'));
|
268 |
-
var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
|
269 |
-
|
270 |
-
EOT;
|
271 |
-
$script = '<'."?php\n".sprintf($script, $cert);
|
272 |
-
|
273 |
-
try {
|
274 |
-
$process = new PhpProcess($script);
|
275 |
-
$process->mustRun();
|
276 |
-
} catch (\Exception $e) {
|
277 |
-
// In the case of any exceptions just accept it is not possible to
|
278 |
-
// determine the safety of openssl_x509_parse and bail out.
|
279 |
-
return self::$useOpensslParse = false;
|
280 |
-
}
|
281 |
-
|
282 |
-
$output = preg_split('{\r?\n}', trim($process->getOutput()));
|
283 |
-
$errorOutput = trim($process->getErrorOutput());
|
284 |
-
|
285 |
-
if (
|
286 |
-
count($output) === 3
|
287 |
-
&& $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
|
288 |
-
&& $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
|
289 |
-
&& $output[2] === 'int(-1)'
|
290 |
-
&& preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
|
291 |
-
) {
|
292 |
-
// This PHP has the fix backported probably by a distro security team.
|
293 |
-
return self::$useOpensslParse = true;
|
294 |
-
}
|
295 |
-
|
296 |
-
return self::$useOpensslParse = false;
|
297 |
-
}
|
298 |
-
|
299 |
-
/**
|
300 |
-
* Resets the static caches
|
301 |
-
*/
|
302 |
-
public static function reset()
|
303 |
-
{
|
304 |
-
self::$caFileValidity = array();
|
305 |
-
self::$caPath = null;
|
306 |
-
self::$useOpensslParse = null;
|
307 |
-
}
|
308 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of composer/ca-bundle.
|
5 |
+
*
|
6 |
+
* (c) Composer <https://github.com/composer>
|
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 <chris@cs278.org>
|
19 |
+
* @author Jordi Boggiano <j.boggiano@seld.be>
|
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 <me@evancoury.com>
|
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 |
+
|
70 |
+
// If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
|
71 |
+
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
72 |
+
$envCertFile = getenv('SSL_CERT_FILE');
|
73 |
+
if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
|
74 |
+
return self::$caPath = $envCertFile;
|
75 |
+
}
|
76 |
+
|
77 |
+
// If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
|
78 |
+
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
79 |
+
$envCertDir = getenv('SSL_CERT_DIR');
|
80 |
+
if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
|
81 |
+
return self::$caPath = $envCertDir;
|
82 |
+
}
|
83 |
+
|
84 |
+
$configured = ini_get('openssl.cafile');
|
85 |
+
if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
|
86 |
+
return self::$caPath = $configured;
|
87 |
+
}
|
88 |
+
|
89 |
+
$configured = ini_get('openssl.capath');
|
90 |
+
if ($configured && is_dir($configured) && is_readable($configured)) {
|
91 |
+
return self::$caPath = $configured;
|
92 |
+
}
|
93 |
+
|
94 |
+
$caBundlePaths = array(
|
95 |
+
'/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
|
96 |
+
'/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
|
97 |
+
'/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
|
98 |
+
'/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
|
99 |
+
'/usr/ssl/certs/ca-bundle.crt', // Cygwin
|
100 |
+
'/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
|
101 |
+
'/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
|
102 |
+
'/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
|
103 |
+
'/etc/ssl/cert.pem', // OpenBSD
|
104 |
+
'/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
|
105 |
+
'/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
|
106 |
+
);
|
107 |
+
|
108 |
+
foreach ($caBundlePaths as $caBundle) {
|
109 |
+
if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
|
110 |
+
return self::$caPath = $caBundle;
|
111 |
+
}
|
112 |
+
}
|
113 |
+
|
114 |
+
foreach ($caBundlePaths as $caBundle) {
|
115 |
+
$caBundle = dirname($caBundle);
|
116 |
+
if (@is_dir($caBundle) && glob($caBundle.'/*')) {
|
117 |
+
return self::$caPath = $caBundle;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Returns the path to the bundled CA file
|
126 |
+
*
|
127 |
+
* In case you don't want to trust the user or the system, you can use this directly
|
128 |
+
*
|
129 |
+
* @return string path to a CA bundle file
|
130 |
+
*/
|
131 |
+
public static function getBundledCaBundlePath()
|
132 |
+
{
|
133 |
+
$caBundleFile = __DIR__.'/../res/cacert.pem';
|
134 |
+
|
135 |
+
// cURL does not understand 'phar://' paths
|
136 |
+
// see https://github.com/composer/ca-bundle/issues/10
|
137 |
+
if (0 === strpos($caBundleFile, 'phar://')) {
|
138 |
+
file_put_contents(
|
139 |
+
$tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
|
140 |
+
file_get_contents($caBundleFile)
|
141 |
+
);
|
142 |
+
|
143 |
+
register_shutdown_function(function() use ($tempCaBundleFile) {
|
144 |
+
@unlink($tempCaBundleFile);
|
145 |
+
});
|
146 |
+
|
147 |
+
$caBundleFile = $tempCaBundleFile;
|
148 |
+
}
|
149 |
+
|
150 |
+
return $caBundleFile;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Validates a CA file using opensl_x509_parse only if it is safe to use
|
155 |
+
*
|
156 |
+
* @param string $filename
|
157 |
+
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
158 |
+
*
|
159 |
+
* @return bool
|
160 |
+
*/
|
161 |
+
public static function validateCaFile($filename, LoggerInterface $logger = null)
|
162 |
+
{
|
163 |
+
static $warned = false;
|
164 |
+
|
165 |
+
if (isset(self::$caFileValidity[$filename])) {
|
166 |
+
return self::$caFileValidity[$filename];
|
167 |
+
}
|
168 |
+
|
169 |
+
$contents = file_get_contents($filename);
|
170 |
+
|
171 |
+
// assume the CA is valid if php is vulnerable to
|
172 |
+
// https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
|
173 |
+
if (!static::isOpensslParseSafe()) {
|
174 |
+
if (!$warned && $logger) {
|
175 |
+
$logger->warning(sprintf(
|
176 |
+
'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
|
177 |
+
PHP_VERSION
|
178 |
+
));
|
179 |
+
$warned = true;
|
180 |
+
}
|
181 |
+
|
182 |
+
$isValid = !empty($contents);
|
183 |
+
} else {
|
184 |
+
$isValid = (bool) openssl_x509_parse($contents);
|
185 |
+
}
|
186 |
+
|
187 |
+
if ($logger) {
|
188 |
+
$logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
|
189 |
+
}
|
190 |
+
|
191 |
+
return self::$caFileValidity[$filename] = $isValid;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Test if it is safe to use the PHP function openssl_x509_parse().
|
196 |
+
*
|
197 |
+
* This checks if OpenSSL extensions is vulnerable to remote code execution
|
198 |
+
* via the exploit documented as CVE-2013-6420.
|
199 |
+
*
|
200 |
+
* @return bool
|
201 |
+
*/
|
202 |
+
public static function isOpensslParseSafe()
|
203 |
+
{
|
204 |
+
if (null !== self::$useOpensslParse) {
|
205 |
+
return self::$useOpensslParse;
|
206 |
+
}
|
207 |
+
|
208 |
+
if (PHP_VERSION_ID >= 50600) {
|
209 |
+
return self::$useOpensslParse = true;
|
210 |
+
}
|
211 |
+
|
212 |
+
// Vulnerable:
|
213 |
+
// PHP 5.3.0 - PHP 5.3.27
|
214 |
+
// PHP 5.4.0 - PHP 5.4.22
|
215 |
+
// PHP 5.5.0 - PHP 5.5.6
|
216 |
+
if (
|
217 |
+
(PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
|
218 |
+
|| (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
|
219 |
+
|| (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
|
220 |
+
) {
|
221 |
+
// This version of PHP has the fix for CVE-2013-6420 applied.
|
222 |
+
return self::$useOpensslParse = true;
|
223 |
+
}
|
224 |
+
|
225 |
+
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
226 |
+
// Windows is probably insecure in this case.
|
227 |
+
return self::$useOpensslParse = false;
|
228 |
+
}
|
229 |
+
|
230 |
+
$compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
|
231 |
+
$regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
|
232 |
+
|
233 |
+
if (preg_match($regex, PHP_VERSION, $m)) {
|
234 |
+
return ((int) $m[1]) >= $fixedVersion;
|
235 |
+
}
|
236 |
+
|
237 |
+
return false;
|
238 |
+
};
|
239 |
+
|
240 |
+
// Hard coded list of PHP distributions with the fix backported.
|
241 |
+
if (
|
242 |
+
$compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
|
243 |
+
|| $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
|
244 |
+
|| $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
|
245 |
+
) {
|
246 |
+
return self::$useOpensslParse = true;
|
247 |
+
}
|
248 |
+
|
249 |
+
// Symfony Process component is missing so we assume it is unsafe at this point
|
250 |
+
if (!class_exists('Symfony\Component\Process\PhpProcess')) {
|
251 |
+
return self::$useOpensslParse = false;
|
252 |
+
}
|
253 |
+
|
254 |
+
// This is where things get crazy, because distros backport security
|
255 |
+
// fixes the chances are on NIX systems the fix has been applied but
|
256 |
+
// it's not possible to verify that from the PHP version.
|
257 |
+
//
|
258 |
+
// To verify exec a new PHP process and run the issue testcase with
|
259 |
+
// known safe input that replicates the bug.
|
260 |
+
|
261 |
+
// Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
|
262 |
+
// changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
|
263 |
+
$cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
|
264 |
+
$script = <<<'EOT'
|
265 |
+
|
266 |
+
error_reporting(-1);
|
267 |
+
$info = openssl_x509_parse(base64_decode('%s'));
|
268 |
+
var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
|
269 |
+
|
270 |
+
EOT;
|
271 |
+
$script = '<'."?php\n".sprintf($script, $cert);
|
272 |
+
|
273 |
+
try {
|
274 |
+
$process = new PhpProcess($script);
|
275 |
+
$process->mustRun();
|
276 |
+
} catch (\Exception $e) {
|
277 |
+
// In the case of any exceptions just accept it is not possible to
|
278 |
+
// determine the safety of openssl_x509_parse and bail out.
|
279 |
+
return self::$useOpensslParse = false;
|
280 |
+
}
|
281 |
+
|
282 |
+
$output = preg_split('{\r?\n}', trim($process->getOutput()));
|
283 |
+
$errorOutput = trim($process->getErrorOutput());
|
284 |
+
|
285 |
+
if (
|
286 |
+
count($output) === 3
|
287 |
+
&& $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
|
288 |
+
&& $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
|
289 |
+
&& $output[2] === 'int(-1)'
|
290 |
+
&& preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
|
291 |
+
) {
|
292 |
+
// This PHP has the fix backported probably by a distro security team.
|
293 |
+
return self::$useOpensslParse = true;
|
294 |
+
}
|
295 |
+
|
296 |
+
return self::$useOpensslParse = false;
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Resets the static caches
|
301 |
+
*/
|
302 |
+
public static function reset()
|
303 |
+
{
|
304 |
+
self::$caFileValidity = array();
|
305 |
+
self::$caPath = null;
|
306 |
+
self::$useOpensslParse = null;
|
307 |
+
}
|
308 |
+
}
|
includes/vendor/composer/installed.json
CHANGED
@@ -1,481 +1,481 @@
|
|
1 |
-
[
|
2 |
-
{
|
3 |
-
"name": "composer/ca-bundle",
|
4 |
-
"version": "1.1.3",
|
5 |
-
"version_normalized": "1.1.3.0",
|
6 |
-
"source": {
|
7 |
-
"type": "git",
|
8 |
-
"url": "https://github.com/composer/ca-bundle.git",
|
9 |
-
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660"
|
10 |
-
},
|
11 |
-
"dist": {
|
12 |
-
"type": "zip",
|
13 |
-
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/8afa52cd417f4ec417b4bfe86b68106538a87660",
|
14 |
-
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660",
|
15 |
-
"shasum": ""
|
16 |
-
},
|
17 |
-
"require": {
|
18 |
-
"ext-openssl": "*",
|
19 |
-
"ext-pcre": "*",
|
20 |
-
"php": "^5.3.2 || ^7.0"
|
21 |
-
},
|
22 |
-
"require-dev": {
|
23 |
-
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
24 |
-
"psr/log": "^1.0",
|
25 |
-
"symfony/process": "^2.5 || ^3.0 || ^4.0"
|
26 |
-
},
|
27 |
-
"time": "2018-10-18T06:09:13+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": "erusev/parsedown",
|
62 |
-
"version": "1.7.1",
|
63 |
-
"version_normalized": "1.7.1.0",
|
64 |
-
"source": {
|
65 |
-
"type": "git",
|
66 |
-
"url": "https://github.com/erusev/parsedown.git",
|
67 |
-
"reference": "92e9c27ba0e74b8b028b111d1b6f956a15c01fc1"
|
68 |
-
},
|
69 |
-
"dist": {
|
70 |
-
"type": "zip",
|
71 |
-
"url": "https://api.github.com/repos/erusev/parsedown/zipball/92e9c27ba0e74b8b028b111d1b6f956a15c01fc1",
|
72 |
-
"reference": "92e9c27ba0e74b8b028b111d1b6f956a15c01fc1",
|
73 |
-
"shasum": ""
|
74 |
-
},
|
75 |
-
"require": {
|
76 |
-
"ext-mbstring": "*",
|
77 |
-
"php": ">=5.3.0"
|
78 |
-
},
|
79 |
-
"require-dev": {
|
80 |
-
"phpunit/phpunit": "^4.8.35"
|
81 |
-
},
|
82 |
-
"time": "2018-03-08T01:11:30+00:00",
|
83 |
-
"type": "library",
|
84 |
-
"installation-source": "dist",
|
85 |
-
"autoload": {
|
86 |
-
"psr-0": {
|
87 |
-
"Parsedown": ""
|
88 |
-
}
|
89 |
-
},
|
90 |
-
"notification-url": "https://packagist.org/downloads/",
|
91 |
-
"license": [
|
92 |
-
"MIT"
|
93 |
-
],
|
94 |
-
"authors": [
|
95 |
-
{
|
96 |
-
"name": "Emanuil Rusev",
|
97 |
-
"email": "hello@erusev.com",
|
98 |
-
"homepage": "http://erusev.com"
|
99 |
-
}
|
100 |
-
],
|
101 |
-
"description": "Parser for Markdown.",
|
102 |
-
"homepage": "http://parsedown.org",
|
103 |
-
"keywords": [
|
104 |
-
"markdown",
|
105 |
-
"parser"
|
106 |
-
]
|
107 |
-
},
|
108 |
-
{
|
109 |
-
"name": "geoip2/geoip2",
|
110 |
-
"version": "v2.9.0",
|
111 |
-
"version_normalized": "2.9.0.0",
|
112 |
-
"source": {
|
113 |
-
"type": "git",
|
114 |
-
"url": "https://github.com/maxmind/GeoIP2-php.git",
|
115 |
-
"reference": "a807fbf65212eef5d8d2db1a1b31082b53633d77"
|
116 |
-
},
|
117 |
-
"dist": {
|
118 |
-
"type": "zip",
|
119 |
-
"url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/a807fbf65212eef5d8d2db1a1b31082b53633d77",
|
120 |
-
"reference": "a807fbf65212eef5d8d2db1a1b31082b53633d77",
|
121 |
-
"shasum": ""
|
122 |
-
},
|
123 |
-
"require": {
|
124 |
-
"maxmind-db/reader": "~1.0",
|
125 |
-
"maxmind/web-service-common": "~0.5",
|
126 |
-
"php": ">=5.4"
|
127 |
-
},
|
128 |
-
"require-dev": {
|
129 |
-
"friendsofphp/php-cs-fixer": "2.*",
|
130 |
-
"phpunit/phpunit": "4.*",
|
131 |
-
"squizlabs/php_codesniffer": "3.*"
|
132 |
-
},
|
133 |
-
"time": "2018-04-10T15:32:59+00:00",
|
134 |
-
"type": "library",
|
135 |
-
"installation-source": "dist",
|
136 |
-
"autoload": {
|
137 |
-
"psr-4": {
|
138 |
-
"GeoIp2\\": "src"
|
139 |
-
}
|
140 |
-
},
|
141 |
-
"notification-url": "https://packagist.org/downloads/",
|
142 |
-
"license": [
|
143 |
-
"Apache-2.0"
|
144 |
-
],
|
145 |
-
"authors": [
|
146 |
-
{
|
147 |
-
"name": "Gregory J. Oschwald",
|
148 |
-
"email": "goschwald@maxmind.com",
|
149 |
-
"homepage": "http://www.maxmind.com/"
|
150 |
-
}
|
151 |
-
],
|
152 |
-
"description": "MaxMind GeoIP2 PHP API",
|
153 |
-
"homepage": "https://github.com/maxmind/GeoIP2-php",
|
154 |
-
"keywords": [
|
155 |
-
"IP",
|
156 |
-
"geoip",
|
157 |
-
"geoip2",
|
158 |
-
"geolocation",
|
159 |
-
"maxmind"
|
160 |
-
]
|
161 |
-
},
|
162 |
-
{
|
163 |
-
"name": "jaybizzle/crawler-detect",
|
164 |
-
"version": "v1.2.69",
|
165 |
-
"version_normalized": "1.2.69.0",
|
166 |
-
"source": {
|
167 |
-
"type": "git",
|
168 |
-
"url": "https://github.com/JayBizzle/Crawler-Detect.git",
|
169 |
-
"reference": "bac5e3f342f22477e74c5ba5daf3c3f84370bf20"
|
170 |
-
},
|
171 |
-
"dist": {
|
172 |
-
"type": "zip",
|
173 |
-
"url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/bac5e3f342f22477e74c5ba5daf3c3f84370bf20",
|
174 |
-
"reference": "bac5e3f342f22477e74c5ba5daf3c3f84370bf20",
|
175 |
-
"shasum": ""
|
176 |
-
},
|
177 |
-
"require": {
|
178 |
-
"php": ">=5.3.0"
|
179 |
-
},
|
180 |
-
"require-dev": {
|
181 |
-
"phpunit/phpunit": "^4.8|^5.5|^6.5",
|
182 |
-
"satooshi/php-coveralls": "1.*"
|
183 |
-
},
|
184 |
-
"time": "2018-10-03T08:53:34+00:00",
|
185 |
-
"type": "library",
|
186 |
-
"installation-source": "dist",
|
187 |
-
"autoload": {
|
188 |
-
"psr-4": {
|
189 |
-
"Jaybizzle\\CrawlerDetect\\": "src/"
|
190 |
-
}
|
191 |
-
},
|
192 |
-
"notification-url": "https://packagist.org/downloads/",
|
193 |
-
"license": [
|
194 |
-
"MIT"
|
195 |
-
],
|
196 |
-
"authors": [
|
197 |
-
{
|
198 |
-
"name": "Mark Beech",
|
199 |
-
"email": "m@rkbee.ch",
|
200 |
-
"role": "Developer"
|
201 |
-
}
|
202 |
-
],
|
203 |
-
"description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent",
|
204 |
-
"homepage": "https://github.com/JayBizzle/Crawler-Detect/",
|
205 |
-
"keywords": [
|
206 |
-
"crawler",
|
207 |
-
"crawler detect",
|
208 |
-
"crawler detector",
|
209 |
-
"crawlerdetect",
|
210 |
-
"php crawler detect"
|
211 |
-
]
|
212 |
-
},
|
213 |
-
{
|
214 |
-
"name": "maxmind-db/reader",
|
215 |
-
"version": "v1.3.0",
|
216 |
-
"version_normalized": "1.3.0.0",
|
217 |
-
"source": {
|
218 |
-
"type": "git",
|
219 |
-
"url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
|
220 |
-
"reference": "e042b4f8a2dff41e19019faf16427178b07fbd58"
|
221 |
-
},
|
222 |
-
"dist": {
|
223 |
-
"type": "zip",
|
224 |
-
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/e042b4f8a2dff41e19019faf16427178b07fbd58",
|
225 |
-
"reference": "e042b4f8a2dff41e19019faf16427178b07fbd58",
|
226 |
-
"shasum": ""
|
227 |
-
},
|
228 |
-
"require": {
|
229 |
-
"php": ">=5.4"
|
230 |
-
},
|
231 |
-
"require-dev": {
|
232 |
-
"friendsofphp/php-cs-fixer": "2.*",
|
233 |
-
"phpunit/phpunit": "4.* || 5.*",
|
234 |
-
"satooshi/php-coveralls": "1.0.*",
|
235 |
-
"squizlabs/php_codesniffer": "3.*"
|
236 |
-
},
|
237 |
-
"suggest": {
|
238 |
-
"ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
239 |
-
"ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
240 |
-
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
|
241 |
-
},
|
242 |
-
"time": "2018-02-21T21:23:33+00:00",
|
243 |
-
"type": "library",
|
244 |
-
"installation-source": "dist",
|
245 |
-
"autoload": {
|
246 |
-
"psr-4": {
|
247 |
-
"MaxMind\\Db\\": "src/MaxMind/Db"
|
248 |
-
}
|
249 |
-
},
|
250 |
-
"notification-url": "https://packagist.org/downloads/",
|
251 |
-
"license": [
|
252 |
-
"Apache-2.0"
|
253 |
-
],
|
254 |
-
"authors": [
|
255 |
-
{
|
256 |
-
"name": "Gregory J. Oschwald",
|
257 |
-
"email": "goschwald@maxmind.com",
|
258 |
-
"homepage": "http://www.maxmind.com/"
|
259 |
-
}
|
260 |
-
],
|
261 |
-
"description": "MaxMind DB Reader API",
|
262 |
-
"homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
|
263 |
-
"keywords": [
|
264 |
-
"database",
|
265 |
-
"geoip",
|
266 |
-
"geoip2",
|
267 |
-
"geolocation",
|
268 |
-
"maxmind"
|
269 |
-
]
|
270 |
-
},
|
271 |
-
{
|
272 |
-
"name": "maxmind/web-service-common",
|
273 |
-
"version": "v0.5.0",
|
274 |
-
"version_normalized": "0.5.0.0",
|
275 |
-
"source": {
|
276 |
-
"type": "git",
|
277 |
-
"url": "https://github.com/maxmind/web-service-common-php.git",
|
278 |
-
"reference": "61a9836fa3bb1743ab89752bae5005d71e78c73b"
|
279 |
-
},
|
280 |
-
"dist": {
|
281 |
-
"type": "zip",
|
282 |
-
"url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/61a9836fa3bb1743ab89752bae5005d71e78c73b",
|
283 |
-
"reference": "61a9836fa3bb1743ab89752bae5005d71e78c73b",
|
284 |
-
"shasum": ""
|
285 |
-
},
|
286 |
-
"require": {
|
287 |
-
"composer/ca-bundle": "^1.0.3",
|
288 |
-
"ext-curl": "*",
|
289 |
-
"ext-json": "*",
|
290 |
-
"php": ">=5.4"
|
291 |
-
},
|
292 |
-
"require-dev": {
|
293 |
-
"friendsofphp/php-cs-fixer": "2.*",
|
294 |
-
"phpunit/phpunit": "4.*",
|
295 |
-
"squizlabs/php_codesniffer": "3.*"
|
296 |
-
},
|
297 |
-
"time": "2018-02-12T22:31:54+00:00",
|
298 |
-
"type": "library",
|
299 |
-
"installation-source": "dist",
|
300 |
-
"autoload": {
|
301 |
-
"psr-4": {
|
302 |
-
"MaxMind\\Exception\\": "src/Exception",
|
303 |
-
"MaxMind\\WebService\\": "src/WebService"
|
304 |
-
}
|
305 |
-
},
|
306 |
-
"notification-url": "https://packagist.org/downloads/",
|
307 |
-
"license": [
|
308 |
-
"Apache-2.0"
|
309 |
-
],
|
310 |
-
"authors": [
|
311 |
-
{
|
312 |
-
"name": "Gregory Oschwald",
|
313 |
-
"email": "goschwald@maxmind.com"
|
314 |
-
}
|
315 |
-
],
|
316 |
-
"description": "Internal MaxMind Web Service API",
|
317 |
-
"homepage": "https://github.com/maxmind/web-service-common-php"
|
318 |
-
},
|
319 |
-
{
|
320 |
-
"name": "psr/cache",
|
321 |
-
"version": "1.0.1",
|
322 |
-
"version_normalized": "1.0.1.0",
|
323 |
-
"source": {
|
324 |
-
"type": "git",
|
325 |
-
"url": "https://github.com/php-fig/cache.git",
|
326 |
-
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
|
327 |
-
},
|
328 |
-
"dist": {
|
329 |
-
"type": "zip",
|
330 |
-
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
|
331 |
-
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
|
332 |
-
"shasum": ""
|
333 |
-
},
|
334 |
-
"require": {
|
335 |
-
"php": ">=5.3.0"
|
336 |
-
},
|
337 |
-
"time": "2016-08-06T20:24:11+00:00",
|
338 |
-
"type": "library",
|
339 |
-
"extra": {
|
340 |
-
"branch-alias": {
|
341 |
-
"dev-master": "1.0.x-dev"
|
342 |
-
}
|
343 |
-
},
|
344 |
-
"installation-source": "dist",
|
345 |
-
"autoload": {
|
346 |
-
"psr-4": {
|
347 |
-
"Psr\\Cache\\": "src/"
|
348 |
-
}
|
349 |
-
},
|
350 |
-
"notification-url": "https://packagist.org/downloads/",
|
351 |
-
"license": [
|
352 |
-
"MIT"
|
353 |
-
],
|
354 |
-
"authors": [
|
355 |
-
{
|
356 |
-
"name": "PHP-FIG",
|
357 |
-
"homepage": "http://www.php-fig.org/"
|
358 |
-
}
|
359 |
-
],
|
360 |
-
"description": "Common interface for caching libraries",
|
361 |
-
"keywords": [
|
362 |
-
"cache",
|
363 |
-
"psr",
|
364 |
-
"psr-6"
|
365 |
-
]
|
366 |
-
},
|
367 |
-
{
|
368 |
-
"name": "s1lentium/iptools",
|
369 |
-
"version": "v1.1.1",
|
370 |
-
"version_normalized": "1.1.1.0",
|
371 |
-
"source": {
|
372 |
-
"type": "git",
|
373 |
-
"url": "https://github.com/S1lentium/IPTools.git",
|
374 |
-
"reference": "f6f8ab6132ca7443bd7cced1681f5066d725fd5f"
|
375 |
-
},
|
376 |
-
"dist": {
|
377 |
-
"type": "zip",
|
378 |
-
"url": "https://api.github.com/repos/S1lentium/IPTools/zipball/f6f8ab6132ca7443bd7cced1681f5066d725fd5f",
|
379 |
-
"reference": "f6f8ab6132ca7443bd7cced1681f5066d725fd5f",
|
380 |
-
"shasum": ""
|
381 |
-
},
|
382 |
-
"require": {
|
383 |
-
"ext-bcmath": "*",
|
384 |
-
"php": ">=5.4.0"
|
385 |
-
},
|
386 |
-
"require-dev": {
|
387 |
-
"phpunit/phpunit": "~4.0",
|
388 |
-
"satooshi/php-coveralls": "~1.0"
|
389 |
-
},
|
390 |
-
"time": "2018-09-19T06:15:53+00:00",
|
391 |
-
"type": "library",
|
392 |
-
"installation-source": "dist",
|
393 |
-
"autoload": {
|
394 |
-
"psr-4": {
|
395 |
-
"IPTools\\": "src/"
|
396 |
-
}
|
397 |
-
},
|
398 |
-
"notification-url": "https://packagist.org/downloads/",
|
399 |
-
"license": [
|
400 |
-
"MIT"
|
401 |
-
],
|
402 |
-
"authors": [
|
403 |
-
{
|
404 |
-
"name": "Safarov Alisher",
|
405 |
-
"email": "alisher.safarov@outlook.com",
|
406 |
-
"homepage": "https://github.com/S1lentium"
|
407 |
-
}
|
408 |
-
],
|
409 |
-
"description": "PHP Library for manipulating network addresses (IPv4 and IPv6)",
|
410 |
-
"keywords": [
|
411 |
-
"IP",
|
412 |
-
"IP-Tools",
|
413 |
-
"cidr",
|
414 |
-
"ipv4",
|
415 |
-
"ipv6",
|
416 |
-
"network",
|
417 |
-
"subnet"
|
418 |
-
]
|
419 |
-
},
|
420 |
-
{
|
421 |
-
"name": "whichbrowser/parser",
|
422 |
-
"version": "v2.0.37",
|
423 |
-
"version_normalized": "2.0.37.0",
|
424 |
-
"source": {
|
425 |
-
"type": "git",
|
426 |
-
"url": "https://github.com/WhichBrowser/Parser-PHP.git",
|
427 |
-
"reference": "9c6ad8eadc23294b1c66d92876c11f13c5d4cf48"
|
428 |
-
},
|
429 |
-
"dist": {
|
430 |
-
"type": "zip",
|
431 |
-
"url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/9c6ad8eadc23294b1c66d92876c11f13c5d4cf48",
|
432 |
-
"reference": "9c6ad8eadc23294b1c66d92876c11f13c5d4cf48",
|
433 |
-
"shasum": ""
|
434 |
-
},
|
435 |
-
"require": {
|
436 |
-
"php": ">=5.4.0",
|
437 |
-
"psr/cache": "^1.0"
|
438 |
-
},
|
439 |
-
"require-dev": {
|
440 |
-
"icomefromthenet/reverse-regex": "0.0.6.3",
|
441 |
-
"phpunit/php-code-coverage": "^2.2|^3.0",
|
442 |
-
"phpunit/phpunit": "^4.0|^5.0",
|
443 |
-
"satooshi/php-coveralls": "^1.0",
|
444 |
-
"squizlabs/php_codesniffer": "2.5.*",
|
445 |
-
"symfony/yaml": ">=2.8"
|
446 |
-
},
|
447 |
-
"suggest": {
|
448 |
-
"cache/array-adapter": "Allows testing of the caching functionality"
|
449 |
-
},
|
450 |
-
"time": "2018-10-02T09:26:41+00:00",
|
451 |
-
"type": "library",
|
452 |
-
"installation-source": "dist",
|
453 |
-
"autoload": {
|
454 |
-
"psr-4": {
|
455 |
-
"WhichBrowser\\": [
|
456 |
-
"src/",
|
457 |
-
"tests/src/"
|
458 |
-
]
|
459 |
-
}
|
460 |
-
},
|
461 |
-
"notification-url": "https://packagist.org/downloads/",
|
462 |
-
"license": [
|
463 |
-
"MIT"
|
464 |
-
],
|
465 |
-
"authors": [
|
466 |
-
{
|
467 |
-
"name": "Niels Leenheer",
|
468 |
-
"email": "niels@leenheer.nl",
|
469 |
-
"role": "Developer"
|
470 |
-
}
|
471 |
-
],
|
472 |
-
"description": "Useragent sniffing library for PHP",
|
473 |
-
"homepage": "http://whichbrowser.net",
|
474 |
-
"keywords": [
|
475 |
-
"browser",
|
476 |
-
"sniffing",
|
477 |
-
"ua",
|
478 |
-
"useragent"
|
479 |
-
]
|
480 |
-
}
|
481 |
-
]
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"name": "composer/ca-bundle",
|
4 |
+
"version": "1.1.3",
|
5 |
+
"version_normalized": "1.1.3.0",
|
6 |
+
"source": {
|
7 |
+
"type": "git",
|
8 |
+
"url": "https://github.com/composer/ca-bundle.git",
|
9 |
+
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660"
|
10 |
+
},
|
11 |
+
"dist": {
|
12 |
+
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/8afa52cd417f4ec417b4bfe86b68106538a87660",
|
14 |
+
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660",
|
15 |
+
"shasum": ""
|
16 |
+
},
|
17 |
+
"require": {
|
18 |
+
"ext-openssl": "*",
|
19 |
+
"ext-pcre": "*",
|
20 |
+
"php": "^5.3.2 || ^7.0"
|
21 |
+
},
|
22 |
+
"require-dev": {
|
23 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
24 |
+
"psr/log": "^1.0",
|
25 |
+
"symfony/process": "^2.5 || ^3.0 || ^4.0"
|
26 |
+
},
|
27 |
+
"time": "2018-10-18T06:09:13+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": "erusev/parsedown",
|
62 |
+
"version": "1.7.1",
|
63 |
+
"version_normalized": "1.7.1.0",
|
64 |
+
"source": {
|
65 |
+
"type": "git",
|
66 |
+
"url": "https://github.com/erusev/parsedown.git",
|
67 |
+
"reference": "92e9c27ba0e74b8b028b111d1b6f956a15c01fc1"
|
68 |
+
},
|
69 |
+
"dist": {
|
70 |
+
"type": "zip",
|
71 |
+
"url": "https://api.github.com/repos/erusev/parsedown/zipball/92e9c27ba0e74b8b028b111d1b6f956a15c01fc1",
|
72 |
+
"reference": "92e9c27ba0e74b8b028b111d1b6f956a15c01fc1",
|
73 |
+
"shasum": ""
|
74 |
+
},
|
75 |
+
"require": {
|
76 |
+
"ext-mbstring": "*",
|
77 |
+
"php": ">=5.3.0"
|
78 |
+
},
|
79 |
+
"require-dev": {
|
80 |
+
"phpunit/phpunit": "^4.8.35"
|
81 |
+
},
|
82 |
+
"time": "2018-03-08T01:11:30+00:00",
|
83 |
+
"type": "library",
|
84 |
+
"installation-source": "dist",
|
85 |
+
"autoload": {
|
86 |
+
"psr-0": {
|
87 |
+
"Parsedown": ""
|
88 |
+
}
|
89 |
+
},
|
90 |
+
"notification-url": "https://packagist.org/downloads/",
|
91 |
+
"license": [
|
92 |
+
"MIT"
|
93 |
+
],
|
94 |
+
"authors": [
|
95 |
+
{
|
96 |
+
"name": "Emanuil Rusev",
|
97 |
+
"email": "hello@erusev.com",
|
98 |
+
"homepage": "http://erusev.com"
|
99 |
+
}
|
100 |
+
],
|
101 |
+
"description": "Parser for Markdown.",
|
102 |
+
"homepage": "http://parsedown.org",
|
103 |
+
"keywords": [
|
104 |
+
"markdown",
|
105 |
+
"parser"
|
106 |
+
]
|
107 |
+
},
|
108 |
+
{
|
109 |
+
"name": "geoip2/geoip2",
|
110 |
+
"version": "v2.9.0",
|
111 |
+
"version_normalized": "2.9.0.0",
|
112 |
+
"source": {
|
113 |
+
"type": "git",
|
114 |
+
"url": "https://github.com/maxmind/GeoIP2-php.git",
|
115 |
+
"reference": "a807fbf65212eef5d8d2db1a1b31082b53633d77"
|
116 |
+
},
|
117 |
+
"dist": {
|
118 |
+
"type": "zip",
|
119 |
+
"url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/a807fbf65212eef5d8d2db1a1b31082b53633d77",
|
120 |
+
"reference": "a807fbf65212eef5d8d2db1a1b31082b53633d77",
|
121 |
+
"shasum": ""
|
122 |
+
},
|
123 |
+
"require": {
|
124 |
+
"maxmind-db/reader": "~1.0",
|
125 |
+
"maxmind/web-service-common": "~0.5",
|
126 |
+
"php": ">=5.4"
|
127 |
+
},
|
128 |
+
"require-dev": {
|
129 |
+
"friendsofphp/php-cs-fixer": "2.*",
|
130 |
+
"phpunit/phpunit": "4.*",
|
131 |
+
"squizlabs/php_codesniffer": "3.*"
|
132 |
+
},
|
133 |
+
"time": "2018-04-10T15:32:59+00:00",
|
134 |
+
"type": "library",
|
135 |
+
"installation-source": "dist",
|
136 |
+
"autoload": {
|
137 |
+
"psr-4": {
|
138 |
+
"GeoIp2\\": "src"
|
139 |
+
}
|
140 |
+
},
|
141 |
+
"notification-url": "https://packagist.org/downloads/",
|
142 |
+
"license": [
|
143 |
+
"Apache-2.0"
|
144 |
+
],
|
145 |
+
"authors": [
|
146 |
+
{
|
147 |
+
"name": "Gregory J. Oschwald",
|
148 |
+
"email": "goschwald@maxmind.com",
|
149 |
+
"homepage": "http://www.maxmind.com/"
|
150 |
+
}
|
151 |
+
],
|
152 |
+
"description": "MaxMind GeoIP2 PHP API",
|
153 |
+
"homepage": "https://github.com/maxmind/GeoIP2-php",
|
154 |
+
"keywords": [
|
155 |
+
"IP",
|
156 |
+
"geoip",
|
157 |
+
"geoip2",
|
158 |
+
"geolocation",
|
159 |
+
"maxmind"
|
160 |
+
]
|
161 |
+
},
|
162 |
+
{
|
163 |
+
"name": "jaybizzle/crawler-detect",
|
164 |
+
"version": "v1.2.69",
|
165 |
+
"version_normalized": "1.2.69.0",
|
166 |
+
"source": {
|
167 |
+
"type": "git",
|
168 |
+
"url": "https://github.com/JayBizzle/Crawler-Detect.git",
|
169 |
+
"reference": "bac5e3f342f22477e74c5ba5daf3c3f84370bf20"
|
170 |
+
},
|
171 |
+
"dist": {
|
172 |
+
"type": "zip",
|
173 |
+
"url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/bac5e3f342f22477e74c5ba5daf3c3f84370bf20",
|
174 |
+
"reference": "bac5e3f342f22477e74c5ba5daf3c3f84370bf20",
|
175 |
+
"shasum": ""
|
176 |
+
},
|
177 |
+
"require": {
|
178 |
+
"php": ">=5.3.0"
|
179 |
+
},
|
180 |
+
"require-dev": {
|
181 |
+
"phpunit/phpunit": "^4.8|^5.5|^6.5",
|
182 |
+
"satooshi/php-coveralls": "1.*"
|
183 |
+
},
|
184 |
+
"time": "2018-10-03T08:53:34+00:00",
|
185 |
+
"type": "library",
|
186 |
+
"installation-source": "dist",
|
187 |
+
"autoload": {
|
188 |
+
"psr-4": {
|
189 |
+
"Jaybizzle\\CrawlerDetect\\": "src/"
|
190 |
+
}
|
191 |
+
},
|
192 |
+
"notification-url": "https://packagist.org/downloads/",
|
193 |
+
"license": [
|
194 |
+
"MIT"
|
195 |
+
],
|
196 |
+
"authors": [
|
197 |
+
{
|
198 |
+
"name": "Mark Beech",
|
199 |
+
"email": "m@rkbee.ch",
|
200 |
+
"role": "Developer"
|
201 |
+
}
|
202 |
+
],
|
203 |
+
"description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent",
|
204 |
+
"homepage": "https://github.com/JayBizzle/Crawler-Detect/",
|
205 |
+
"keywords": [
|
206 |
+
"crawler",
|
207 |
+
"crawler detect",
|
208 |
+
"crawler detector",
|
209 |
+
"crawlerdetect",
|
210 |
+
"php crawler detect"
|
211 |
+
]
|
212 |
+
},
|
213 |
+
{
|
214 |
+
"name": "maxmind-db/reader",
|
215 |
+
"version": "v1.3.0",
|
216 |
+
"version_normalized": "1.3.0.0",
|
217 |
+
"source": {
|
218 |
+
"type": "git",
|
219 |
+
"url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
|
220 |
+
"reference": "e042b4f8a2dff41e19019faf16427178b07fbd58"
|
221 |
+
},
|
222 |
+
"dist": {
|
223 |
+
"type": "zip",
|
224 |
+
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/e042b4f8a2dff41e19019faf16427178b07fbd58",
|
225 |
+
"reference": "e042b4f8a2dff41e19019faf16427178b07fbd58",
|
226 |
+
"shasum": ""
|
227 |
+
},
|
228 |
+
"require": {
|
229 |
+
"php": ">=5.4"
|
230 |
+
},
|
231 |
+
"require-dev": {
|
232 |
+
"friendsofphp/php-cs-fixer": "2.*",
|
233 |
+
"phpunit/phpunit": "4.* || 5.*",
|
234 |
+
"satooshi/php-coveralls": "1.0.*",
|
235 |
+
"squizlabs/php_codesniffer": "3.*"
|
236 |
+
},
|
237 |
+
"suggest": {
|
238 |
+
"ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
239 |
+
"ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
240 |
+
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
|
241 |
+
},
|
242 |
+
"time": "2018-02-21T21:23:33+00:00",
|
243 |
+
"type": "library",
|
244 |
+
"installation-source": "dist",
|
245 |
+
"autoload": {
|
246 |
+
"psr-4": {
|
247 |
+
"MaxMind\\Db\\": "src/MaxMind/Db"
|
248 |
+
}
|
249 |
+
},
|
250 |
+
"notification-url": "https://packagist.org/downloads/",
|
251 |
+
"license": [
|
252 |
+
"Apache-2.0"
|
253 |
+
],
|
254 |
+
"authors": [
|
255 |
+
{
|
256 |
+
"name": "Gregory J. Oschwald",
|
257 |
+
"email": "goschwald@maxmind.com",
|
258 |
+
"homepage": "http://www.maxmind.com/"
|
259 |
+
}
|
260 |
+
],
|
261 |
+
"description": "MaxMind DB Reader API",
|
262 |
+
"homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
|
263 |
+
"keywords": [
|
264 |
+
"database",
|
265 |
+
"geoip",
|
266 |
+
"geoip2",
|
267 |
+
"geolocation",
|
268 |
+
"maxmind"
|
269 |
+
]
|
270 |
+
},
|
271 |
+
{
|
272 |
+
"name": "maxmind/web-service-common",
|
273 |
+
"version": "v0.5.0",
|
274 |
+
"version_normalized": "0.5.0.0",
|
275 |
+
"source": {
|
276 |
+
"type": "git",
|
277 |
+
"url": "https://github.com/maxmind/web-service-common-php.git",
|
278 |
+
"reference": "61a9836fa3bb1743ab89752bae5005d71e78c73b"
|
279 |
+
},
|
280 |
+
"dist": {
|
281 |
+
"type": "zip",
|
282 |
+
"url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/61a9836fa3bb1743ab89752bae5005d71e78c73b",
|
283 |
+
"reference": "61a9836fa3bb1743ab89752bae5005d71e78c73b",
|
284 |
+
"shasum": ""
|
285 |
+
},
|
286 |
+
"require": {
|
287 |
+
"composer/ca-bundle": "^1.0.3",
|
288 |
+
"ext-curl": "*",
|
289 |
+
"ext-json": "*",
|
290 |
+
"php": ">=5.4"
|
291 |
+
},
|
292 |
+
"require-dev": {
|
293 |
+
"friendsofphp/php-cs-fixer": "2.*",
|
294 |
+
"phpunit/phpunit": "4.*",
|
295 |
+
"squizlabs/php_codesniffer": "3.*"
|
296 |
+
},
|
297 |
+
"time": "2018-02-12T22:31:54+00:00",
|
298 |
+
"type": "library",
|
299 |
+
"installation-source": "dist",
|
300 |
+
"autoload": {
|
301 |
+
"psr-4": {
|
302 |
+
"MaxMind\\Exception\\": "src/Exception",
|
303 |
+
"MaxMind\\WebService\\": "src/WebService"
|
304 |
+
}
|
305 |
+
},
|
306 |
+
"notification-url": "https://packagist.org/downloads/",
|
307 |
+
"license": [
|
308 |
+
"Apache-2.0"
|
309 |
+
],
|
310 |
+
"authors": [
|
311 |
+
{
|
312 |
+
"name": "Gregory Oschwald",
|
313 |
+
"email": "goschwald@maxmind.com"
|
314 |
+
}
|
315 |
+
],
|
316 |
+
"description": "Internal MaxMind Web Service API",
|
317 |
+
"homepage": "https://github.com/maxmind/web-service-common-php"
|
318 |
+
},
|
319 |
+
{
|
320 |
+
"name": "psr/cache",
|
321 |
+
"version": "1.0.1",
|
322 |
+
"version_normalized": "1.0.1.0",
|
323 |
+
"source": {
|
324 |
+
"type": "git",
|
325 |
+
"url": "https://github.com/php-fig/cache.git",
|
326 |
+
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
|
327 |
+
},
|
328 |
+
"dist": {
|
329 |
+
"type": "zip",
|
330 |
+
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
|
331 |
+
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
|
332 |
+
"shasum": ""
|
333 |
+
},
|
334 |
+
"require": {
|
335 |
+
"php": ">=5.3.0"
|
336 |
+
},
|
337 |
+
"time": "2016-08-06T20:24:11+00:00",
|
338 |
+
"type": "library",
|
339 |
+
"extra": {
|
340 |
+
"branch-alias": {
|
341 |
+
"dev-master": "1.0.x-dev"
|
342 |
+
}
|
343 |
+
},
|
344 |
+
"installation-source": "dist",
|
345 |
+
"autoload": {
|
346 |
+
"psr-4": {
|
347 |
+
"Psr\\Cache\\": "src/"
|
348 |
+
}
|
349 |
+
},
|
350 |
+
"notification-url": "https://packagist.org/downloads/",
|
351 |
+
"license": [
|
352 |
+
"MIT"
|
353 |
+
],
|
354 |
+
"authors": [
|
355 |
+
{
|
356 |
+
"name": "PHP-FIG",
|
357 |
+
"homepage": "http://www.php-fig.org/"
|
358 |
+
}
|
359 |
+
],
|
360 |
+
"description": "Common interface for caching libraries",
|
361 |
+
"keywords": [
|
362 |
+
"cache",
|
363 |
+
"psr",
|
364 |
+
"psr-6"
|
365 |
+
]
|
366 |
+
},
|
367 |
+
{
|
368 |
+
"name": "s1lentium/iptools",
|
369 |
+
"version": "v1.1.1",
|
370 |
+
"version_normalized": "1.1.1.0",
|
371 |
+
"source": {
|
372 |
+
"type": "git",
|
373 |
+
"url": "https://github.com/S1lentium/IPTools.git",
|
374 |
+
"reference": "f6f8ab6132ca7443bd7cced1681f5066d725fd5f"
|
375 |
+
},
|
376 |
+
"dist": {
|
377 |
+
"type": "zip",
|
378 |
+
"url": "https://api.github.com/repos/S1lentium/IPTools/zipball/f6f8ab6132ca7443bd7cced1681f5066d725fd5f",
|
379 |
+
"reference": "f6f8ab6132ca7443bd7cced1681f5066d725fd5f",
|
380 |
+
"shasum": ""
|
381 |
+
},
|
382 |
+
"require": {
|
383 |
+
"ext-bcmath": "*",
|
384 |
+
"php": ">=5.4.0"
|
385 |
+
},
|
386 |
+
"require-dev": {
|
387 |
+
"phpunit/phpunit": "~4.0",
|
388 |
+
"satooshi/php-coveralls": "~1.0"
|
389 |
+
},
|
390 |
+
"time": "2018-09-19T06:15:53+00:00",
|
391 |
+
"type": "library",
|
392 |
+
"installation-source": "dist",
|
393 |
+
"autoload": {
|
394 |
+
"psr-4": {
|
395 |
+
"IPTools\\": "src/"
|
396 |
+
}
|
397 |
+
},
|
398 |
+
"notification-url": "https://packagist.org/downloads/",
|
399 |
+
"license": [
|
400 |
+
"MIT"
|
401 |
+
],
|
402 |
+
"authors": [
|
403 |
+
{
|
404 |
+
"name": "Safarov Alisher",
|
405 |
+
"email": "alisher.safarov@outlook.com",
|
406 |
+
"homepage": "https://github.com/S1lentium"
|
407 |
+
}
|
408 |
+
],
|
409 |
+
"description": "PHP Library for manipulating network addresses (IPv4 and IPv6)",
|
410 |
+
"keywords": [
|
411 |
+
"IP",
|
412 |
+
"IP-Tools",
|
413 |
+
"cidr",
|
414 |
+
"ipv4",
|
415 |
+
"ipv6",
|
416 |
+
"network",
|
417 |
+
"subnet"
|
418 |
+
]
|
419 |
+
},
|
420 |
+
{
|
421 |
+
"name": "whichbrowser/parser",
|
422 |
+
"version": "v2.0.37",
|
423 |
+
"version_normalized": "2.0.37.0",
|
424 |
+
"source": {
|
425 |
+
"type": "git",
|
426 |
+
"url": "https://github.com/WhichBrowser/Parser-PHP.git",
|
427 |
+
"reference": "9c6ad8eadc23294b1c66d92876c11f13c5d4cf48"
|
428 |
+
},
|
429 |
+
"dist": {
|
430 |
+
"type": "zip",
|
431 |
+
"url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/9c6ad8eadc23294b1c66d92876c11f13c5d4cf48",
|
432 |
+
"reference": "9c6ad8eadc23294b1c66d92876c11f13c5d4cf48",
|
433 |
+
"shasum": ""
|
434 |
+
},
|
435 |
+
"require": {
|
436 |
+
"php": ">=5.4.0",
|
437 |
+
"psr/cache": "^1.0"
|
438 |
+
},
|
439 |
+
"require-dev": {
|
440 |
+
"icomefromthenet/reverse-regex": "0.0.6.3",
|
441 |
+
"phpunit/php-code-coverage": "^2.2|^3.0",
|
442 |
+
"phpunit/phpunit": "^4.0|^5.0",
|
443 |
+
"satooshi/php-coveralls": "^1.0",
|
444 |
+
"squizlabs/php_codesniffer": "2.5.*",
|
445 |
+
"symfony/yaml": ">=2.8"
|
446 |
+
},
|
447 |
+
"suggest": {
|
448 |
+
"cache/array-adapter": "Allows testing of the caching functionality"
|
449 |
+
},
|
450 |
+
"time": "2018-10-02T09:26:41+00:00",
|
451 |
+
"type": "library",
|
452 |
+
"installation-source": "dist",
|
453 |
+
"autoload": {
|
454 |
+
"psr-4": {
|
455 |
+
"WhichBrowser\\": [
|
456 |
+
"src/",
|
457 |
+
"tests/src/"
|
458 |
+
]
|
459 |
+
}
|
460 |
+
},
|
461 |
+
"notification-url": "https://packagist.org/downloads/",
|
462 |
+
"license": [
|
463 |
+
"MIT"
|
464 |
+
],
|
465 |
+
"authors": [
|
466 |
+
{
|
467 |
+
"name": "Niels Leenheer",
|
468 |
+
"email": "niels@leenheer.nl",
|
469 |
+
"role": "Developer"
|
470 |
+
}
|
471 |
+
],
|
472 |
+
"description": "Useragent sniffing library for PHP",
|
473 |
+
"homepage": "http://whichbrowser.net",
|
474 |
+
"keywords": [
|
475 |
+
"browser",
|
476 |
+
"sniffing",
|
477 |
+
"ua",
|
478 |
+
"useragent"
|
479 |
+
]
|
480 |
+
}
|
481 |
+
]
|
includes/vendor/erusev/parsedown/LICENSE.txt
CHANGED
@@ -1,20 +1,20 @@
|
|
1 |
-
The MIT License (MIT)
|
2 |
-
|
3 |
-
Copyright (c) 2013-2018 Emanuil Rusev, erusev.com
|
4 |
-
|
5 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6 |
-
this software and associated documentation files (the "Software"), to deal in
|
7 |
-
the Software without restriction, including without limitation the rights to
|
8 |
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9 |
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
10 |
-
subject to the following conditions:
|
11 |
-
|
12 |
-
The above copyright notice and this permission notice shall be included in all
|
13 |
-
copies or substantial portions of the Software.
|
14 |
-
|
15 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17 |
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18 |
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19 |
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20 |
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1 |
+
The MIT License (MIT)
|
2 |
+
|
3 |
+
Copyright (c) 2013-2018 Emanuil Rusev, erusev.com
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6 |
+
this software and associated documentation files (the "Software"), to deal in
|
7 |
+
the Software without restriction, including without limitation the rights to
|
8 |
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9 |
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10 |
+
subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17 |
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18 |
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19 |
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20 |
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
includes/vendor/erusev/parsedown/Parsedown.php
CHANGED
@@ -1,1679 +1,1679 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
#
|
4 |
-
#
|
5 |
-
# Parsedown
|
6 |
-
# http://parsedown.org
|
7 |
-
#
|
8 |
-
# (c) Emanuil Rusev
|
9 |
-
# http://erusev.com
|
10 |
-
#
|
11 |
-
# For the full license information, view the LICENSE file that was distributed
|
12 |
-
# with this source code.
|
13 |
-
#
|
14 |
-
#
|
15 |
-
|
16 |
-
class Parsedown
|
17 |
-
{
|
18 |
-
# ~
|
19 |
-
|
20 |
-
const version = '1.7.1';
|
21 |
-
|
22 |
-
# ~
|
23 |
-
|
24 |
-
function text($text)
|
25 |
-
{
|
26 |
-
# make sure no definitions are set
|
27 |
-
$this->DefinitionData = array();
|
28 |
-
|
29 |
-
# standardize line breaks
|
30 |
-
$text = str_replace(array("\r\n", "\r"), "\n", $text);
|
31 |
-
|
32 |
-
# remove surrounding line breaks
|
33 |
-
$text = trim($text, "\n");
|
34 |
-
|
35 |
-
# split text into lines
|
36 |
-
$lines = explode("\n", $text);
|
37 |
-
|
38 |
-
# iterate through lines to identify blocks
|
39 |
-
$markup = $this->lines($lines);
|
40 |
-
|
41 |
-
# trim line breaks
|
42 |
-
$markup = trim($markup, "\n");
|
43 |
-
|
44 |
-
return $markup;
|
45 |
-
}
|
46 |
-
|
47 |
-
#
|
48 |
-
# Setters
|
49 |
-
#
|
50 |
-
|
51 |
-
function setBreaksEnabled($breaksEnabled)
|
52 |
-
{
|
53 |
-
$this->breaksEnabled = $breaksEnabled;
|
54 |
-
|
55 |
-
return $this;
|
56 |
-
}
|
57 |
-
|
58 |
-
protected $breaksEnabled;
|
59 |
-
|
60 |
-
function setMarkupEscaped($markupEscaped)
|
61 |
-
{
|
62 |
-
$this->markupEscaped = $markupEscaped;
|
63 |
-
|
64 |
-
return $this;
|
65 |
-
}
|
66 |
-
|
67 |
-
protected $markupEscaped;
|
68 |
-
|
69 |
-
function setUrlsLinked($urlsLinked)
|
70 |
-
{
|
71 |
-
$this->urlsLinked = $urlsLinked;
|
72 |
-
|
73 |
-
return $this;
|
74 |
-
}
|
75 |
-
|
76 |
-
protected $urlsLinked = true;
|
77 |
-
|
78 |
-
function setSafeMode($safeMode)
|
79 |
-
{
|
80 |
-
$this->safeMode = (bool) $safeMode;
|
81 |
-
|
82 |
-
return $this;
|
83 |
-
}
|
84 |
-
|
85 |
-
protected $safeMode;
|
86 |
-
|
87 |
-
protected $safeLinksWhitelist = array(
|
88 |
-
'http://',
|
89 |
-
'https://',
|
90 |
-
'ftp://',
|
91 |
-
'ftps://',
|
92 |
-
'mailto:',
|
93 |
-
'data:image/png;base64,',
|
94 |
-
'data:image/gif;base64,',
|
95 |
-
'data:image/jpeg;base64,',
|
96 |
-
'irc:',
|
97 |
-
'ircs:',
|
98 |
-
'git:',
|
99 |
-
'ssh:',
|
100 |
-
'news:',
|
101 |
-
'steam:',
|
102 |
-
);
|
103 |
-
|
104 |
-
#
|
105 |
-
# Lines
|
106 |
-
#
|
107 |
-
|
108 |
-
protected $BlockTypes = array(
|
109 |
-
'#' => array('Header'),
|
110 |
-
'*' => array('Rule', 'List'),
|
111 |
-
'+' => array('List'),
|
112 |
-
'-' => array('SetextHeader', 'Table', 'Rule', 'List'),
|
113 |
-
'0' => array('List'),
|
114 |
-
'1' => array('List'),
|
115 |
-
'2' => array('List'),
|
116 |
-
'3' => array('List'),
|
117 |
-
'4' => array('List'),
|
118 |
-
'5' => array('List'),
|
119 |
-
'6' => array('List'),
|
120 |
-
'7' => array('List'),
|
121 |
-
'8' => array('List'),
|
122 |
-
'9' => array('List'),
|
123 |
-
':' => array('Table'),
|
124 |
-
'<' => array('Comment', 'Markup'),
|
125 |
-
'=' => array('SetextHeader'),
|
126 |
-
'>' => array('Quote'),
|
127 |
-
'[' => array('Reference'),
|
128 |
-
'_' => array('Rule'),
|
129 |
-
'`' => array('FencedCode'),
|
130 |
-
'|' => array('Table'),
|
131 |
-
'~' => array('FencedCode'),
|
132 |
-
);
|
133 |
-
|
134 |
-
# ~
|
135 |
-
|
136 |
-
protected $unmarkedBlockTypes = array(
|
137 |
-
'Code',
|
138 |
-
);
|
139 |
-
|
140 |
-
#
|
141 |
-
# Blocks
|
142 |
-
#
|
143 |
-
|
144 |
-
protected function lines(array $lines)
|
145 |
-
{
|
146 |
-
$CurrentBlock = null;
|
147 |
-
|
148 |
-
foreach ($lines as $line)
|
149 |
-
{
|
150 |
-
if (chop($line) === '')
|
151 |
-
{
|
152 |
-
if (isset($CurrentBlock))
|
153 |
-
{
|
154 |
-
$CurrentBlock['interrupted'] = true;
|
155 |
-
}
|
156 |
-
|
157 |
-
continue;
|
158 |
-
}
|
159 |
-
|
160 |
-
if (strpos($line, "\t") !== false)
|
161 |
-
{
|
162 |
-
$parts = explode("\t", $line);
|
163 |
-
|
164 |
-
$line = $parts[0];
|
165 |
-
|
166 |
-
unset($parts[0]);
|
167 |
-
|
168 |
-
foreach ($parts as $part)
|
169 |
-
{
|
170 |
-
$shortage = 4 - mb_strlen($line, 'utf-8') % 4;
|
171 |
-
|
172 |
-
$line .= str_repeat(' ', $shortage);
|
173 |
-
$line .= $part;
|
174 |
-
}
|
175 |
-
}
|
176 |
-
|
177 |
-
$indent = 0;
|
178 |
-
|
179 |
-
while (isset($line[$indent]) and $line[$indent] === ' ')
|
180 |
-
{
|
181 |
-
$indent ++;
|
182 |
-
}
|
183 |
-
|
184 |
-
$text = $indent > 0 ? substr($line, $indent) : $line;
|
185 |
-
|
186 |
-
# ~
|
187 |
-
|
188 |
-
$Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
|
189 |
-
|
190 |
-
# ~
|
191 |
-
|
192 |
-
if (isset($CurrentBlock['continuable']))
|
193 |
-
{
|
194 |
-
$Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
|
195 |
-
|
196 |
-
if (isset($Block))
|
197 |
-
{
|
198 |
-
$CurrentBlock = $Block;
|
199 |
-
|
200 |
-
continue;
|
201 |
-
}
|
202 |
-
else
|
203 |
-
{
|
204 |
-
if ($this->isBlockCompletable($CurrentBlock['type']))
|
205 |
-
{
|
206 |
-
$CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
|
207 |
-
}
|
208 |
-
}
|
209 |
-
}
|
210 |
-
|
211 |
-
# ~
|
212 |
-
|
213 |
-
$marker = $text[0];
|
214 |
-
|
215 |
-
# ~
|
216 |
-
|
217 |
-
$blockTypes = $this->unmarkedBlockTypes;
|
218 |
-
|
219 |
-
if (isset($this->BlockTypes[$marker]))
|
220 |
-
{
|
221 |
-
foreach ($this->BlockTypes[$marker] as $blockType)
|
222 |
-
{
|
223 |
-
$blockTypes []= $blockType;
|
224 |
-
}
|
225 |
-
}
|
226 |
-
|
227 |
-
#
|
228 |
-
# ~
|
229 |
-
|
230 |
-
foreach ($blockTypes as $blockType)
|
231 |
-
{
|
232 |
-
$Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
|
233 |
-
|
234 |
-
if (isset($Block))
|
235 |
-
{
|
236 |
-
$Block['type'] = $blockType;
|
237 |
-
|
238 |
-
if ( ! isset($Block['identified']))
|
239 |
-
{
|
240 |
-
$Blocks []= $CurrentBlock;
|
241 |
-
|
242 |
-
$Block['identified'] = true;
|
243 |
-
}
|
244 |
-
|
245 |
-
if ($this->isBlockContinuable($blockType))
|
246 |
-
{
|
247 |
-
$Block['continuable'] = true;
|
248 |
-
}
|
249 |
-
|
250 |
-
$CurrentBlock = $Block;
|
251 |
-
|
252 |
-
continue 2;
|
253 |
-
}
|
254 |
-
}
|
255 |
-
|
256 |
-
# ~
|
257 |
-
|
258 |
-
if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
|
259 |
-
{
|
260 |
-
$CurrentBlock['element']['text'] .= "\n".$text;
|
261 |
-
}
|
262 |
-
else
|
263 |
-
{
|
264 |
-
$Blocks []= $CurrentBlock;
|
265 |
-
|
266 |
-
$CurrentBlock = $this->paragraph($Line);
|
267 |
-
|
268 |
-
$CurrentBlock['identified'] = true;
|
269 |
-
}
|
270 |
-
}
|
271 |
-
|
272 |
-
# ~
|
273 |
-
|
274 |
-
if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))
|
275 |
-
{
|
276 |
-
$CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
|
277 |
-
}
|
278 |
-
|
279 |
-
# ~
|
280 |
-
|
281 |
-
$Blocks []= $CurrentBlock;
|
282 |
-
|
283 |
-
unset($Blocks[0]);
|
284 |
-
|
285 |
-
# ~
|
286 |
-
|
287 |
-
$markup = '';
|
288 |
-
|
289 |
-
foreach ($Blocks as $Block)
|
290 |
-
{
|
291 |
-
if (isset($Block['hidden']))
|
292 |
-
{
|
293 |
-
continue;
|
294 |
-
}
|
295 |
-
|
296 |
-
$markup .= "\n";
|
297 |
-
$markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
|
298 |
-
}
|
299 |
-
|
300 |
-
$markup .= "\n";
|
301 |
-
|
302 |
-
# ~
|
303 |
-
|
304 |
-
return $markup;
|
305 |
-
}
|
306 |
-
|
307 |
-
protected function isBlockContinuable($Type)
|
308 |
-
{
|
309 |
-
return method_exists($this, 'block'.$Type.'Continue');
|
310 |
-
}
|
311 |
-
|
312 |
-
protected function isBlockCompletable($Type)
|
313 |
-
{
|
314 |
-
return method_exists($this, 'block'.$Type.'Complete');
|
315 |
-
}
|
316 |
-
|
317 |
-
#
|
318 |
-
# Code
|
319 |
-
|
320 |
-
protected function blockCode($Line, $Block = null)
|
321 |
-
{
|
322 |
-
if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
|
323 |
-
{
|
324 |
-
return;
|
325 |
-
}
|
326 |
-
|
327 |
-
if ($Line['indent'] >= 4)
|
328 |
-
{
|
329 |
-
$text = substr($Line['body'], 4);
|
330 |
-
|
331 |
-
$Block = array(
|
332 |
-
'element' => array(
|
333 |
-
'name' => 'pre',
|
334 |
-
'handler' => 'element',
|
335 |
-
'text' => array(
|
336 |
-
'name' => 'code',
|
337 |
-
'text' => $text,
|
338 |
-
),
|
339 |
-
),
|
340 |
-
);
|
341 |
-
|
342 |
-
return $Block;
|
343 |
-
}
|
344 |
-
}
|
345 |
-
|
346 |
-
protected function blockCodeContinue($Line, $Block)
|
347 |
-
{
|
348 |
-
if ($Line['indent'] >= 4)
|
349 |
-
{
|
350 |
-
if (isset($Block['interrupted']))
|
351 |
-
{
|
352 |
-
$Block['element']['text']['text'] .= "\n";
|
353 |
-
|
354 |
-
unset($Block['interrupted']);
|
355 |
-
}
|
356 |
-
|
357 |
-
$Block['element']['text']['text'] .= "\n";
|
358 |
-
|
359 |
-
$text = substr($Line['body'], 4);
|
360 |
-
|
361 |
-
$Block['element']['text']['text'] .= $text;
|
362 |
-
|
363 |
-
return $Block;
|
364 |
-
}
|
365 |
-
}
|
366 |
-
|
367 |
-
protected function blockCodeComplete($Block)
|
368 |
-
{
|
369 |
-
$text = $Block['element']['text']['text'];
|
370 |
-
|
371 |
-
$Block['element']['text']['text'] = $text;
|
372 |
-
|
373 |
-
return $Block;
|
374 |
-
}
|
375 |
-
|
376 |
-
#
|
377 |
-
# Comment
|
378 |
-
|
379 |
-
protected function blockComment($Line)
|
380 |
-
{
|
381 |
-
if ($this->markupEscaped or $this->safeMode)
|
382 |
-
{
|
383 |
-
return;
|
384 |
-
}
|
385 |
-
|
386 |
-
if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
|
387 |
-
{
|
388 |
-
$Block = array(
|
389 |
-
'markup' => $Line['body'],
|
390 |
-
);
|
391 |
-
|
392 |
-
if (preg_match('/-->$/', $Line['text']))
|
393 |
-
{
|
394 |
-
$Block['closed'] = true;
|
395 |
-
}
|
396 |
-
|
397 |
-
return $Block;
|
398 |
-
}
|
399 |
-
}
|
400 |
-
|
401 |
-
protected function blockCommentContinue($Line, array $Block)
|
402 |
-
{
|
403 |
-
if (isset($Block['closed']))
|
404 |
-
{
|
405 |
-
return;
|
406 |
-
}
|
407 |
-
|
408 |
-
$Block['markup'] .= "\n" . $Line['body'];
|
409 |
-
|
410 |
-
if (preg_match('/-->$/', $Line['text']))
|
411 |
-
{
|
412 |
-
$Block['closed'] = true;
|
413 |
-
}
|
414 |
-
|
415 |
-
return $Block;
|
416 |
-
}
|
417 |
-
|
418 |
-
#
|
419 |
-
# Fenced Code
|
420 |
-
|
421 |
-
protected function blockFencedCode($Line)
|
422 |
-
{
|
423 |
-
if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches))
|
424 |
-
{
|
425 |
-
$Element = array(
|
426 |
-
'name' => 'code',
|
427 |
-
'text' => '',
|
428 |
-
);
|
429 |
-
|
430 |
-
if (isset($matches[1]))
|
431 |
-
{
|
432 |
-
$class = 'language-'.$matches[1];
|
433 |
-
|
434 |
-
$Element['attributes'] = array(
|
435 |
-
'class' => $class,
|
436 |
-
);
|
437 |
-
}
|
438 |
-
|
439 |
-
$Block = array(
|
440 |
-
'char' => $Line['text'][0],
|
441 |
-
'element' => array(
|
442 |
-
'name' => 'pre',
|
443 |
-
'handler' => 'element',
|
444 |
-
'text' => $Element,
|
445 |
-
),
|
446 |
-
);
|
447 |
-
|
448 |
-
return $Block;
|
449 |
-
}
|
450 |
-
}
|
451 |
-
|
452 |
-
protected function blockFencedCodeContinue($Line, $Block)
|
453 |
-
{
|
454 |
-
if (isset($Block['complete']))
|
455 |
-
{
|
456 |
-
return;
|
457 |
-
}
|
458 |
-
|
459 |
-
if (isset($Block['interrupted']))
|
460 |
-
{
|
461 |
-
$Block['element']['text']['text'] .= "\n";
|
462 |
-
|
463 |
-
unset($Block['interrupted']);
|
464 |
-
}
|
465 |
-
|
466 |
-
if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
|
467 |
-
{
|
468 |
-
$Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
|
469 |
-
|
470 |
-
$Block['complete'] = true;
|
471 |
-
|
472 |
-
return $Block;
|
473 |
-
}
|
474 |
-
|
475 |
-
$Block['element']['text']['text'] .= "\n".$Line['body'];
|
476 |
-
|
477 |
-
return $Block;
|
478 |
-
}
|
479 |
-
|
480 |
-
protected function blockFencedCodeComplete($Block)
|
481 |
-
{
|
482 |
-
$text = $Block['element']['text']['text'];
|
483 |
-
|
484 |
-
$Block['element']['text']['text'] = $text;
|
485 |
-
|
486 |
-
return $Block;
|
487 |
-
}
|
488 |
-
|
489 |
-
#
|
490 |
-
# Header
|
491 |
-
|
492 |
-
protected function blockHeader($Line)
|
493 |
-
{
|
494 |
-
if (isset($Line['text'][1]))
|
495 |
-
{
|
496 |
-
$level = 1;
|
497 |
-
|
498 |
-
while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
|
499 |
-
{
|
500 |
-
$level ++;
|
501 |
-
}
|
502 |
-
|
503 |
-
if ($level > 6)
|
504 |
-
{
|
505 |
-
return;
|
506 |
-
}
|
507 |
-
|
508 |
-
$text = trim($Line['text'], '# ');
|
509 |
-
|
510 |
-
$Block = array(
|
511 |
-
'element' => array(
|
512 |
-
'name' => 'h' . min(6, $level),
|
513 |
-
'text' => $text,
|
514 |
-
'handler' => 'line',
|
515 |
-
),
|
516 |
-
);
|
517 |
-
|
518 |
-
return $Block;
|
519 |
-
}
|
520 |
-
}
|
521 |
-
|
522 |
-
#
|
523 |
-
# List
|
524 |
-
|
525 |
-
protected function blockList($Line)
|
526 |
-
{
|
527 |
-
list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
|
528 |
-
|
529 |
-
if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
|
530 |
-
{
|
531 |
-
$Block = array(
|
532 |
-
'indent' => $Line['indent'],
|
533 |
-
'pattern' => $pattern,
|
534 |
-
'element' => array(
|
535 |
-
'name' => $name,
|
536 |
-
'handler' => 'elements',
|
537 |
-
),
|
538 |
-
);
|
539 |
-
|
540 |
-
if($name === 'ol')
|
541 |
-
{
|
542 |
-
$listStart = stristr($matches[0], '.', true);
|
543 |
-
|
544 |
-
if($listStart !== '1')
|
545 |
-
{
|
546 |
-
$Block['element']['attributes'] = array('start' => $listStart);
|
547 |
-
}
|
548 |
-
}
|
549 |
-
|
550 |
-
$Block['li'] = array(
|
551 |
-
'name' => 'li',
|
552 |
-
'handler' => 'li',
|
553 |
-
'text' => array(
|
554 |
-
$matches[2],
|
555 |
-
),
|
556 |
-
);
|
557 |
-
|
558 |
-
$Block['element']['text'] []= & $Block['li'];
|
559 |
-
|
560 |
-
return $Block;
|
561 |
-
}
|
562 |
-
}
|
563 |
-
|
564 |
-
protected function blockListContinue($Line, array $Block)
|
565 |
-
{
|
566 |
-
if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
|
567 |
-
{
|
568 |
-
if (isset($Block['interrupted']))
|
569 |
-
{
|
570 |
-
$Block['li']['text'] []= '';
|
571 |
-
|
572 |
-
$Block['loose'] = true;
|
573 |
-
|
574 |
-
unset($Block['interrupted']);
|
575 |
-
}
|
576 |
-
|
577 |
-
unset($Block['li']);
|
578 |
-
|
579 |
-
$text = isset($matches[1]) ? $matches[1] : '';
|
580 |
-
|
581 |
-
$Block['li'] = array(
|
582 |
-
'name' => 'li',
|
583 |
-
'handler' => 'li',
|
584 |
-
'text' => array(
|
585 |
-
$text,
|
586 |
-
),
|
587 |
-
);
|
588 |
-
|
589 |
-
$Block['element']['text'] []= & $Block['li'];
|
590 |
-
|
591 |
-
return $Block;
|
592 |
-
}
|
593 |
-
|
594 |
-
if ($Line['text'][0] === '[' and $this->blockReference($Line))
|
595 |
-
{
|
596 |
-
return $Block;
|
597 |
-
}
|
598 |
-
|
599 |
-
if ( ! isset($Block['interrupted']))
|
600 |
-
{
|
601 |
-
$text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
|
602 |
-
|
603 |
-
$Block['li']['text'] []= $text;
|
604 |
-
|
605 |
-
return $Block;
|
606 |
-
}
|
607 |
-
|
608 |
-
if ($Line['indent'] > 0)
|
609 |
-
{
|
610 |
-
$Block['li']['text'] []= '';
|
611 |
-
|
612 |
-
$text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
|
613 |
-
|
614 |
-
$Block['li']['text'] []= $text;
|
615 |
-
|
616 |
-
unset($Block['interrupted']);
|
617 |
-
|
618 |
-
return $Block;
|
619 |
-
}
|
620 |
-
}
|
621 |
-
|
622 |
-
protected function blockListComplete(array $Block)
|
623 |
-
{
|
624 |
-
if (isset($Block['loose']))
|
625 |
-
{
|
626 |
-
foreach ($Block['element']['text'] as &$li)
|
627 |
-
{
|
628 |
-
if (end($li['text']) !== '')
|
629 |
-
{
|
630 |
-
$li['text'] []= '';
|
631 |
-
}
|
632 |
-
}
|
633 |
-
}
|
634 |
-
|
635 |
-
return $Block;
|
636 |
-
}
|
637 |
-
|
638 |
-
#
|
639 |
-
# Quote
|
640 |
-
|
641 |
-
protected function blockQuote($Line)
|
642 |
-
{
|
643 |
-
if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
|
644 |
-
{
|
645 |
-
$Block = array(
|
646 |
-
'element' => array(
|
647 |
-
'name' => 'blockquote',
|
648 |
-
'handler' => 'lines',
|
649 |
-
'text' => (array) $matches[1],
|
650 |
-
),
|
651 |
-
);
|
652 |
-
|
653 |
-
return $Block;
|
654 |
-
}
|
655 |
-
}
|
656 |
-
|
657 |
-
protected function blockQuoteContinue($Line, array $Block)
|
658 |
-
{
|
659 |
-
if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
|
660 |
-
{
|
661 |
-
if (isset($Block['interrupted']))
|
662 |
-
{
|
663 |
-
$Block['element']['text'] []= '';
|
664 |
-
|
665 |
-
unset($Block['interrupted']);
|
666 |
-
}
|
667 |
-
|
668 |
-
$Block['element']['text'] []= $matches[1];
|
669 |
-
|
670 |
-
return $Block;
|
671 |
-
}
|
672 |
-
|
673 |
-
if ( ! isset($Block['interrupted']))
|
674 |
-
{
|
675 |
-
$Block['element']['text'] []= $Line['text'];
|
676 |
-
|
677 |
-
return $Block;
|
678 |
-
}
|
679 |
-
}
|
680 |
-
|
681 |
-
#
|
682 |
-
# Rule
|
683 |
-
|
684 |
-
protected function blockRule($Line)
|
685 |
-
{
|
686 |
-
if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
|
687 |
-
{
|
688 |
-
$Block = array(
|
689 |
-
'element' => array(
|
690 |
-
'name' => 'hr'
|
691 |
-
),
|
692 |
-
);
|
693 |
-
|
694 |
-
return $Block;
|
695 |
-
}
|
696 |
-
}
|
697 |
-
|
698 |
-
#
|
699 |
-
# Setext
|
700 |
-
|
701 |
-
protected function blockSetextHeader($Line, array $Block = null)
|
702 |
-
{
|
703 |
-
if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
|
704 |
-
{
|
705 |
-
return;
|
706 |
-
}
|
707 |
-
|
708 |
-
if (chop($Line['text'], $Line['text'][0]) === '')
|
709 |
-
{
|
710 |
-
$Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
|
711 |
-
|
712 |
-
return $Block;
|
713 |
-
}
|
714 |
-
}
|
715 |
-
|
716 |
-
#
|
717 |
-
# Markup
|
718 |
-
|
719 |
-
protected function blockMarkup($Line)
|
720 |
-
{
|
721 |
-
if ($this->markupEscaped or $this->safeMode)
|
722 |
-
{
|
723 |
-
return;
|
724 |
-
}
|
725 |
-
|
726 |
-
if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
|
727 |
-
{
|
728 |
-
$element = strtolower($matches[1]);
|
729 |
-
|
730 |
-
if (in_array($element, $this->textLevelElements))
|
731 |
-
{
|
732 |
-
return;
|
733 |
-
}
|
734 |
-
|
735 |
-
$Block = array(
|
736 |
-
'name' => $matches[1],
|
737 |
-
'depth' => 0,
|
738 |
-
'markup' => $Line['text'],
|
739 |
-
);
|
740 |
-
|
741 |
-
$length = strlen($matches[0]);
|
742 |
-
|
743 |
-
$remainder = substr($Line['text'], $length);
|
744 |
-
|
745 |
-
if (trim($remainder) === '')
|
746 |
-
{
|
747 |
-
if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
|
748 |
-
{
|
749 |
-
$Block['closed'] = true;
|
750 |
-
|
751 |
-
$Block['void'] = true;
|
752 |
-
}
|
753 |
-
}
|
754 |
-
else
|
755 |
-
{
|
756 |
-
if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
|
757 |
-
{
|
758 |
-
return;
|
759 |
-
}
|
760 |
-
|
761 |
-
if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
|
762 |
-
{
|
763 |
-
$Block['closed'] = true;
|
764 |
-
}
|
765 |
-
}
|
766 |
-
|
767 |
-
return $Block;
|
768 |
-
}
|
769 |
-
}
|
770 |
-
|
771 |
-
protected function blockMarkupContinue($Line, array $Block)
|
772 |
-
{
|
773 |
-
if (isset($Block['closed']))
|
774 |
-
{
|
775 |
-
return;
|
776 |
-
}
|
777 |
-
|
778 |
-
if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
|
779 |
-
{
|
780 |
-
$Block['depth'] ++;
|
781 |
-
}
|
782 |
-
|
783 |
-
if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
|
784 |
-
{
|
785 |
-
if ($Block['depth'] > 0)
|
786 |
-
{
|
787 |
-
$Block['depth'] --;
|
788 |
-
}
|
789 |
-
else
|
790 |
-
{
|
791 |
-
$Block['closed'] = true;
|
792 |
-
}
|
793 |
-
}
|
794 |
-
|
795 |
-
if (isset($Block['interrupted']))
|
796 |
-
{
|
797 |
-
$Block['markup'] .= "\n";
|
798 |
-
|
799 |
-
unset($Block['interrupted']);
|
800 |
-
}
|
801 |
-
|
802 |
-
$Block['markup'] .= "\n".$Line['body'];
|
803 |
-
|
804 |
-
return $Block;
|
805 |
-
}
|
806 |
-
|
807 |
-
#
|
808 |
-
# Reference
|
809 |
-
|
810 |
-
protected function blockReference($Line)
|
811 |
-
{
|
812 |
-
if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
|
813 |
-
{
|
814 |
-
$id = strtolower($matches[1]);
|
815 |
-
|
816 |
-
$Data = array(
|
817 |
-
'url' => $matches[2],
|
818 |
-
'title' => null,
|
819 |
-
);
|
820 |
-
|
821 |
-
if (isset($matches[3]))
|
822 |
-
{
|
823 |
-
$Data['title'] = $matches[3];
|
824 |
-
}
|
825 |
-
|
826 |
-
$this->DefinitionData['Reference'][$id] = $Data;
|
827 |
-
|
828 |
-
$Block = array(
|
829 |
-
'hidden' => true,
|
830 |
-
);
|
831 |
-
|
832 |
-
return $Block;
|
833 |
-
}
|
834 |
-
}
|
835 |
-
|
836 |
-
#
|
837 |
-
# Table
|
838 |
-
|
839 |
-
protected function blockTable($Line, array $Block = null)
|
840 |
-
{
|
841 |
-
if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
|
842 |
-
{
|
843 |
-
return;
|
844 |
-
}
|
845 |
-
|
846 |
-
if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
|
847 |
-
{
|
848 |
-
$alignments = array();
|
849 |
-
|
850 |
-
$divider = $Line['text'];
|
851 |
-
|
852 |
-
$divider = trim($divider);
|
853 |
-
$divider = trim($divider, '|');
|
854 |
-
|
855 |
-
$dividerCells = explode('|', $divider);
|
856 |
-
|
857 |
-
foreach ($dividerCells as $dividerCell)
|
858 |
-
{
|
859 |
-
$dividerCell = trim($dividerCell);
|
860 |
-
|
861 |
-
if ($dividerCell === '')
|
862 |
-
{
|
863 |
-
continue;
|
864 |
-
}
|
865 |
-
|
866 |
-
$alignment = null;
|
867 |
-
|
868 |
-
if ($dividerCell[0] === ':')
|
869 |
-
{
|
870 |
-
$alignment = 'left';
|
871 |
-
}
|
872 |
-
|
873 |
-
if (substr($dividerCell, - 1) === ':')
|
874 |
-
{
|
875 |
-
$alignment = $alignment === 'left' ? 'center' : 'right';
|
876 |
-
}
|
877 |
-
|
878 |
-
$alignments []= $alignment;
|
879 |
-
}
|
880 |
-
|
881 |
-
# ~
|
882 |
-
|
883 |
-
$HeaderElements = array();
|
884 |
-
|
885 |
-
$header = $Block['element']['text'];
|
886 |
-
|
887 |
-
$header = trim($header);
|
888 |
-
$header = trim($header, '|');
|
889 |
-
|
890 |
-
$headerCells = explode('|', $header);
|
891 |
-
|
892 |
-
foreach ($headerCells as $index => $headerCell)
|
893 |
-
{
|
894 |
-
$headerCell = trim($headerCell);
|
895 |
-
|
896 |
-
$HeaderElement = array(
|
897 |
-
'name' => 'th',
|
898 |
-
'text' => $headerCell,
|
899 |
-
'handler' => 'line',
|
900 |
-
);
|
901 |
-
|
902 |
-
if (isset($alignments[$index]))
|
903 |
-
{
|
904 |
-
$alignment = $alignments[$index];
|
905 |
-
|
906 |
-
$HeaderElement['attributes'] = array(
|
907 |
-
'style' => 'text-align: '.$alignment.';',
|
908 |
-
);
|
909 |
-
}
|
910 |
-
|
911 |
-
$HeaderElements []= $HeaderElement;
|
912 |
-
}
|
913 |
-
|
914 |
-
# ~
|
915 |
-
|
916 |
-
$Block = array(
|
917 |
-
'alignments' => $alignments,
|
918 |
-
'identified' => true,
|
919 |
-
'element' => array(
|
920 |
-
'name' => 'table',
|
921 |
-
'handler' => 'elements',
|
922 |
-
),
|
923 |
-
);
|
924 |
-
|
925 |
-
$Block['element']['text'] []= array(
|
926 |
-
'name' => 'thead',
|
927 |
-
'handler' => 'elements',
|
928 |
-
);
|
929 |
-
|
930 |
-
$Block['element']['text'] []= array(
|
931 |
-
'name' => 'tbody',
|
932 |
-
'handler' => 'elements',
|
933 |
-
'text' => array(),
|
934 |
-
);
|
935 |
-
|
936 |
-
$Block['element']['text'][0]['text'] []= array(
|
937 |
-
'name' => 'tr',
|
938 |
-
'handler' => 'elements',
|
939 |
-
'text' => $HeaderElements,
|
940 |
-
);
|
941 |
-
|
942 |
-
return $Block;
|
943 |
-
}
|
944 |
-
}
|
945 |
-
|
946 |
-
protected function blockTableContinue($Line, array $Block)
|
947 |
-
{
|
948 |
-
if (isset($Block['interrupted']))
|
949 |
-
{
|
950 |
-
return;
|
951 |
-
}
|
952 |
-
|
953 |
-
if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
|
954 |
-
{
|
955 |
-
$Elements = array();
|
956 |
-
|
957 |
-
$row = $Line['text'];
|
958 |
-
|
959 |
-
$row = trim($row);
|
960 |
-
$row = trim($row, '|');
|
961 |
-
|
962 |
-
preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
|
963 |
-
|
964 |
-
foreach ($matches[0] as $index => $cell)
|
965 |
-
{
|
966 |
-
$cell = trim($cell);
|
967 |
-
|
968 |
-
$Element = array(
|
969 |
-
'name' => 'td',
|
970 |
-
'handler' => 'line',
|
971 |
-
'text' => $cell,
|
972 |
-
);
|
973 |
-
|
974 |
-
if (isset($Block['alignments'][$index]))
|
975 |
-
{
|
976 |
-
$Element['attributes'] = array(
|
977 |
-
'style' => 'text-align: '.$Block['alignments'][$index].';',
|
978 |
-
);
|
979 |
-
}
|
980 |
-
|
981 |
-
$Elements []= $Element;
|
982 |
-
}
|
983 |
-
|
984 |
-
$Element = array(
|
985 |
-
'name' => 'tr',
|
986 |
-
'handler' => 'elements',
|
987 |
-
'text' => $Elements,
|
988 |
-
);
|
989 |
-
|
990 |
-
$Block['element']['text'][1]['text'] []= $Element;
|
991 |
-
|
992 |
-
return $Block;
|
993 |
-
}
|
994 |
-
}
|
995 |
-
|
996 |
-
#
|
997 |
-
# ~
|
998 |
-
#
|
999 |
-
|
1000 |
-
protected function paragraph($Line)
|
1001 |
-
{
|
1002 |
-
$Block = array(
|
1003 |
-
'element' => array(
|
1004 |
-
'name' => 'p',
|
1005 |
-
'text' => $Line['text'],
|
1006 |
-
'handler' => 'line',
|
1007 |
-
),
|
1008 |
-
);
|
1009 |
-
|
1010 |
-
return $Block;
|
1011 |
-
}
|
1012 |
-
|
1013 |
-
#
|
1014 |
-
# Inline Elements
|
1015 |
-
#
|
1016 |
-
|
1017 |
-
protected $InlineTypes = array(
|
1018 |
-
'"' => array('SpecialCharacter'),
|
1019 |
-
'!' => array('Image'),
|
1020 |
-
'&' => array('SpecialCharacter'),
|
1021 |
-
'*' => array('Emphasis'),
|
1022 |
-
':' => array('Url'),
|
1023 |
-
'<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
|
1024 |
-
'>' => array('SpecialCharacter'),
|
1025 |
-
'[' => array('Link'),
|
1026 |
-
'_' => array('Emphasis'),
|
1027 |
-
'`' => array('Code'),
|
1028 |
-
'~' => array('Strikethrough'),
|
1029 |
-
'\\' => array('EscapeSequence'),
|
1030 |
-
);
|
1031 |
-
|
1032 |
-
# ~
|
1033 |
-
|
1034 |
-
protected $inlineMarkerList = '!"*_&[:<>`~\\';
|
1035 |
-
|
1036 |
-
#
|
1037 |
-
# ~
|
1038 |
-
#
|
1039 |
-
|
1040 |
-
public function line($text, $nonNestables=array())
|
1041 |
-
{
|
1042 |
-
$markup = '';
|
1043 |
-
|
1044 |
-
# $excerpt is based on the first occurrence of a marker
|
1045 |
-
|
1046 |
-
while ($excerpt = strpbrk($text, $this->inlineMarkerList))
|
1047 |
-
{
|
1048 |
-
$marker = $excerpt[0];
|
1049 |
-
|
1050 |
-
$markerPosition = strpos($text, $marker);
|
1051 |
-
|
1052 |
-
$Excerpt = array('text' => $excerpt, 'context' => $text);
|
1053 |
-
|
1054 |
-
foreach ($this->InlineTypes[$marker] as $inlineType)
|
1055 |
-
{
|
1056 |
-
# check to see if the current inline type is nestable in the current context
|
1057 |
-
|
1058 |
-
if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables))
|
1059 |
-
{
|
1060 |
-
continue;
|
1061 |
-
}
|
1062 |
-
|
1063 |
-
$Inline = $this->{'inline'.$inlineType}($Excerpt);
|
1064 |
-
|
1065 |
-
if ( ! isset($Inline))
|
1066 |
-
{
|
1067 |
-
continue;
|
1068 |
-
}
|
1069 |
-
|
1070 |
-
# makes sure that the inline belongs to "our" marker
|
1071 |
-
|
1072 |
-
if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
|
1073 |
-
{
|
1074 |
-
continue;
|
1075 |
-
}
|
1076 |
-
|
1077 |
-
# sets a default inline position
|
1078 |
-
|
1079 |
-
if ( ! isset($Inline['position']))
|
1080 |
-
{
|
1081 |
-
$Inline['position'] = $markerPosition;
|
1082 |
-
}
|
1083 |
-
|
1084 |
-
# cause the new element to 'inherit' our non nestables
|
1085 |
-
|
1086 |
-
foreach ($nonNestables as $non_nestable)
|
1087 |
-
{
|
1088 |
-
$Inline['element']['nonNestables'][] = $non_nestable;
|
1089 |
-
}
|
1090 |
-
|
1091 |
-
# the text that comes before the inline
|
1092 |
-
$unmarkedText = substr($text, 0, $Inline['position']);
|
1093 |
-
|
1094 |
-
# compile the unmarked text
|
1095 |
-
$markup .= $this->unmarkedText($unmarkedText);
|
1096 |
-
|
1097 |
-
# compile the inline
|
1098 |
-
$markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
|
1099 |
-
|
1100 |
-
# remove the examined text
|
1101 |
-
$text = substr($text, $Inline['position'] + $Inline['extent']);
|
1102 |
-
|
1103 |
-
continue 2;
|
1104 |
-
}
|
1105 |
-
|
1106 |
-
# the marker does not belong to an inline
|
1107 |
-
|
1108 |
-
$unmarkedText = substr($text, 0, $markerPosition + 1);
|
1109 |
-
|
1110 |
-
$markup .= $this->unmarkedText($unmarkedText);
|
1111 |
-
|
1112 |
-
$text = substr($text, $markerPosition + 1);
|
1113 |
-
}
|
1114 |
-
|
1115 |
-
$markup .= $this->unmarkedText($text);
|
1116 |
-
|
1117 |
-
return $markup;
|
1118 |
-
}
|
1119 |
-
|
1120 |
-
#
|
1121 |
-
# ~
|
1122 |
-
#
|
1123 |
-
|
1124 |
-
protected function inlineCode($Excerpt)
|
1125 |
-
{
|
1126 |
-
$marker = $Excerpt['text'][0];
|
1127 |
-
|
1128 |
-
if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
|
1129 |
-
{
|
1130 |
-
$text = $matches[2];
|
1131 |
-
$text = preg_replace("/[ ]*\n/", ' ', $text);
|
1132 |
-
|
1133 |
-
return array(
|
1134 |
-
'extent' => strlen($matches[0]),
|
1135 |
-
'element' => array(
|
1136 |
-
'name' => 'code',
|
1137 |
-
'text' => $text,
|
1138 |
-
),
|
1139 |
-
);
|
1140 |
-
}
|
1141 |
-
}
|
1142 |
-
|
1143 |
-
protected function inlineEmailTag($Excerpt)
|
1144 |
-
{
|
1145 |
-
if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
|
1146 |
-
{
|
1147 |
-
$url = $matches[1];
|
1148 |
-
|
1149 |
-
if ( ! isset($matches[2]))
|
1150 |
-
{
|
1151 |
-
$url = 'mailto:' . $url;
|
1152 |
-
}
|
1153 |
-
|
1154 |
-
return array(
|
1155 |
-
'extent' => strlen($matches[0]),
|
1156 |
-
'element' => array(
|
1157 |
-
'name' => 'a',
|
1158 |
-
'text' => $matches[1],
|
1159 |
-
'attributes' => array(
|
1160 |
-
'href' => $url,
|
1161 |
-
),
|
1162 |
-
),
|
1163 |
-
);
|
1164 |
-
}
|
1165 |
-
}
|
1166 |
-
|
1167 |
-
protected function inlineEmphasis($Excerpt)
|
1168 |
-
{
|
1169 |
-
if ( ! isset($Excerpt['text'][1]))
|
1170 |
-
{
|
1171 |
-
return;
|
1172 |
-
}
|
1173 |
-
|
1174 |
-
$marker = $Excerpt['text'][0];
|
1175 |
-
|
1176 |
-
if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
|
1177 |
-
{
|
1178 |
-
$emphasis = 'strong';
|
1179 |
-
}
|
1180 |
-
elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
|
1181 |
-
{
|
1182 |
-
$emphasis = 'em';
|
1183 |
-
}
|
1184 |
-
else
|
1185 |
-
{
|
1186 |
-
return;
|
1187 |
-
}
|
1188 |
-
|
1189 |
-
return array(
|
1190 |
-
'extent' => strlen($matches[0]),
|
1191 |
-
'element' => array(
|
1192 |
-
'name' => $emphasis,
|
1193 |
-
'handler' => 'line',
|
1194 |
-
'text' => $matches[1],
|
1195 |
-
),
|
1196 |
-
);
|
1197 |
-
}
|
1198 |
-
|
1199 |
-
protected function inlineEscapeSequence($Excerpt)
|
1200 |
-
{
|
1201 |
-
if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
|
1202 |
-
{
|
1203 |
-
return array(
|
1204 |
-
'markup' => $Excerpt['text'][1],
|
1205 |
-
'extent' => 2,
|
1206 |
-
);
|
1207 |
-
}
|
1208 |
-
}
|
1209 |
-
|
1210 |
-
protected function inlineImage($Excerpt)
|
1211 |
-
{
|
1212 |
-
if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
|
1213 |
-
{
|
1214 |
-
return;
|
1215 |
-
}
|
1216 |
-
|
1217 |
-
$Excerpt['text']= substr($Excerpt['text'], 1);
|
1218 |
-
|
1219 |
-
$Link = $this->inlineLink($Excerpt);
|
1220 |
-
|
1221 |
-
if ($Link === null)
|
1222 |
-
{
|
1223 |
-
return;
|
1224 |
-
}
|
1225 |
-
|
1226 |
-
$Inline = array(
|
1227 |
-
'extent' => $Link['extent'] + 1,
|
1228 |
-
'element' => array(
|
1229 |
-
'name' => 'img',
|
1230 |
-
'attributes' => array(
|
1231 |
-
'src' => $Link['element']['attributes']['href'],
|
1232 |
-
'alt' => $Link['element']['text'],
|
1233 |
-
),
|
1234 |
-
),
|
1235 |
-
);
|
1236 |
-
|
1237 |
-
$Inline['element']['attributes'] += $Link['element']['attributes'];
|
1238 |
-
|
1239 |
-
unset($Inline['element']['attributes']['href']);
|
1240 |
-
|
1241 |
-
return $Inline;
|
1242 |
-
}
|
1243 |
-
|
1244 |
-
protected function inlineLink($Excerpt)
|
1245 |
-
{
|
1246 |
-
$Element = array(
|
1247 |
-
'name' => 'a',
|
1248 |
-
'handler' => 'line',
|
1249 |
-
'nonNestables' => array('Url', 'Link'),
|
1250 |
-
'text' => null,
|
1251 |
-
'attributes' => array(
|
1252 |
-
'href' => null,
|
1253 |
-
'title' => null,
|
1254 |
-
),
|
1255 |
-
);
|
1256 |
-
|
1257 |
-
$extent = 0;
|
1258 |
-
|
1259 |
-
$remainder = $Excerpt['text'];
|
1260 |
-
|
1261 |
-
if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
|
1262 |
-
{
|
1263 |
-
$Element['text'] = $matches[1];
|
1264 |
-
|
1265 |
-
$extent += strlen($matches[0]);
|
1266 |
-
|
1267 |
-
$remainder = substr($remainder, $extent);
|
1268 |
-
}
|
1269 |
-
else
|
1270 |
-
{
|
1271 |
-
return;
|
1272 |
-
}
|
1273 |
-
|
1274 |
-
if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches))
|
1275 |
-
{
|
1276 |
-
$Element['attributes']['href'] = $matches[1];
|
1277 |
-
|
1278 |
-
if (isset($matches[2]))
|
1279 |
-
{
|
1280 |
-
$Element['attributes']['title'] = substr($matches[2], 1, - 1);
|
1281 |
-
}
|
1282 |
-
|
1283 |
-
$extent += strlen($matches[0]);
|
1284 |
-
}
|
1285 |
-
else
|
1286 |
-
{
|
1287 |
-
if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
|
1288 |
-
{
|
1289 |
-
$definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
|
1290 |
-
$definition = strtolower($definition);
|
1291 |
-
|
1292 |
-
$extent += strlen($matches[0]);
|
1293 |
-
}
|
1294 |
-
else
|
1295 |
-
{
|
1296 |
-
$definition = strtolower($Element['text']);
|
1297 |
-
}
|
1298 |
-
|
1299 |
-
if ( ! isset($this->DefinitionData['Reference'][$definition]))
|
1300 |
-
{
|
1301 |
-
return;
|
1302 |
-
}
|
1303 |
-
|
1304 |
-
$Definition = $this->DefinitionData['Reference'][$definition];
|
1305 |
-
|
1306 |
-
$Element['attributes']['href'] = $Definition['url'];
|
1307 |
-
$Element['attributes']['title'] = $Definition['title'];
|
1308 |
-
}
|
1309 |
-
|
1310 |
-
return array(
|
1311 |
-
'extent' => $extent,
|
1312 |
-
'element' => $Element,
|
1313 |
-
);
|
1314 |
-
}
|
1315 |
-
|
1316 |
-
protected function inlineMarkup($Excerpt)
|
1317 |
-
{
|
1318 |
-
if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)
|
1319 |
-
{
|
1320 |
-
return;
|
1321 |
-
}
|
1322 |
-
|
1323 |
-
if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*[ ]*>/s', $Excerpt['text'], $matches))
|
1324 |
-
{
|
1325 |
-
return array(
|
1326 |
-
'markup' => $matches[0],
|
1327 |
-
'extent' => strlen($matches[0]),
|
1328 |
-
);
|
1329 |
-
}
|
1330 |
-
|
1331 |
-
if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
|
1332 |
-
{
|
1333 |
-
return array(
|
1334 |
-
'markup' => $matches[0],
|
1335 |
-
'extent' => strlen($matches[0]),
|
1336 |
-
);
|
1337 |
-
}
|
1338 |
-
|
1339 |
-
if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
|
1340 |
-
{
|
1341 |
-
return array(
|
1342 |
-
'markup' => $matches[0],
|
1343 |
-
'extent' => strlen($matches[0]),
|
1344 |
-
);
|
1345 |
-
}
|
1346 |
-
}
|
1347 |
-
|
1348 |
-
protected function inlineSpecialCharacter($Excerpt)
|
1349 |
-
{
|
1350 |
-
if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
|
1351 |
-
{
|
1352 |
-
return array(
|
1353 |
-
'markup' => '&',
|
1354 |
-
'extent' => 1,
|
1355 |
-
);
|
1356 |
-
}
|
1357 |
-
|
1358 |
-
$SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
|
1359 |
-
|
1360 |
-
if (isset($SpecialCharacter[$Excerpt['text'][0]]))
|
1361 |
-
{
|
1362 |
-
return array(
|
1363 |
-
'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
|
1364 |
-
'extent' => 1,
|
1365 |
-
);
|
1366 |
-
}
|
1367 |
-
}
|
1368 |
-
|
1369 |
-
protected function inlineStrikethrough($Excerpt)
|
1370 |
-
{
|
1371 |
-
if ( ! isset($Excerpt['text'][1]))
|
1372 |
-
{
|
1373 |
-
return;
|
1374 |
-
}
|
1375 |
-
|
1376 |
-
if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
|
1377 |
-
{
|
1378 |
-
return array(
|
1379 |
-
'extent' => strlen($matches[0]),
|
1380 |
-
'element' => array(
|
1381 |
-
'name' => 'del',
|
1382 |
-
'text' => $matches[1],
|
1383 |
-
'handler' => 'line',
|
1384 |
-
),
|
1385 |
-
);
|
1386 |
-
}
|
1387 |
-
}
|
1388 |
-
|
1389 |
-
protected function inlineUrl($Excerpt)
|
1390 |
-
{
|
1391 |
-
if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
|
1392 |
-
{
|
1393 |
-
return;
|
1394 |
-
}
|
1395 |
-
|
1396 |
-
if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
|
1397 |
-
{
|
1398 |
-
$url = $matches[0][0];
|
1399 |
-
|
1400 |
-
$Inline = array(
|
1401 |
-
'extent' => strlen($matches[0][0]),
|
1402 |
-
'position' => $matches[0][1],
|
1403 |
-
'element' => array(
|
1404 |
-
'name' => 'a',
|
1405 |
-
'text' => $url,
|
1406 |
-
'attributes' => array(
|
1407 |
-
'href' => $url,
|
1408 |
-
),
|
1409 |
-
),
|
1410 |
-
);
|
1411 |
-
|
1412 |
-
return $Inline;
|
1413 |
-
}
|
1414 |
-
}
|
1415 |
-
|
1416 |
-
protected function inlineUrlTag($Excerpt)
|
1417 |
-
{
|
1418 |
-
if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
|
1419 |
-
{
|
1420 |
-
$url = $matches[1];
|
1421 |
-
|
1422 |
-
return array(
|
1423 |
-
'extent' => strlen($matches[0]),
|
1424 |
-
'element' => array(
|
1425 |
-
'name' => 'a',
|
1426 |
-
'text' => $url,
|
1427 |
-
'attributes' => array(
|
1428 |
-
'href' => $url,
|
1429 |
-
),
|
1430 |
-
),
|
1431 |
-
);
|
1432 |
-
}
|
1433 |
-
}
|
1434 |
-
|
1435 |
-
# ~
|
1436 |
-
|
1437 |
-
protected function unmarkedText($text)
|
1438 |
-
{
|
1439 |
-
if ($this->breaksEnabled)
|
1440 |
-
{
|
1441 |
-
$text = preg_replace('/[ ]*\n/', "<br />\n", $text);
|
1442 |
-
}
|
1443 |
-
else
|
1444 |
-
{
|
1445 |
-
$text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
|
1446 |
-
$text = str_replace(" \n", "\n", $text);
|
1447 |
-
}
|
1448 |
-
|
1449 |
-
return $text;
|
1450 |
-
}
|
1451 |
-
|
1452 |
-
#
|
1453 |
-
# Handlers
|
1454 |
-
#
|
1455 |
-
|
1456 |
-
protected function element(array $Element)
|
1457 |
-
{
|
1458 |
-
if ($this->safeMode)
|
1459 |
-
{
|
1460 |
-
$Element = $this->sanitiseElement($Element);
|
1461 |
-
}
|
1462 |
-
|
1463 |
-
$markup = '<'.$Element['name'];
|
1464 |
-
|
1465 |
-
if (isset($Element['attributes']))
|
1466 |
-
{
|
1467 |
-
foreach ($Element['attributes'] as $name => $value)
|
1468 |
-
{
|
1469 |
-
if ($value === null)
|
1470 |
-
{
|
1471 |
-
continue;
|
1472 |
-
}
|
1473 |
-
|
1474 |
-
$markup .= ' '.$name.'="'.self::escape($value).'"';
|
1475 |
-
}
|
1476 |
-
}
|
1477 |
-
|
1478 |
-
if (isset($Element['text']))
|
1479 |
-
{
|
1480 |
-
$markup .= '>';
|
1481 |
-
|
1482 |
-
if (!isset($Element['nonNestables']))
|
1483 |
-
{
|
1484 |
-
$Element['nonNestables'] = array();
|
1485 |
-
}
|
1486 |
-
|
1487 |
-
if (isset($Element['handler']))
|
1488 |
-
{
|
1489 |
-
$markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);
|
1490 |
-
}
|
1491 |
-
else
|
1492 |
-
{
|
1493 |
-
$markup .= self::escape($Element['text'], true);
|
1494 |
-
}
|
1495 |
-
|
1496 |
-
$markup .= '</'.$Element['name'].'>';
|
1497 |
-
}
|
1498 |
-
else
|
1499 |
-
{
|
1500 |
-
$markup .= ' />';
|
1501 |
-
}
|
1502 |
-
|
1503 |
-
return $markup;
|
1504 |
-
}
|
1505 |
-
|
1506 |
-
protected function elements(array $Elements)
|
1507 |
-
{
|
1508 |
-
$markup = '';
|
1509 |
-
|
1510 |
-
foreach ($Elements as $Element)
|
1511 |
-
{
|
1512 |
-
$markup .= "\n" . $this->element($Element);
|
1513 |
-
}
|
1514 |
-
|
1515 |
-
$markup .= "\n";
|
1516 |
-
|
1517 |
-
return $markup;
|
1518 |
-
}
|
1519 |
-
|
1520 |
-
# ~
|
1521 |
-
|
1522 |
-
protected function li($lines)
|
1523 |
-
{
|
1524 |
-
$markup = $this->lines($lines);
|
1525 |
-
|
1526 |
-
$trimmedMarkup = trim($markup);
|
1527 |
-
|
1528 |
-
if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
|
1529 |
-
{
|
1530 |
-
$markup = $trimmedMarkup;
|
1531 |
-
$markup = substr($markup, 3);
|
1532 |
-
|
1533 |
-
$position = strpos($markup, "</p>");
|
1534 |
-
|
1535 |
-
$markup = substr_replace($markup, '', $position, 4);
|
1536 |
-
}
|
1537 |
-
|
1538 |
-
return $markup;
|
1539 |
-
}
|
1540 |
-
|
1541 |
-
#
|
1542 |
-
# Deprecated Methods
|
1543 |
-
#
|
1544 |
-
|
1545 |
-
function parse($text)
|
1546 |
-
{
|
1547 |
-
$markup = $this->text($text);
|
1548 |
-
|
1549 |
-
return $markup;
|
1550 |
-
}
|
1551 |
-
|
1552 |
-
protected function sanitiseElement(array $Element)
|
1553 |
-
{
|
1554 |
-
static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
|
1555 |
-
static $safeUrlNameToAtt = array(
|
1556 |
-
'a' => 'href',
|
1557 |
-
'img' => 'src',
|
1558 |
-
);
|
1559 |
-
|
1560 |
-
if (isset($safeUrlNameToAtt[$Element['name']]))
|
1561 |
-
{
|
1562 |
-
$Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
|
1563 |
-
}
|
1564 |
-
|
1565 |
-
if ( ! empty($Element['attributes']))
|
1566 |
-
{
|
1567 |
-
foreach ($Element['attributes'] as $att => $val)
|
1568 |
-
{
|
1569 |
-
# filter out badly parsed attribute
|
1570 |
-
if ( ! preg_match($goodAttribute, $att))
|
1571 |
-
{
|
1572 |
-
unset($Element['attributes'][$att]);
|
1573 |
-
}
|
1574 |
-
# dump onevent attribute
|
1575 |
-
elseif (self::striAtStart($att, 'on'))
|
1576 |
-
{
|
1577 |
-
unset($Element['attributes'][$att]);
|
1578 |
-
}
|
1579 |
-
}
|
1580 |
-
}
|
1581 |
-
|
1582 |
-
return $Element;
|
1583 |
-
}
|
1584 |
-
|
1585 |
-
protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
|
1586 |
-
{
|
1587 |
-
foreach ($this->safeLinksWhitelist as $scheme)
|
1588 |
-
{
|
1589 |
-
if (self::striAtStart($Element['attributes'][$attribute], $scheme))
|
1590 |
-
{
|
1591 |
-
return $Element;
|
1592 |
-
}
|
1593 |
-
}
|
1594 |
-
|
1595 |
-
$Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
|
1596 |
-
|
1597 |
-
return $Element;
|
1598 |
-
}
|
1599 |
-
|
1600 |
-
#
|
1601 |
-
# Static Methods
|
1602 |
-
#
|
1603 |
-
|
1604 |
-
protected static function escape($text, $allowQuotes = false)
|
1605 |
-
{
|
1606 |
-
return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
|
1607 |
-
}
|
1608 |
-
|
1609 |
-
protected static function striAtStart($string, $needle)
|
1610 |
-
{
|
1611 |
-
$len = strlen($needle);
|
1612 |
-
|
1613 |
-
if ($len > strlen($string))
|
1614 |
-
{
|
1615 |
-
return false;
|
1616 |
-
}
|
1617 |
-
else
|
1618 |
-
{
|
1619 |
-
return strtolower(substr($string, 0, $len)) === strtolower($needle);
|
1620 |
-
}
|
1621 |
-
}
|
1622 |
-
|
1623 |
-
static function instance($name = 'default')
|
1624 |
-
{
|
1625 |
-
if (isset(self::$instances[$name]))
|
1626 |
-
{
|
1627 |
-
return self::$instances[$name];
|
1628 |
-
}
|
1629 |
-
|
1630 |
-
$instance = new static();
|
1631 |
-
|
1632 |
-
self::$instances[$name] = $instance;
|
1633 |
-
|
1634 |
-
return $instance;
|
1635 |
-
}
|
1636 |
-
|
1637 |
-
private static $instances = array();
|
1638 |
-
|
1639 |
-
#
|
1640 |
-
# Fields
|
1641 |
-
#
|
1642 |
-
|
1643 |
-
protected $DefinitionData;
|
1644 |
-
|
1645 |
-
#
|
1646 |
-
# Read-Only
|
1647 |
-
|
1648 |
-
protected $specialCharacters = array(
|
1649 |
-
'\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
|
1650 |
-
);
|
1651 |
-
|
1652 |
-
protected $StrongRegex = array(
|
1653 |
-
'*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
|
1654 |
-
'_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
|
1655 |
-
);
|
1656 |
-
|
1657 |
-
protected $EmRegex = array(
|
1658 |
-
'*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
|
1659 |
-
'_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
|
1660 |
-
);
|
1661 |
-
|
1662 |
-
protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
|
1663 |
-
|
1664 |
-
protected $voidElements = array(
|
1665 |
-
'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
|
1666 |
-
);
|
1667 |
-
|
1668 |
-
protected $textLevelElements = array(
|
1669 |
-
'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
|
1670 |
-
'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
|
1671 |
-
'i', 'rp', 'del', 'code', 'strike', 'marquee',
|
1672 |
-
'q', 'rt', 'ins', 'font', 'strong',
|
1673 |
-
's', 'tt', 'kbd', 'mark',
|
1674 |
-
'u', 'xm', 'sub', 'nobr',
|
1675 |
-
'sup', 'ruby',
|
1676 |
-
'var', 'span',
|
1677 |
-
'wbr', 'time',
|
1678 |
-
);
|
1679 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
#
|
4 |
+
#
|
5 |
+
# Parsedown
|
6 |
+
# http://parsedown.org
|
7 |
+
#
|
8 |
+
# (c) Emanuil Rusev
|
9 |
+
# http://erusev.com
|
10 |
+
#
|
11 |
+
# For the full license information, view the LICENSE file that was distributed
|
12 |
+
# with this source code.
|
13 |
+
#
|
14 |
+
#
|
15 |
+
|
16 |
+
class Parsedown
|
17 |
+
{
|
18 |
+
# ~
|
19 |
+
|
20 |
+
const version = '1.7.1';
|
21 |
+
|
22 |
+
# ~
|
23 |
+
|
24 |
+
function text($text)
|
25 |
+
{
|
26 |
+
# make sure no definitions are set
|
27 |
+
$this->DefinitionData = array();
|
28 |
+
|
29 |
+
# standardize line breaks
|
30 |
+
$text = str_replace(array("\r\n", "\r"), "\n", $text);
|
31 |
+
|
32 |
+
# remove surrounding line breaks
|
33 |
+
$text = trim($text, "\n");
|
34 |
+
|
35 |
+
# split text into lines
|
36 |
+
$lines = explode("\n", $text);
|
37 |
+
|
38 |
+
# iterate through lines to identify blocks
|
39 |
+
$markup = $this->lines($lines);
|
40 |
+
|
41 |
+
# trim line breaks
|
42 |
+
$markup = trim($markup, "\n");
|
43 |
+
|
44 |
+
return $markup;
|
45 |
+
}
|
46 |
+
|
47 |
+
#
|
48 |
+
# Setters
|
49 |
+
#
|
50 |
+
|
51 |
+
function setBreaksEnabled($breaksEnabled)
|
52 |
+
{
|
53 |
+
$this->breaksEnabled = $breaksEnabled;
|
54 |
+
|
55 |
+
return $this;
|
56 |
+
}
|
57 |
+
|
58 |
+
protected $breaksEnabled;
|
59 |
+
|
60 |
+
function setMarkupEscaped($markupEscaped)
|
61 |
+
{
|
62 |
+
$this->markupEscaped = $markupEscaped;
|
63 |
+
|
64 |
+
return $this;
|
65 |
+
}
|
66 |
+
|
67 |
+
protected $markupEscaped;
|
68 |
+
|
69 |
+
function setUrlsLinked($urlsLinked)
|
70 |
+
{
|
71 |
+
$this->urlsLinked = $urlsLinked;
|
72 |
+
|
73 |
+
return $this;
|
74 |
+
}
|
75 |
+
|
76 |
+
protected $urlsLinked = true;
|
77 |
+
|
78 |
+
function setSafeMode($safeMode)
|
79 |
+
{
|
80 |
+
$this->safeMode = (bool) $safeMode;
|
81 |
+
|
82 |
+
return $this;
|
83 |
+
}
|
84 |
+
|
85 |
+
protected $safeMode;
|
86 |
+
|
87 |
+
protected $safeLinksWhitelist = array(
|
88 |
+
'http://',
|
89 |
+
'https://',
|
90 |
+
'ftp://',
|
91 |
+
'ftps://',
|
92 |
+
'mailto:',
|
93 |
+
'data:image/png;base64,',
|
94 |
+
'data:image/gif;base64,',
|
95 |
+
'data:image/jpeg;base64,',
|
96 |
+
'irc:',
|
97 |
+
'ircs:',
|
98 |
+
'git:',
|
99 |
+
'ssh:',
|
100 |
+
'news:',
|
101 |
+
'steam:',
|
102 |
+
);
|
103 |
+
|
104 |
+
#
|
105 |
+
# Lines
|
106 |
+
#
|
107 |
+
|
108 |
+
protected $BlockTypes = array(
|
109 |
+
'#' => array('Header'),
|
110 |
+
'*' => array('Rule', 'List'),
|
111 |
+
'+' => array('List'),
|
112 |
+
'-' => array('SetextHeader', 'Table', 'Rule', 'List'),
|
113 |
+
'0' => array('List'),
|
114 |
+
'1' => array('List'),
|
115 |
+
'2' => array('List'),
|
116 |
+
'3' => array('List'),
|
117 |
+
'4' => array('List'),
|
118 |
+
'5' => array('List'),
|
119 |
+
'6' => array('List'),
|
120 |
+
'7' => array('List'),
|
121 |
+
'8' => array('List'),
|
122 |
+
'9' => array('List'),
|
123 |
+
':' => array('Table'),
|
124 |
+
'<' => array('Comment', 'Markup'),
|
125 |
+
'=' => array('SetextHeader'),
|
126 |
+
'>' => array('Quote'),
|
127 |
+
'[' => array('Reference'),
|
128 |
+
'_' => array('Rule'),
|
129 |
+
'`' => array('FencedCode'),
|
130 |
+
'|' => array('Table'),
|
131 |
+
'~' => array('FencedCode'),
|
132 |
+
);
|
133 |
+
|
134 |
+
# ~
|
135 |
+
|
136 |
+
protected $unmarkedBlockTypes = array(
|
137 |
+
'Code',
|
138 |
+
);
|
139 |
+
|
140 |
+
#
|
141 |
+
# Blocks
|
142 |
+
#
|
143 |
+
|
144 |
+
protected function lines(array $lines)
|
145 |
+
{
|
146 |
+
$CurrentBlock = null;
|
147 |
+
|
148 |
+
foreach ($lines as $line)
|
149 |
+
{
|
150 |
+
if (chop($line) === '')
|
151 |
+
{
|
152 |
+
if (isset($CurrentBlock))
|
153 |
+
{
|
154 |
+
$CurrentBlock['interrupted'] = true;
|
155 |
+
}
|
156 |
+
|
157 |
+
continue;
|
158 |
+
}
|
159 |
+
|
160 |
+
if (strpos($line, "\t") !== false)
|
161 |
+
{
|
162 |
+
$parts = explode("\t", $line);
|
163 |
+
|
164 |
+
$line = $parts[0];
|
165 |
+
|
166 |
+
unset($parts[0]);
|
167 |
+
|
168 |
+
foreach ($parts as $part)
|
169 |
+
{
|
170 |
+
$shortage = 4 - mb_strlen($line, 'utf-8') % 4;
|
171 |
+
|
172 |
+
$line .= str_repeat(' ', $shortage);
|
173 |
+
$line .= $part;
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
$indent = 0;
|
178 |
+
|
179 |
+
while (isset($line[$indent]) and $line[$indent] === ' ')
|
180 |
+
{
|
181 |
+
$indent ++;
|
182 |
+
}
|
183 |
+
|
184 |
+
$text = $indent > 0 ? substr($line, $indent) : $line;
|
185 |
+
|
186 |
+
# ~
|
187 |
+
|
188 |
+
$Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
|
189 |
+
|
190 |
+
# ~
|
191 |
+
|
192 |
+
if (isset($CurrentBlock['continuable']))
|
193 |
+
{
|
194 |
+
$Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
|
195 |
+
|
196 |
+
if (isset($Block))
|
197 |
+
{
|
198 |
+
$CurrentBlock = $Block;
|
199 |
+
|
200 |
+
continue;
|
201 |
+
}
|
202 |
+
else
|
203 |
+
{
|
204 |
+
if ($this->isBlockCompletable($CurrentBlock['type']))
|
205 |
+
{
|
206 |
+
$CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
|
207 |
+
}
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
# ~
|
212 |
+
|
213 |
+
$marker = $text[0];
|
214 |
+
|
215 |
+
# ~
|
216 |
+
|
217 |
+
$blockTypes = $this->unmarkedBlockTypes;
|
218 |
+
|
219 |
+
if (isset($this->BlockTypes[$marker]))
|
220 |
+
{
|
221 |
+
foreach ($this->BlockTypes[$marker] as $blockType)
|
222 |
+
{
|
223 |
+
$blockTypes []= $blockType;
|
224 |
+
}
|
225 |
+
}
|
226 |
+
|
227 |
+
#
|
228 |
+
# ~
|
229 |
+
|
230 |
+
foreach ($blockTypes as $blockType)
|
231 |
+
{
|
232 |
+
$Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
|
233 |
+
|
234 |
+
if (isset($Block))
|
235 |
+
{
|
236 |
+
$Block['type'] = $blockType;
|
237 |
+
|
238 |
+
if ( ! isset($Block['identified']))
|
239 |
+
{
|
240 |
+
$Blocks []= $CurrentBlock;
|
241 |
+
|
242 |
+
$Block['identified'] = true;
|
243 |
+
}
|
244 |
+
|
245 |
+
if ($this->isBlockContinuable($blockType))
|
246 |
+
{
|
247 |
+
$Block['continuable'] = true;
|
248 |
+
}
|
249 |
+
|
250 |
+
$CurrentBlock = $Block;
|
251 |
+
|
252 |
+
continue 2;
|
253 |
+
}
|
254 |
+
}
|
255 |
+
|
256 |
+
# ~
|
257 |
+
|
258 |
+
if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
|
259 |
+
{
|
260 |
+
$CurrentBlock['element']['text'] .= "\n".$text;
|
261 |
+
}
|
262 |
+
else
|
263 |
+
{
|
264 |
+
$Blocks []= $CurrentBlock;
|
265 |
+
|
266 |
+
$CurrentBlock = $this->paragraph($Line);
|
267 |
+
|
268 |
+
$CurrentBlock['identified'] = true;
|
269 |
+
}
|
270 |
+
}
|
271 |
+
|
272 |
+
# ~
|
273 |
+
|
274 |
+
if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))
|
275 |
+
{
|
276 |
+
$CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
|
277 |
+
}
|
278 |
+
|
279 |
+
# ~
|
280 |
+
|
281 |
+
$Blocks []= $CurrentBlock;
|
282 |
+
|
283 |
+
unset($Blocks[0]);
|
284 |
+
|
285 |
+
# ~
|
286 |
+
|
287 |
+
$markup = '';
|
288 |
+
|
289 |
+
foreach ($Blocks as $Block)
|
290 |
+
{
|
291 |
+
if (isset($Block['hidden']))
|
292 |
+
{
|
293 |
+
continue;
|
294 |
+
}
|
295 |
+
|
296 |
+
$markup .= "\n";
|
297 |
+
$markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
|
298 |
+
}
|
299 |
+
|
300 |
+
$markup .= "\n";
|
301 |
+
|
302 |
+
# ~
|
303 |
+
|
304 |
+
return $markup;
|
305 |
+
}
|
306 |
+
|
307 |
+
protected function isBlockContinuable($Type)
|
308 |
+
{
|
309 |
+
return method_exists($this, 'block'.$Type.'Continue');
|
310 |
+
}
|
311 |
+
|
312 |
+
protected function isBlockCompletable($Type)
|
313 |
+
{
|
314 |
+
return method_exists($this, 'block'.$Type.'Complete');
|
315 |
+
}
|
316 |
+
|
317 |
+
#
|
318 |
+
# Code
|
319 |
+
|
320 |
+
protected function blockCode($Line, $Block = null)
|
321 |
+
{
|
322 |
+
if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
|
323 |
+
{
|
324 |
+
return;
|
325 |
+
}
|
326 |
+
|
327 |
+
if ($Line['indent'] >= 4)
|
328 |
+
{
|
329 |
+
$text = substr($Line['body'], 4);
|
330 |
+
|
331 |
+
$Block = array(
|
332 |
+
'element' => array(
|
333 |
+
'name' => 'pre',
|
334 |
+
'handler' => 'element',
|
335 |
+
'text' => array(
|
336 |
+
'name' => 'code',
|
337 |
+
'text' => $text,
|
338 |
+
),
|
339 |
+
),
|
340 |
+
);
|
341 |
+
|
342 |
+
return $Block;
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
protected function blockCodeContinue($Line, $Block)
|
347 |
+
{
|
348 |
+
if ($Line['indent'] >= 4)
|
349 |
+
{
|
350 |
+
if (isset($Block['interrupted']))
|
351 |
+
{
|
352 |
+
$Block['element']['text']['text'] .= "\n";
|
353 |
+
|
354 |
+
unset($Block['interrupted']);
|
355 |
+
}
|
356 |
+
|
357 |
+
$Block['element']['text']['text'] .= "\n";
|
358 |
+
|
359 |
+
$text = substr($Line['body'], 4);
|
360 |
+
|
361 |
+
$Block['element']['text']['text'] .= $text;
|
362 |
+
|
363 |
+
return $Block;
|
364 |
+
}
|
365 |
+
}
|
366 |
+
|
367 |
+
protected function blockCodeComplete($Block)
|
368 |
+
{
|
369 |
+
$text = $Block['element']['text']['text'];
|
370 |
+
|
371 |
+
$Block['element']['text']['text'] = $text;
|
372 |
+
|
373 |
+
return $Block;
|
374 |
+
}
|
375 |
+
|
376 |
+
#
|
377 |
+
# Comment
|
378 |
+
|
379 |
+
protected function blockComment($Line)
|
380 |
+
{
|
381 |
+
if ($this->markupEscaped or $this->safeMode)
|
382 |
+
{
|
383 |
+
return;
|
384 |
+
}
|
385 |
+
|
386 |
+
if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
|
387 |
+
{
|
388 |
+
$Block = array(
|
389 |
+
'markup' => $Line['body'],
|
390 |
+
);
|
391 |
+
|
392 |
+
if (preg_match('/-->$/', $Line['text']))
|
393 |
+
{
|
394 |
+
$Block['closed'] = true;
|
395 |
+
}
|
396 |
+
|
397 |
+
return $Block;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
protected function blockCommentContinue($Line, array $Block)
|
402 |
+
{
|
403 |
+
if (isset($Block['closed']))
|
404 |
+
{
|
405 |
+
return;
|
406 |
+
}
|
407 |
+
|
408 |
+
$Block['markup'] .= "\n" . $Line['body'];
|
409 |
+
|
410 |
+
if (preg_match('/-->$/', $Line['text']))
|
411 |
+
{
|
412 |
+
$Block['closed'] = true;
|
413 |
+
}
|
414 |
+
|
415 |
+
return $Block;
|
416 |
+
}
|
417 |
+
|
418 |
+
#
|
419 |
+
# Fenced Code
|
420 |
+
|
421 |
+
protected function blockFencedCode($Line)
|
422 |
+
{
|
423 |
+
if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches))
|
424 |
+
{
|
425 |
+
$Element = array(
|
426 |
+
'name' => 'code',
|
427 |
+
'text' => '',
|
428 |
+
);
|
429 |
+
|
430 |
+
if (isset($matches[1]))
|
431 |
+
{
|
432 |
+
$class = 'language-'.$matches[1];
|
433 |
+
|
434 |
+
$Element['attributes'] = array(
|
435 |
+
'class' => $class,
|
436 |
+
);
|
437 |
+
}
|
438 |
+
|
439 |
+
$Block = array(
|
440 |
+
'char' => $Line['text'][0],
|
441 |
+
'element' => array(
|
442 |
+
'name' => 'pre',
|
443 |
+
'handler' => 'element',
|
444 |
+
'text' => $Element,
|
445 |
+
),
|
446 |
+
);
|
447 |
+
|
448 |
+
return $Block;
|
449 |
+
}
|
450 |
+
}
|
451 |
+
|
452 |
+
protected function blockFencedCodeContinue($Line, $Block)
|
453 |
+
{
|
454 |
+
if (isset($Block['complete']))
|
455 |
+
{
|
456 |
+
return;
|
457 |
+
}
|
458 |
+
|
459 |
+
if (isset($Block['interrupted']))
|
460 |
+
{
|
461 |
+
$Block['element']['text']['text'] .= "\n";
|
462 |
+
|
463 |
+
unset($Block['interrupted']);
|
464 |
+
}
|
465 |
+
|
466 |
+
if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
|
467 |
+
{
|
468 |
+
$Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
|
469 |
+
|
470 |
+
$Block['complete'] = true;
|
471 |
+
|
472 |
+
return $Block;
|
473 |
+
}
|
474 |
+
|
475 |
+
$Block['element']['text']['text'] .= "\n".$Line['body'];
|
476 |
+
|
477 |
+
return $Block;
|
478 |
+
}
|
479 |
+
|
480 |
+
protected function blockFencedCodeComplete($Block)
|
481 |
+
{
|
482 |
+
$text = $Block['element']['text']['text'];
|
483 |
+
|
484 |
+
$Block['element']['text']['text'] = $text;
|
485 |
+
|
486 |
+
return $Block;
|
487 |
+
}
|
488 |
+
|
489 |
+
#
|
490 |
+
# Header
|
491 |
+
|
492 |
+
protected function blockHeader($Line)
|
493 |
+
{
|
494 |
+
if (isset($Line['text'][1]))
|
495 |
+
{
|
496 |
+
$level = 1;
|
497 |
+
|
498 |
+
while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
|
499 |
+
{
|
500 |
+
$level ++;
|
501 |
+
}
|
502 |
+
|
503 |
+
if ($level > 6)
|
504 |
+
{
|
505 |
+
return;
|
506 |
+
}
|
507 |
+
|
508 |
+
$text = trim($Line['text'], '# ');
|
509 |
+
|
510 |
+
$Block = array(
|
511 |
+
'element' => array(
|
512 |
+
'name' => 'h' . min(6, $level),
|
513 |
+
'text' => $text,
|
514 |
+
'handler' => 'line',
|
515 |
+
),
|
516 |
+
);
|
517 |
+
|
518 |
+
return $Block;
|
519 |
+
}
|
520 |
+
}
|
521 |
+
|
522 |
+
#
|
523 |
+
# List
|
524 |
+
|
525 |
+
protected function blockList($Line)
|
526 |
+
{
|
527 |
+
list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
|
528 |
+
|
529 |
+
if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
|
530 |
+
{
|
531 |
+
$Block = array(
|
532 |
+
'indent' => $Line['indent'],
|
533 |
+
'pattern' => $pattern,
|
534 |
+
'element' => array(
|
535 |
+
'name' => $name,
|
536 |
+
'handler' => 'elements',
|
537 |
+
),
|
538 |
+
);
|
539 |
+
|
540 |
+
if($name === 'ol')
|
541 |
+
{
|
542 |
+
$listStart = stristr($matches[0], '.', true);
|
543 |
+
|
544 |
+
if($listStart !== '1')
|
545 |
+
{
|
546 |
+
$Block['element']['attributes'] = array('start' => $listStart);
|
547 |
+
}
|
548 |
+
}
|
549 |
+
|
550 |
+
$Block['li'] = array(
|
551 |
+
'name' => 'li',
|
552 |
+
'handler' => 'li',
|
553 |
+
'text' => array(
|
554 |
+
$matches[2],
|
555 |
+
),
|
556 |
+
);
|
557 |
+
|
558 |
+
$Block['element']['text'] []= & $Block['li'];
|
559 |
+
|
560 |
+
return $Block;
|
561 |
+
}
|
562 |
+
}
|
563 |
+
|
564 |
+
protected function blockListContinue($Line, array $Block)
|
565 |
+
{
|
566 |
+
if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
|
567 |
+
{
|
568 |
+
if (isset($Block['interrupted']))
|
569 |
+
{
|
570 |
+
$Block['li']['text'] []= '';
|
571 |
+
|
572 |
+
$Block['loose'] = true;
|
573 |
+
|
574 |
+
unset($Block['interrupted']);
|
575 |
+
}
|
576 |
+
|
577 |
+
unset($Block['li']);
|
578 |
+
|
579 |
+
$text = isset($matches[1]) ? $matches[1] : '';
|
580 |
+
|
581 |
+
$Block['li'] = array(
|
582 |
+
'name' => 'li',
|
583 |
+
'handler' => 'li',
|
584 |
+
'text' => array(
|
585 |
+
$text,
|
586 |
+
),
|
587 |
+
);
|
588 |
+
|
589 |
+
$Block['element']['text'] []= & $Block['li'];
|
590 |
+
|
591 |
+
return $Block;
|
592 |
+
}
|
593 |
+
|
594 |
+
if ($Line['text'][0] === '[' and $this->blockReference($Line))
|
595 |
+
{
|
596 |
+
return $Block;
|
597 |
+
}
|
598 |
+
|
599 |
+
if ( ! isset($Block['interrupted']))
|
600 |
+
{
|
601 |
+
$text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
|
602 |
+
|
603 |
+
$Block['li']['text'] []= $text;
|
604 |
+
|
605 |
+
return $Block;
|
606 |
+
}
|
607 |
+
|
608 |
+
if ($Line['indent'] > 0)
|
609 |
+
{
|
610 |
+
$Block['li']['text'] []= '';
|
611 |
+
|
612 |
+
$text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
|
613 |
+
|
614 |
+
$Block['li']['text'] []= $text;
|
615 |
+
|
616 |
+
unset($Block['interrupted']);
|
617 |
+
|
618 |
+
return $Block;
|
619 |
+
}
|
620 |
+
}
|
621 |
+
|
622 |
+
protected function blockListComplete(array $Block)
|
623 |
+
{
|
624 |
+
if (isset($Block['loose']))
|
625 |
+
{
|
626 |
+
foreach ($Block['element']['text'] as &$li)
|
627 |
+
{
|
628 |
+
if (end($li['text']) !== '')
|
629 |
+
{
|
630 |
+
$li['text'] []= '';
|
631 |
+
}
|
632 |
+
}
|
633 |
+
}
|
634 |
+
|
635 |
+
return $Block;
|
636 |
+
}
|
637 |
+
|
638 |
+
#
|
639 |
+
# Quote
|
640 |
+
|
641 |
+
protected function blockQuote($Line)
|
642 |
+
{
|
643 |
+
if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
|
644 |
+
{
|
645 |
+
$Block = array(
|
646 |
+
'element' => array(
|
647 |
+
'name' => 'blockquote',
|
648 |
+
'handler' => 'lines',
|
649 |
+
'text' => (array) $matches[1],
|
650 |
+
),
|
651 |
+
);
|
652 |
+
|
653 |
+
return $Block;
|
654 |
+
}
|
655 |
+
}
|
656 |
+
|
657 |
+
protected function blockQuoteContinue($Line, array $Block)
|
658 |
+
{
|
659 |
+
if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
|
660 |
+
{
|
661 |
+
if (isset($Block['interrupted']))
|
662 |
+
{
|
663 |
+
$Block['element']['text'] []= '';
|
664 |
+
|
665 |
+
unset($Block['interrupted']);
|
666 |
+
}
|
667 |
+
|
668 |
+
$Block['element']['text'] []= $matches[1];
|
669 |
+
|
670 |
+
return $Block;
|
671 |
+
}
|
672 |
+
|
673 |
+
if ( ! isset($Block['interrupted']))
|
674 |
+
{
|
675 |
+
$Block['element']['text'] []= $Line['text'];
|
676 |
+
|
677 |
+
return $Block;
|
678 |
+
}
|
679 |
+
}
|
680 |
+
|
681 |
+
#
|
682 |
+
# Rule
|
683 |
+
|
684 |
+
protected function blockRule($Line)
|
685 |
+
{
|
686 |
+
if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
|
687 |
+
{
|
688 |
+
$Block = array(
|
689 |
+
'element' => array(
|
690 |
+
'name' => 'hr'
|
691 |
+
),
|
692 |
+
);
|
693 |
+
|
694 |
+
return $Block;
|
695 |
+
}
|
696 |
+
}
|
697 |
+
|
698 |
+
#
|
699 |
+
# Setext
|
700 |
+
|
701 |
+
protected function blockSetextHeader($Line, array $Block = null)
|
702 |
+
{
|
703 |
+
if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
|
704 |
+
{
|
705 |
+
return;
|
706 |
+
}
|
707 |
+
|
708 |
+
if (chop($Line['text'], $Line['text'][0]) === '')
|
709 |
+
{
|
710 |
+
$Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
|
711 |
+
|
712 |
+
return $Block;
|
713 |
+
}
|
714 |
+
}
|
715 |
+
|
716 |
+
#
|
717 |
+
# Markup
|
718 |
+
|
719 |
+
protected function blockMarkup($Line)
|
720 |
+
{
|
721 |
+
if ($this->markupEscaped or $this->safeMode)
|
722 |
+
{
|
723 |
+
return;
|
724 |
+
}
|
725 |
+
|
726 |
+
if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
|
727 |
+
{
|
728 |
+
$element = strtolower($matches[1]);
|
729 |
+
|
730 |
+
if (in_array($element, $this->textLevelElements))
|
731 |
+
{
|
732 |
+
return;
|
733 |
+
}
|
734 |
+
|
735 |
+
$Block = array(
|
736 |
+
'name' => $matches[1],
|
737 |
+
'depth' => 0,
|
738 |
+
'markup' => $Line['text'],
|
739 |
+
);
|
740 |
+
|
741 |
+
$length = strlen($matches[0]);
|
742 |
+
|
743 |
+
$remainder = substr($Line['text'], $length);
|
744 |
+
|
745 |
+
if (trim($remainder) === '')
|
746 |
+
{
|
747 |
+
if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
|
748 |
+
{
|
749 |
+
$Block['closed'] = true;
|
750 |
+
|
751 |
+
$Block['void'] = true;
|
752 |
+
}
|
753 |
+
}
|
754 |
+
else
|
755 |
+
{
|
756 |
+
if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
|
757 |
+
{
|
758 |
+
return;
|
759 |
+
}
|
760 |
+
|
761 |
+
if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
|
762 |
+
{
|
763 |
+
$Block['closed'] = true;
|
764 |
+
}
|
765 |
+
}
|
766 |
+
|
767 |
+
return $Block;
|
768 |
+
}
|
769 |
+
}
|
770 |
+
|
771 |
+
protected function blockMarkupContinue($Line, array $Block)
|
772 |
+
{
|
773 |
+
if (isset($Block['closed']))
|
774 |
+
{
|
775 |
+
return;
|
776 |
+
}
|
777 |
+
|
778 |
+
if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
|
779 |
+
{
|
780 |
+
$Block['depth'] ++;
|
781 |
+
}
|
782 |
+
|
783 |
+
if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
|
784 |
+
{
|
785 |
+
if ($Block['depth'] > 0)
|
786 |
+
{
|
787 |
+
$Block['depth'] --;
|
788 |
+
}
|
789 |
+
else
|
790 |
+
{
|
791 |
+
$Block['closed'] = true;
|
792 |
+
}
|
793 |
+
}
|
794 |
+
|
795 |
+
if (isset($Block['interrupted']))
|
796 |
+
{
|
797 |
+
$Block['markup'] .= "\n";
|
798 |
+
|
799 |
+
unset($Block['interrupted']);
|
800 |
+
}
|
801 |
+
|
802 |
+
$Block['markup'] .= "\n".$Line['body'];
|
803 |
+
|
804 |
+
return $Block;
|
805 |
+
}
|
806 |
+
|
807 |
+
#
|
808 |
+
# Reference
|
809 |
+
|
810 |
+
protected function blockReference($Line)
|
811 |
+
{
|
812 |
+
if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
|
813 |
+
{
|
814 |
+
$id = strtolower($matches[1]);
|
815 |
+
|
816 |
+
$Data = array(
|
817 |
+
'url' => $matches[2],
|
818 |
+
'title' => null,
|
819 |
+
);
|
820 |
+
|
821 |
+
if (isset($matches[3]))
|
822 |
+
{
|
823 |
+
$Data['title'] = $matches[3];
|
824 |
+
}
|
825 |
+
|
826 |
+
$this->DefinitionData['Reference'][$id] = $Data;
|
827 |
+
|
828 |
+
$Block = array(
|
829 |
+
'hidden' => true,
|
830 |
+
);
|
831 |
+
|
832 |
+
return $Block;
|
833 |
+
}
|
834 |
+
}
|
835 |
+
|
836 |
+
#
|
837 |
+
# Table
|
838 |
+
|
839 |
+
protected function blockTable($Line, array $Block = null)
|
840 |
+
{
|
841 |
+
if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
|
842 |
+
{
|
843 |
+
return;
|
844 |
+
}
|
845 |
+
|
846 |
+
if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
|
847 |
+
{
|
848 |
+
$alignments = array();
|
849 |
+
|
850 |
+
$divider = $Line['text'];
|
851 |
+
|
852 |
+
$divider = trim($divider);
|
853 |
+
$divider = trim($divider, '|');
|
854 |
+
|
855 |
+
$dividerCells = explode('|', $divider);
|
856 |
+
|
857 |
+
foreach ($dividerCells as $dividerCell)
|
858 |
+
{
|
859 |
+
$dividerCell = trim($dividerCell);
|
860 |
+
|
861 |
+
if ($dividerCell === '')
|
862 |
+
{
|
863 |
+
continue;
|
864 |
+
}
|
865 |
+
|
866 |
+
$alignment = null;
|
867 |
+
|
868 |
+
if ($dividerCell[0] === ':')
|
869 |
+
{
|
870 |
+
$alignment = 'left';
|
871 |
+
}
|
872 |
+
|
873 |
+
if (substr($dividerCell, - 1) === ':')
|
874 |
+
{
|
875 |
+
$alignment = $alignment === 'left' ? 'center' : 'right';
|
876 |
+
}
|
877 |
+
|
878 |
+
$alignments []= $alignment;
|
879 |
+
}
|
880 |
+
|
881 |
+
# ~
|
882 |
+
|
883 |
+
$HeaderElements = array();
|
884 |
+
|
885 |
+
$header = $Block['element']['text'];
|
886 |
+
|
887 |
+
$header = trim($header);
|
888 |
+
$header = trim($header, '|');
|
889 |
+
|
890 |
+
$headerCells = explode('|', $header);
|
891 |
+
|
892 |
+
foreach ($headerCells as $index => $headerCell)
|
893 |
+
{
|
894 |
+
$headerCell = trim($headerCell);
|
895 |
+
|
896 |
+
$HeaderElement = array(
|
897 |
+
'name' => 'th',
|
898 |
+
'text' => $headerCell,
|
899 |
+
'handler' => 'line',
|
900 |
+
);
|
901 |
+
|
902 |
+
if (isset($alignments[$index]))
|
903 |
+
{
|
904 |
+
$alignment = $alignments[$index];
|
905 |
+
|
906 |
+
$HeaderElement['attributes'] = array(
|
907 |
+
'style' => 'text-align: '.$alignment.';',
|
908 |
+
);
|
909 |
+
}
|
910 |
+
|
911 |
+
$HeaderElements []= $HeaderElement;
|
912 |
+
}
|
913 |
+
|
914 |
+
# ~
|
915 |
+
|
916 |
+
$Block = array(
|
917 |
+
'alignments' => $alignments,
|
918 |
+
'identified' => true,
|
919 |
+
'element' => array(
|
920 |
+
'name' => 'table',
|
921 |
+
'handler' => 'elements',
|
922 |
+
),
|
923 |
+
);
|
924 |
+
|
925 |
+
$Block['element']['text'] []= array(
|
926 |
+
'name' => 'thead',
|
927 |
+
'handler' => 'elements',
|
928 |
+
);
|
929 |
+
|
930 |
+
$Block['element']['text'] []= array(
|
931 |
+
'name' => 'tbody',
|
932 |
+
'handler' => 'elements',
|
933 |
+
'text' => array(),
|
934 |
+
);
|
935 |
+
|
936 |
+
$Block['element']['text'][0]['text'] []= array(
|
937 |
+
'name' => 'tr',
|
938 |
+
'handler' => 'elements',
|
939 |
+
'text' => $HeaderElements,
|
940 |
+
);
|
941 |
+
|
942 |
+
return $Block;
|
943 |
+
}
|
944 |
+
}
|
945 |
+
|
946 |
+
protected function blockTableContinue($Line, array $Block)
|
947 |
+
{
|
948 |
+
if (isset($Block['interrupted']))
|
949 |
+
{
|
950 |
+
return;
|
951 |
+
}
|
952 |
+
|
953 |
+
if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
|
954 |
+
{
|
955 |
+
$Elements = array();
|
956 |
+
|
957 |
+
$row = $Line['text'];
|
958 |
+
|
959 |
+
$row = trim($row);
|
960 |
+
$row = trim($row, '|');
|
961 |
+
|
962 |
+
preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
|
963 |
+
|
964 |
+
foreach ($matches[0] as $index => $cell)
|
965 |
+
{
|
966 |
+
$cell = trim($cell);
|
967 |
+
|
968 |
+
$Element = array(
|
969 |
+
'name' => 'td',
|
970 |
+
'handler' => 'line',
|
971 |
+
'text' => $cell,
|
972 |
+
);
|
973 |
+
|
974 |
+
if (isset($Block['alignments'][$index]))
|
975 |
+
{
|
976 |
+
$Element['attributes'] = array(
|
977 |
+
'style' => 'text-align: '.$Block['alignments'][$index].';',
|
978 |
+
);
|
979 |
+
}
|
980 |
+
|
981 |
+
$Elements []= $Element;
|
982 |
+
}
|
983 |
+
|
984 |
+
$Element = array(
|
985 |
+
'name' => 'tr',
|
986 |
+
'handler' => 'elements',
|
987 |
+
'text' => $Elements,
|
988 |
+
);
|
989 |
+
|
990 |
+
$Block['element']['text'][1]['text'] []= $Element;
|
991 |
+
|
992 |
+
return $Block;
|
993 |
+
}
|
994 |
+
}
|
995 |
+
|
996 |
+
#
|
997 |
+
# ~
|
998 |
+
#
|
999 |
+
|
1000 |
+
protected function paragraph($Line)
|
1001 |
+
{
|
1002 |
+
$Block = array(
|
1003 |
+
'element' => array(
|
1004 |
+
'name' => 'p',
|
1005 |
+
'text' => $Line['text'],
|
1006 |
+
'handler' => 'line',
|
1007 |
+
),
|
1008 |
+
);
|
1009 |
+
|
1010 |
+
return $Block;
|
1011 |
+
}
|
1012 |
+
|
1013 |
+
#
|
1014 |
+
# Inline Elements
|
1015 |
+
#
|
1016 |
+
|
1017 |
+
protected $InlineTypes = array(
|
1018 |
+
'"' => array('SpecialCharacter'),
|
1019 |
+
'!' => array('Image'),
|
1020 |
+
'&' => array('SpecialCharacter'),
|
1021 |
+
'*' => array('Emphasis'),
|
1022 |
+
':' => array('Url'),
|
1023 |
+
'<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
|
1024 |
+
'>' => array('SpecialCharacter'),
|
1025 |
+
'[' => array('Link'),
|
1026 |
+
'_' => array('Emphasis'),
|
1027 |
+
'`' => array('Code'),
|
1028 |
+
'~' => array('Strikethrough'),
|
1029 |
+
'\\' => array('EscapeSequence'),
|
1030 |
+
);
|
1031 |
+
|
1032 |
+
# ~
|
1033 |
+
|
1034 |
+
protected $inlineMarkerList = '!"*_&[:<>`~\\';
|
1035 |
+
|
1036 |
+
#
|
1037 |
+
# ~
|
1038 |
+
#
|
1039 |
+
|
1040 |
+
public function line($text, $nonNestables=array())
|
1041 |
+
{
|
1042 |
+
$markup = '';
|
1043 |
+
|
1044 |
+
# $excerpt is based on the first occurrence of a marker
|
1045 |
+
|
1046 |
+
while ($excerpt = strpbrk($text, $this->inlineMarkerList))
|
1047 |
+
{
|
1048 |
+
$marker = $excerpt[0];
|
1049 |
+
|
1050 |
+
$markerPosition = strpos($text, $marker);
|
1051 |
+
|
1052 |
+
$Excerpt = array('text' => $excerpt, 'context' => $text);
|
1053 |
+
|
1054 |
+
foreach ($this->InlineTypes[$marker] as $inlineType)
|
1055 |
+
{
|
1056 |
+
# check to see if the current inline type is nestable in the current context
|
1057 |
+
|
1058 |
+
if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables))
|
1059 |
+
{
|
1060 |
+
continue;
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
$Inline = $this->{'inline'.$inlineType}($Excerpt);
|
1064 |
+
|
1065 |
+
if ( ! isset($Inline))
|
1066 |
+
{
|
1067 |
+
continue;
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
# makes sure that the inline belongs to "our" marker
|
1071 |
+
|
1072 |
+
if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
|
1073 |
+
{
|
1074 |
+
continue;
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
# sets a default inline position
|
1078 |
+
|
1079 |
+
if ( ! isset($Inline['position']))
|
1080 |
+
{
|
1081 |
+
$Inline['position'] = $markerPosition;
|
1082 |
+
}
|
1083 |
+
|
1084 |
+
# cause the new element to 'inherit' our non nestables
|
1085 |
+
|
1086 |
+
foreach ($nonNestables as $non_nestable)
|
1087 |
+
{
|
1088 |
+
$Inline['element']['nonNestables'][] = $non_nestable;
|
1089 |
+
}
|
1090 |
+
|
1091 |
+
# the text that comes before the inline
|
1092 |
+
$unmarkedText = substr($text, 0, $Inline['position']);
|
1093 |
+
|
1094 |
+
# compile the unmarked text
|
1095 |
+
$markup .= $this->unmarkedText($unmarkedText);
|
1096 |
+
|
1097 |
+
# compile the inline
|
1098 |
+
$markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
|
1099 |
+
|
1100 |
+
# remove the examined text
|
1101 |
+
$text = substr($text, $Inline['position'] + $Inline['extent']);
|
1102 |
+
|
1103 |
+
continue 2;
|
1104 |
+
}
|
1105 |
+
|
1106 |
+
# the marker does not belong to an inline
|
1107 |
+
|
1108 |
+
$unmarkedText = substr($text, 0, $markerPosition + 1);
|
1109 |
+
|
1110 |
+
$markup .= $this->unmarkedText($unmarkedText);
|
1111 |
+
|
1112 |
+
$text = substr($text, $markerPosition + 1);
|
1113 |
+
}
|
1114 |
+
|
1115 |
+
$markup .= $this->unmarkedText($text);
|
1116 |
+
|
1117 |
+
return $markup;
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
#
|
1121 |
+
# ~
|
1122 |
+
#
|
1123 |
+
|
1124 |
+
protected function inlineCode($Excerpt)
|
1125 |
+
{
|
1126 |
+
$marker = $Excerpt['text'][0];
|
1127 |
+
|
1128 |
+
if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
|
1129 |
+
{
|
1130 |
+
$text = $matches[2];
|
1131 |
+
$text = preg_replace("/[ ]*\n/", ' ', $text);
|
1132 |
+
|
1133 |
+
return array(
|
1134 |
+
'extent' => strlen($matches[0]),
|
1135 |
+
'element' => array(
|
1136 |
+
'name' => 'code',
|
1137 |
+
'text' => $text,
|
1138 |
+
),
|
1139 |
+
);
|
1140 |
+
}
|
1141 |
+
}
|
1142 |
+
|
1143 |
+
protected function inlineEmailTag($Excerpt)
|
1144 |
+
{
|
1145 |
+
if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
|
1146 |
+
{
|
1147 |
+
$url = $matches[1];
|
1148 |
+
|
1149 |
+
if ( ! isset($matches[2]))
|
1150 |
+
{
|
1151 |
+
$url = 'mailto:' . $url;
|
1152 |
+
}
|
1153 |
+
|
1154 |
+
return array(
|
1155 |
+
'extent' => strlen($matches[0]),
|
1156 |
+
'element' => array(
|
1157 |
+
'name' => 'a',
|
1158 |
+
'text' => $matches[1],
|
1159 |
+
'attributes' => array(
|
1160 |
+
'href' => $url,
|
1161 |
+
),
|
1162 |
+
),
|
1163 |
+
);
|
1164 |
+
}
|
1165 |
+
}
|
1166 |
+
|
1167 |
+
protected function inlineEmphasis($Excerpt)
|
1168 |
+
{
|
1169 |
+
if ( ! isset($Excerpt['text'][1]))
|
1170 |
+
{
|
1171 |
+
return;
|
1172 |
+
}
|
1173 |
+
|
1174 |
+
$marker = $Excerpt['text'][0];
|
1175 |
+
|
1176 |
+
if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
|
1177 |
+
{
|
1178 |
+
$emphasis = 'strong';
|
1179 |
+
}
|
1180 |
+
elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
|
1181 |
+
{
|
1182 |
+
$emphasis = 'em';
|
1183 |
+
}
|
1184 |
+
else
|
1185 |
+
{
|
1186 |
+
return;
|
1187 |
+
}
|
1188 |
+
|
1189 |
+
return array(
|
1190 |
+
'extent' => strlen($matches[0]),
|
1191 |
+
'element' => array(
|
1192 |
+
'name' => $emphasis,
|
1193 |
+
'handler' => 'line',
|
1194 |
+
'text' => $matches[1],
|
1195 |
+
),
|
1196 |
+
);
|
1197 |
+
}
|
1198 |
+
|
1199 |
+
protected function inlineEscapeSequence($Excerpt)
|
1200 |
+
{
|
1201 |
+
if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
|
1202 |
+
{
|
1203 |
+
return array(
|
1204 |
+
'markup' => $Excerpt['text'][1],
|
1205 |
+
'extent' => 2,
|
1206 |
+
);
|
1207 |
+
}
|
1208 |
+
}
|
1209 |
+
|
1210 |
+
protected function inlineImage($Excerpt)
|
1211 |
+
{
|
1212 |
+
if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
|
1213 |
+
{
|
1214 |
+
return;
|
1215 |
+
}
|
1216 |
+
|
1217 |
+
$Excerpt['text']= substr($Excerpt['text'], 1);
|
1218 |
+
|
1219 |
+
$Link = $this->inlineLink($Excerpt);
|
1220 |
+
|
1221 |
+
if ($Link === null)
|
1222 |
+
{
|
1223 |
+
return;
|
1224 |
+
}
|
1225 |
+
|
1226 |
+
$Inline = array(
|
1227 |
+
'extent' => $Link['extent'] + 1,
|
1228 |
+
'element' => array(
|
1229 |
+
'name' => 'img',
|
1230 |
+
'attributes' => array(
|
1231 |
+
'src' => $Link['element']['attributes']['href'],
|
1232 |
+
'alt' => $Link['element']['text'],
|
1233 |
+
),
|
1234 |
+
),
|
1235 |
+
);
|
1236 |
+
|
1237 |
+
$Inline['element']['attributes'] += $Link['element']['attributes'];
|
1238 |
+
|
1239 |
+
unset($Inline['element']['attributes']['href']);
|
1240 |
+
|
1241 |
+
return $Inline;
|
1242 |
+
}
|
1243 |
+
|
1244 |
+
protected function inlineLink($Excerpt)
|
1245 |
+
{
|
1246 |
+
$Element = array(
|
1247 |
+
'name' => 'a',
|
1248 |
+
'handler' => 'line',
|
1249 |
+
'nonNestables' => array('Url', 'Link'),
|
1250 |
+
'text' => null,
|
1251 |
+
'attributes' => array(
|
1252 |
+
'href' => null,
|
1253 |
+
'title' => null,
|
1254 |
+
),
|
1255 |
+
);
|
1256 |
+
|
1257 |
+
$extent = 0;
|
1258 |
+
|
1259 |
+
$remainder = $Excerpt['text'];
|
1260 |
+
|
1261 |
+
if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
|
1262 |
+
{
|
1263 |
+
$Element['text'] = $matches[1];
|
1264 |
+
|
1265 |
+
$extent += strlen($matches[0]);
|
1266 |
+
|
1267 |
+
$remainder = substr($remainder, $extent);
|
1268 |
+
}
|
1269 |
+
else
|
1270 |
+
{
|
1271 |
+
return;
|
1272 |
+
}
|
1273 |
+
|
1274 |
+
if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches))
|
1275 |
+
{
|
1276 |
+
$Element['attributes']['href'] = $matches[1];
|
1277 |
+
|
1278 |
+
if (isset($matches[2]))
|
1279 |
+
{
|
1280 |
+
$Element['attributes']['title'] = substr($matches[2], 1, - 1);
|
1281 |
+
}
|
1282 |
+
|
1283 |
+
$extent += strlen($matches[0]);
|
1284 |
+
}
|
1285 |
+
else
|
1286 |
+
{
|
1287 |
+
if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
|
1288 |
+
{
|
1289 |
+
$definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
|
1290 |
+
$definition = strtolower($definition);
|
1291 |
+
|
1292 |
+
$extent += strlen($matches[0]);
|
1293 |
+
}
|
1294 |
+
else
|
1295 |
+
{
|
1296 |
+
$definition = strtolower($Element['text']);
|
1297 |
+
}
|
1298 |
+
|
1299 |
+
if ( ! isset($this->DefinitionData['Reference'][$definition]))
|
1300 |
+
{
|
1301 |
+
return;
|
1302 |
+
}
|
1303 |
+
|
1304 |
+
$Definition = $this->DefinitionData['Reference'][$definition];
|
1305 |
+
|
1306 |
+
$Element['attributes']['href'] = $Definition['url'];
|
1307 |
+
$Element['attributes']['title'] = $Definition['title'];
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
return array(
|
1311 |
+
'extent' => $extent,
|
1312 |
+
'element' => $Element,
|
1313 |
+
);
|
1314 |
+
}
|
1315 |
+
|
1316 |
+
protected function inlineMarkup($Excerpt)
|
1317 |
+
{
|
1318 |
+
if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)
|
1319 |
+
{
|
1320 |
+
return;
|
1321 |
+
}
|
1322 |
+
|
1323 |
+
if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*[ ]*>/s', $Excerpt['text'], $matches))
|
1324 |
+
{
|
1325 |
+
return array(
|
1326 |
+
'markup' => $matches[0],
|
1327 |
+
'extent' => strlen($matches[0]),
|
1328 |
+
);
|
1329 |
+
}
|
1330 |
+
|
1331 |
+
if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
|
1332 |
+
{
|
1333 |
+
return array(
|
1334 |
+
'markup' => $matches[0],
|
1335 |
+
'extent' => strlen($matches[0]),
|
1336 |
+
);
|
1337 |
+
}
|
1338 |
+
|
1339 |
+
if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
|
1340 |
+
{
|
1341 |
+
return array(
|
1342 |
+
'markup' => $matches[0],
|
1343 |
+
'extent' => strlen($matches[0]),
|
1344 |
+
);
|
1345 |
+
}
|
1346 |
+
}
|
1347 |
+
|
1348 |
+
protected function inlineSpecialCharacter($Excerpt)
|
1349 |
+
{
|
1350 |
+
if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
|
1351 |
+
{
|
1352 |
+
return array(
|
1353 |
+
'markup' => '&',
|
1354 |
+
'extent' => 1,
|
1355 |
+
);
|
1356 |
+
}
|
1357 |
+
|
1358 |
+
$SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
|
1359 |
+
|
1360 |
+
if (isset($SpecialCharacter[$Excerpt['text'][0]]))
|
1361 |
+
{
|
1362 |
+
return array(
|
1363 |
+
'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
|
1364 |
+
'extent' => 1,
|
1365 |
+
);
|
1366 |
+
}
|
1367 |
+
}
|
1368 |
+
|
1369 |
+
protected function inlineStrikethrough($Excerpt)
|
1370 |
+
{
|
1371 |
+
if ( ! isset($Excerpt['text'][1]))
|
1372 |
+
{
|
1373 |
+
return;
|
1374 |
+
}
|
1375 |
+
|
1376 |
+
if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
|
1377 |
+
{
|
1378 |
+
return array(
|
1379 |
+
'extent' => strlen($matches[0]),
|
1380 |
+
'element' => array(
|
1381 |
+
'name' => 'del',
|
1382 |
+
'text' => $matches[1],
|
1383 |
+
'handler' => 'line',
|
1384 |
+
),
|
1385 |
+
);
|
1386 |
+
}
|
1387 |
+
}
|
1388 |
+
|
1389 |
+
protected function inlineUrl($Excerpt)
|
1390 |
+
{
|
1391 |
+
if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
|
1392 |
+
{
|
1393 |
+
return;
|
1394 |
+
}
|
1395 |
+
|
1396 |
+
if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
|
1397 |
+
{
|
1398 |
+
$url = $matches[0][0];
|
1399 |
+
|
1400 |
+
$Inline = array(
|
1401 |
+
'extent' => strlen($matches[0][0]),
|
1402 |
+
'position' => $matches[0][1],
|
1403 |
+
'element' => array(
|
1404 |
+
'name' => 'a',
|
1405 |
+
'text' => $url,
|
1406 |
+
'attributes' => array(
|
1407 |
+
'href' => $url,
|
1408 |
+
),
|
1409 |
+
),
|
1410 |
+
);
|
1411 |
+
|
1412 |
+
return $Inline;
|
1413 |
+
}
|
1414 |
+
}
|
1415 |
+
|
1416 |
+
protected function inlineUrlTag($Excerpt)
|
1417 |
+
{
|
1418 |
+
if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
|
1419 |
+
{
|
1420 |
+
$url = $matches[1];
|
1421 |
+
|
1422 |
+
return array(
|
1423 |
+
'extent' => strlen($matches[0]),
|
1424 |
+
'element' => array(
|
1425 |
+
'name' => 'a',
|
1426 |
+
'text' => $url,
|
1427 |
+
'attributes' => array(
|
1428 |
+
'href' => $url,
|
1429 |
+
),
|
1430 |
+
),
|
1431 |
+
);
|
1432 |
+
}
|
1433 |
+
}
|
1434 |
+
|
1435 |
+
# ~
|
1436 |
+
|
1437 |
+
protected function unmarkedText($text)
|
1438 |
+
{
|
1439 |
+
if ($this->breaksEnabled)
|
1440 |
+
{
|
1441 |
+
$text = preg_replace('/[ ]*\n/', "<br />\n", $text);
|
1442 |
+
}
|
1443 |
+
else
|
1444 |
+
{
|
1445 |
+
$text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
|
1446 |
+
$text = str_replace(" \n", "\n", $text);
|
1447 |
+
}
|
1448 |
+
|
1449 |
+
return $text;
|
1450 |
+
}
|
1451 |
+
|
1452 |
+
#
|
1453 |
+
# Handlers
|
1454 |
+
#
|
1455 |
+
|
1456 |
+
protected function element(array $Element)
|
1457 |
+
{
|
1458 |
+
if ($this->safeMode)
|
1459 |
+
{
|
1460 |
+
$Element = $this->sanitiseElement($Element);
|
1461 |
+
}
|
1462 |
+
|
1463 |
+
$markup = '<'.$Element['name'];
|
1464 |
+
|
1465 |
+
if (isset($Element['attributes']))
|
1466 |
+
{
|
1467 |
+
foreach ($Element['attributes'] as $name => $value)
|
1468 |
+
{
|
1469 |
+
if ($value === null)
|
1470 |
+
{
|
1471 |
+
continue;
|
1472 |
+
}
|
1473 |
+
|
1474 |
+
$markup .= ' '.$name.'="'.self::escape($value).'"';
|
1475 |
+
}
|
1476 |
+
}
|
1477 |
+
|
1478 |
+
if (isset($Element['text']))
|
1479 |
+
{
|
1480 |
+
$markup .= '>';
|
1481 |
+
|
1482 |
+
if (!isset($Element['nonNestables']))
|
1483 |
+
{
|
1484 |
+
$Element['nonNestables'] = array();
|
1485 |
+
}
|
1486 |
+
|
1487 |
+
if (isset($Element['handler']))
|
1488 |
+
{
|
1489 |
+
$markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);
|
1490 |
+
}
|
1491 |
+
else
|
1492 |
+
{
|
1493 |
+
$markup .= self::escape($Element['text'], true);
|
1494 |
+
}
|
1495 |
+
|
1496 |
+
$markup .= '</'.$Element['name'].'>';
|
1497 |
+
}
|
1498 |
+
else
|
1499 |
+
{
|
1500 |
+
$markup .= ' />';
|
1501 |
+
}
|
1502 |
+
|
1503 |
+
return $markup;
|
1504 |
+
}
|
1505 |
+
|
1506 |
+
protected function elements(array $Elements)
|
1507 |
+
{
|
1508 |
+
$markup = '';
|
1509 |
+
|
1510 |
+
foreach ($Elements as $Element)
|
1511 |
+
{
|
1512 |
+
$markup .= "\n" . $this->element($Element);
|
1513 |
+
}
|
1514 |
+
|
1515 |
+
$markup .= "\n";
|
1516 |
+
|
1517 |
+
return $markup;
|
1518 |
+
}
|
1519 |
+
|
1520 |
+
# ~
|
1521 |
+
|
1522 |
+
protected function li($lines)
|
1523 |
+
{
|
1524 |
+
$markup = $this->lines($lines);
|
1525 |
+
|
1526 |
+
$trimmedMarkup = trim($markup);
|
1527 |
+
|
1528 |
+
if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
|
1529 |
+
{
|
1530 |
+
$markup = $trimmedMarkup;
|
1531 |
+
$markup = substr($markup, 3);
|
1532 |
+
|
1533 |
+
$position = strpos($markup, "</p>");
|
1534 |
+
|
1535 |
+
$markup = substr_replace($markup, '', $position, 4);
|
1536 |
+
}
|
1537 |
+
|
1538 |
+
return $markup;
|
1539 |
+
}
|
1540 |
+
|
1541 |
+
#
|
1542 |
+
# Deprecated Methods
|
1543 |
+
#
|
1544 |
+
|
1545 |
+
function parse($text)
|
1546 |
+
{
|
1547 |
+
$markup = $this->text($text);
|
1548 |
+
|
1549 |
+
return $markup;
|
1550 |
+
}
|
1551 |
+
|
1552 |
+
protected function sanitiseElement(array $Element)
|
1553 |
+
{
|
1554 |
+
static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
|
1555 |
+
static $safeUrlNameToAtt = array(
|
1556 |
+
'a' => 'href',
|
1557 |
+
'img' => 'src',
|
1558 |
+
);
|
1559 |
+
|
1560 |
+
if (isset($safeUrlNameToAtt[$Element['name']]))
|
1561 |
+
{
|
1562 |
+
$Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
|
1563 |
+
}
|
1564 |
+
|
1565 |
+
if ( ! empty($Element['attributes']))
|
1566 |
+
{
|
1567 |
+
foreach ($Element['attributes'] as $att => $val)
|
1568 |
+
{
|
1569 |
+
# filter out badly parsed attribute
|
1570 |
+
if ( ! preg_match($goodAttribute, $att))
|
1571 |
+
{
|
1572 |
+
unset($Element['attributes'][$att]);
|
1573 |
+
}
|
1574 |
+
# dump onevent attribute
|
1575 |
+
elseif (self::striAtStart($att, 'on'))
|
1576 |
+
{
|
1577 |
+
unset($Element['attributes'][$att]);
|
1578 |
+
}
|
1579 |
+
}
|
1580 |
+
}
|
1581 |
+
|
1582 |
+
return $Element;
|
1583 |
+
}
|
1584 |
+
|
1585 |
+
protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
|
1586 |
+
{
|
1587 |
+
foreach ($this->safeLinksWhitelist as $scheme)
|
1588 |
+
{
|
1589 |
+
if (self::striAtStart($Element['attributes'][$attribute], $scheme))
|
1590 |
+
{
|
1591 |
+
return $Element;
|
1592 |
+
}
|
1593 |
+
}
|
1594 |
+
|
1595 |
+
$Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
|
1596 |
+
|
1597 |
+
return $Element;
|
1598 |
+
}
|
1599 |
+
|
1600 |
+
#
|
1601 |
+
# Static Methods
|
1602 |
+
#
|
1603 |
+
|
1604 |
+
protected static function escape($text, $allowQuotes = false)
|
1605 |
+
{
|
1606 |
+
return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
|
1607 |
+
}
|
1608 |
+
|
1609 |
+
protected static function striAtStart($string, $needle)
|
1610 |
+
{
|
1611 |
+
$len = strlen($needle);
|
1612 |
+
|
1613 |
+
if ($len > strlen($string))
|
1614 |
+
{
|
1615 |
+
return false;
|
1616 |
+
}
|
1617 |
+
else
|
1618 |
+
{
|
1619 |
+
return strtolower(substr($string, 0, $len)) === strtolower($needle);
|
1620 |
+
}
|
1621 |
+
}
|
1622 |
+
|
1623 |
+
static function instance($name = 'default')
|
1624 |
+
{
|
1625 |
+
if (isset(self::$instances[$name]))
|
1626 |
+
{
|
1627 |
+
return self::$instances[$name];
|
1628 |
+
}
|
1629 |
+
|
1630 |
+
$instance = new static();
|
1631 |
+
|
1632 |
+
self::$instances[$name] = $instance;
|
1633 |
+
|
1634 |
+
return $instance;
|
1635 |
+
}
|
1636 |
+
|
1637 |
+
private static $instances = array();
|
1638 |
+
|
1639 |
+
#
|
1640 |
+
# Fields
|
1641 |
+
#
|
1642 |
+
|
1643 |
+
protected $DefinitionData;
|
1644 |
+
|
1645 |
+
#
|
1646 |
+
# Read-Only
|
1647 |
+
|
1648 |
+
protected $specialCharacters = array(
|
1649 |
+
'\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
|
1650 |
+
);
|
1651 |
+
|
1652 |
+
protected $StrongRegex = array(
|
1653 |
+
'*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
|
1654 |
+
'_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
|
1655 |
+
);
|
1656 |
+
|
1657 |
+
protected $EmRegex = array(
|
1658 |
+
'*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
|
1659 |
+
'_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
|
1660 |
+
);
|
1661 |
+
|
1662 |
+
protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
|
1663 |
+
|
1664 |
+
protected $voidElements = array(
|
1665 |
+
'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
|
1666 |
+
);
|
1667 |
+
|
1668 |
+
protected $textLevelElements = array(
|
1669 |
+
'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
|
1670 |
+
'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
|
1671 |
+
'i', 'rp', 'del', 'code', 'strike', 'marquee',
|
1672 |
+
'q', 'rt', 'ins', 'font', 'strong',
|
1673 |
+
's', 'tt', 'kbd', 'mark',
|
1674 |
+
'u', 'xm', 'sub', 'nobr',
|
1675 |
+
'sup', 'ruby',
|
1676 |
+
'var', 'span',
|
1677 |
+
'wbr', 'time',
|
1678 |
+
);
|
1679 |
+
}
|
includes/vendor/erusev/parsedown/README.md
CHANGED
@@ -1,86 +1,86 @@
|
|
1 |
-
> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac and PC.
|
2 |
-
|
3 |
-
## Parsedown
|
4 |
-
|
5 |
-
[![Build Status](https://img.shields.io/travis/erusev/parsedown/master.svg?style=flat-square)](https://travis-ci.org/erusev/parsedown)
|
6 |
-
<!--[![Total Downloads](http://img.shields.io/packagist/dt/erusev/parsedown.svg?style=flat-square)](https://packagist.org/packages/erusev/parsedown)-->
|
7 |
-
|
8 |
-
Better Markdown Parser in PHP
|
9 |
-
|
10 |
-
[Demo](http://parsedown.org/demo) |
|
11 |
-
[Benchmarks](http://parsedown.org/speed) |
|
12 |
-
[Tests](http://parsedown.org/tests/) |
|
13 |
-
[Documentation](https://github.com/erusev/parsedown/wiki/)
|
14 |
-
|
15 |
-
### Features
|
16 |
-
|
17 |
-
* One File
|
18 |
-
* No Dependencies
|
19 |
-
* Super Fast
|
20 |
-
* Extensible
|
21 |
-
* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
|
22 |
-
* Tested in 5.3 to 7.1 and in HHVM
|
23 |
-
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
|
24 |
-
|
25 |
-
### Installation
|
26 |
-
|
27 |
-
Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown).
|
28 |
-
|
29 |
-
### Example
|
30 |
-
|
31 |
-
``` php
|
32 |
-
$Parsedown = new Parsedown();
|
33 |
-
|
34 |
-
echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>
|
35 |
-
```
|
36 |
-
|
37 |
-
More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
|
38 |
-
|
39 |
-
### Security
|
40 |
-
|
41 |
-
Parsedown is capable of escaping user-input within the HTML that it generates. Additionally Parsedown will apply sanitisation to additional scripting vectors (such as scripting link destinations) that are introduced by the markdown syntax itself.
|
42 |
-
|
43 |
-
To tell Parsedown that it is processing untrusted user-input, use the following:
|
44 |
-
```php
|
45 |
-
$parsedown = new Parsedown;
|
46 |
-
$parsedown->setSafeMode(true);
|
47 |
-
```
|
48 |
-
|
49 |
-
If instead, you wish to allow HTML within untrusted user-input, but still want output to be free from XSS it is recommended that you make use of a HTML sanitiser that allows HTML tags to be whitelisted, like [HTML Purifier](http://htmlpurifier.org/).
|
50 |
-
|
51 |
-
In both cases you should strongly consider employing defence-in-depth measures, like [deploying a Content-Security-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/) (a browser security feature) so that your page is likely to be safe even if an attacker finds a vulnerability in one of the first lines of defence above.
|
52 |
-
|
53 |
-
#### Security of Parsedown Extensions
|
54 |
-
|
55 |
-
Safe mode does not necessarily yield safe results when using extensions to Parsedown. Extensions should be evaluated on their own to determine their specific safety against XSS.
|
56 |
-
|
57 |
-
### Escaping HTML
|
58 |
-
> ⚠️ **WARNING:** This method isn't safe from XSS!
|
59 |
-
|
60 |
-
If you wish to escape HTML **in trusted input**, you can use the following:
|
61 |
-
```php
|
62 |
-
$parsedown = new Parsedown;
|
63 |
-
$parsedown->setMarkupEscaped(true);
|
64 |
-
```
|
65 |
-
|
66 |
-
Beware that this still allows users to insert unsafe scripting vectors, such as links like `[xss](javascript:alert%281%29)`.
|
67 |
-
|
68 |
-
### Questions
|
69 |
-
|
70 |
-
**How does Parsedown work?**
|
71 |
-
|
72 |
-
It tries to read Markdown like a human. First, it looks at the lines. It’s interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line starts with a `-` then perhaps it belongs to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines).
|
73 |
-
|
74 |
-
We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages.
|
75 |
-
|
76 |
-
**Is it compliant with CommonMark?**
|
77 |
-
|
78 |
-
It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve.
|
79 |
-
|
80 |
-
**Who uses it?**
|
81 |
-
|
82 |
-
[Laravel Framework](https://laravel.com/), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [October CMS](http://octobercms.com/), [Pico CMS](http://picocms.org), [Statamic CMS](http://www.statamic.com/), [phpDocumentor](http://www.phpdoc.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
|
83 |
-
|
84 |
-
**How can I help?**
|
85 |
-
|
86 |
-
Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2).
|
1 |
+
> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac and PC.
|
2 |
+
|
3 |
+
## Parsedown
|
4 |
+
|
5 |
+
[![Build Status](https://img.shields.io/travis/erusev/parsedown/master.svg?style=flat-square)](https://travis-ci.org/erusev/parsedown)
|
6 |
+
<!--[![Total Downloads](http://img.shields.io/packagist/dt/erusev/parsedown.svg?style=flat-square)](https://packagist.org/packages/erusev/parsedown)-->
|
7 |
+
|
8 |
+
Better Markdown Parser in PHP
|
9 |
+
|
10 |
+
[Demo](http://parsedown.org/demo) |
|
11 |
+
[Benchmarks](http://parsedown.org/speed) |
|
12 |
+
[Tests](http://parsedown.org/tests/) |
|
13 |
+
[Documentation](https://github.com/erusev/parsedown/wiki/)
|
14 |
+
|
15 |
+
### Features
|
16 |
+
|
17 |
+
* One File
|
18 |
+
* No Dependencies
|
19 |
+
* Super Fast
|
20 |
+
* Extensible
|
21 |
+
* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
|
22 |
+
* Tested in 5.3 to 7.1 and in HHVM
|
23 |
+
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
|
24 |
+
|
25 |
+
### Installation
|
26 |
+
|
27 |
+
Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown).
|
28 |
+
|
29 |
+
### Example
|
30 |
+
|
31 |
+
``` php
|
32 |
+
$Parsedown = new Parsedown();
|
33 |
+
|
34 |
+
echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>
|
35 |
+
```
|
36 |
+
|
37 |
+
More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
|
38 |
+
|
39 |
+
### Security
|
40 |
+
|
41 |
+
Parsedown is capable of escaping user-input within the HTML that it generates. Additionally Parsedown will apply sanitisation to additional scripting vectors (such as scripting link destinations) that are introduced by the markdown syntax itself.
|
42 |
+
|
43 |
+
To tell Parsedown that it is processing untrusted user-input, use the following:
|
44 |
+
```php
|
45 |
+
$parsedown = new Parsedown;
|
46 |
+
$parsedown->setSafeMode(true);
|
47 |
+
```
|
48 |
+
|
49 |
+
If instead, you wish to allow HTML within untrusted user-input, but still want output to be free from XSS it is recommended that you make use of a HTML sanitiser that allows HTML tags to be whitelisted, like [HTML Purifier](http://htmlpurifier.org/).
|
50 |
+
|
51 |
+
In both cases you should strongly consider employing defence-in-depth measures, like [deploying a Content-Security-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/) (a browser security feature) so that your page is likely to be safe even if an attacker finds a vulnerability in one of the first lines of defence above.
|
52 |
+
|
53 |
+
#### Security of Parsedown Extensions
|
54 |
+
|
55 |
+
Safe mode does not necessarily yield safe results when using extensions to Parsedown. Extensions should be evaluated on their own to determine their specific safety against XSS.
|
56 |
+
|
57 |
+
### Escaping HTML
|
58 |
+
> ⚠️ **WARNING:** This method isn't safe from XSS!
|
59 |
+
|
60 |
+
If you wish to escape HTML **in trusted input**, you can use the following:
|
61 |
+
```php
|
62 |
+
$parsedown = new Parsedown;
|
63 |
+
$parsedown->setMarkupEscaped(true);
|
64 |
+
```
|
65 |
+
|
66 |
+
Beware that this still allows users to insert unsafe scripting vectors, such as links like `[xss](javascript:alert%281%29)`.
|
67 |
+
|
68 |
+
### Questions
|
69 |
+
|
70 |
+
**How does Parsedown work?**
|
71 |
+
|
72 |
+
It tries to read Markdown like a human. First, it looks at the lines. It’s interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line starts with a `-` then perhaps it belongs to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines).
|
73 |
+
|
74 |
+
We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages.
|
75 |
+
|
76 |
+
**Is it compliant with CommonMark?**
|
77 |
+
|
78 |
+
It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve.
|
79 |
+
|
80 |
+
**Who uses it?**
|
81 |
+
|
82 |
+
[Laravel Framework](https://laravel.com/), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [October CMS](http://octobercms.com/), [Pico CMS](http://picocms.org), [Statamic CMS](http://www.statamic.com/), [phpDocumentor](http://www.phpdoc.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
|
83 |
+
|
84 |
+
**How can I help?**
|
85 |
+
|
86 |
+
Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2).
|
includes/vendor/erusev/parsedown/composer.json
CHANGED
@@ -1,33 +1,33 @@
|
|
1 |
-
{
|
2 |
-
"name": "erusev/parsedown",
|
3 |
-
"description": "Parser for Markdown.",
|
4 |
-
"keywords": ["markdown", "parser"],
|
5 |
-
"homepage": "http://parsedown.org",
|
6 |
-
"type": "library",
|
7 |
-
"license": "MIT",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "Emanuil Rusev",
|
11 |
-
"email": "hello@erusev.com",
|
12 |
-
"homepage": "http://erusev.com"
|
13 |
-
}
|
14 |
-
],
|
15 |
-
"require": {
|
16 |
-
"php": ">=5.3.0",
|
17 |
-
"ext-mbstring": "*"
|
18 |
-
},
|
19 |
-
"require-dev": {
|
20 |
-
"phpunit/phpunit": "^4.8.35"
|
21 |
-
},
|
22 |
-
"autoload": {
|
23 |
-
"psr-0": {"Parsedown": ""}
|
24 |
-
},
|
25 |
-
"autoload-dev": {
|
26 |
-
"psr-0": {
|
27 |
-
"TestParsedown": "test/",
|
28 |
-
"ParsedownTest": "test/",
|
29 |
-
"CommonMarkTest": "test/",
|
30 |
-
"CommonMarkTestWeak": "test/"
|
31 |
-
}
|
32 |
-
}
|
33 |
-
}
|
1 |
+
{
|
2 |
+
"name": "erusev/parsedown",
|
3 |
+
"description": "Parser for Markdown.",
|
4 |
+
"keywords": ["markdown", "parser"],
|
5 |
+
"homepage": "http://parsedown.org",
|
6 |
+
"type": "library",
|
7 |
+
"license": "MIT",
|
8 |
+
"authors": [
|
9 |
+
{
|
10 |
+
"name": "Emanuil Rusev",
|
11 |
+
"email": "hello@erusev.com",
|
12 |
+
"homepage": "http://erusev.com"
|
13 |
+
}
|
14 |
+
],
|
15 |
+
"require": {
|
16 |
+
"php": ">=5.3.0",
|
17 |
+
"ext-mbstring": "*"
|
18 |
+
},
|
19 |
+
"require-dev": {
|
20 |
+
"phpunit/phpunit": "^4.8.35"
|
21 |
+
},
|
22 |
+
"autoload": {
|
23 |
+
"psr-0": {"Parsedown": ""}
|
24 |
+
},
|
25 |
+
"autoload-dev": {
|
26 |
+
"psr-0": {
|
27 |
+
"TestParsedown": "test/",
|
28 |
+
"ParsedownTest": "test/",
|
29 |
+
"CommonMarkTest": "test/",
|
30 |
+
"CommonMarkTestWeak": "test/"
|
31 |
+
}
|
32 |
+
}
|
33 |
+
}
|
includes/vendor/geoip2/geoip2/.gitmodules
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
[submodule "maxmind-db"]
|
2 |
-
path = maxmind-db
|
3 |
-
url = git://github.com/maxmind/MaxMind-DB.git
|
1 |
+
[submodule "maxmind-db"]
|
2 |
+
path = maxmind-db
|
3 |
+
url = git://github.com/maxmind/MaxMind-DB.git
|
includes/vendor/geoip2/geoip2/.php_cs
CHANGED
@@ -1,35 +1,35 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
return PhpCsFixer\Config::create()
|
4 |
-
->setRiskyAllowed(true)
|
5 |
-
->setRules([
|
6 |
-
'@Symfony' => true,
|
7 |
-
'@Symfony:risky' => true,
|
8 |
-
'array_syntax' => ['syntax' => 'short'],
|
9 |
-
'combine_consecutive_unsets' => true,
|
10 |
-
'concat_space' => [ 'spacing' => 'one'],
|
11 |
-
'heredoc_to_nowdoc' => true,
|
12 |
-
'increment_style' => false,
|
13 |
-
'list_syntax' => ['syntax' => 'long'],
|
14 |
-
'no_extra_consecutive_blank_lines' => ['break', 'continue', 'extra', 'return', 'throw', 'use', 'parenthesis_brace_block', 'square_brace_block', 'curly_brace_block'],
|
15 |
-
'no_short_echo_tag' => true,
|
16 |
-
'no_unreachable_default_argument_value' => true,
|
17 |
-
'no_useless_else' => true,
|
18 |
-
'no_useless_return' => true,
|
19 |
-
'ordered_imports' => true,
|
20 |
-
'pre_increment' => false,
|
21 |
-
'php_unit_strict' => true,
|
22 |
-
'php_unit_test_class_requires_covers' => true,
|
23 |
-
'phpdoc_add_missing_param_annotation' => true,
|
24 |
-
'phpdoc_no_alias_tag' => false,
|
25 |
-
'phpdoc_order' => true,
|
26 |
-
'semicolon_after_instruction' => true,
|
27 |
-
'strict_comparison' => true,
|
28 |
-
'strict_param' => true,
|
29 |
-
'yoda_style' => false,
|
30 |
-
])
|
31 |
-
->setFinder(
|
32 |
-
PhpCsFixer\Finder::create()
|
33 |
-
->in(__DIR__)
|
34 |
-
)
|
35 |
-
;
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return PhpCsFixer\Config::create()
|
4 |
+
->setRiskyAllowed(true)
|
5 |
+
->setRules([
|
6 |
+
'@Symfony' => true,
|
7 |
+
'@Symfony:risky' => true,
|
8 |
+
'array_syntax' => ['syntax' => 'short'],
|
9 |
+
'combine_consecutive_unsets' => true,
|
10 |
+
'concat_space' => [ 'spacing' => 'one'],
|
11 |
+
'heredoc_to_nowdoc' => true,
|
12 |
+
'increment_style' => false,
|
13 |
+
'list_syntax' => ['syntax' => 'long'],
|
14 |
+
'no_extra_consecutive_blank_lines' => ['break', 'continue', 'extra', 'return', 'throw', 'use', 'parenthesis_brace_block', 'square_brace_block', 'curly_brace_block'],
|
15 |
+
'no_short_echo_tag' => true,
|
16 |
+
'no_unreachable_default_argument_value' => true,
|
17 |
+
'no_useless_else' => true,
|
18 |
+
'no_useless_return' => true,
|
19 |
+
'ordered_imports' => true,
|
20 |
+
'pre_increment' => false,
|
21 |
+
'php_unit_strict' => true,
|
22 |
+
'php_unit_test_class_requires_covers' => true,
|
23 |
+
'phpdoc_add_missing_param_annotation' => true,
|
24 |
+
'phpdoc_no_alias_tag' => false,
|
25 |
+
'phpdoc_order' => true,
|
26 |
+
'semicolon_after_instruction' => true,
|
27 |
+
'strict_comparison' => true,
|
28 |
+
'strict_param' => true,
|
29 |
+
'yoda_style' => false,
|
30 |
+
])
|
31 |
+
->setFinder(
|
32 |
+
PhpCsFixer\Finder::create()
|
33 |
+
->in(__DIR__)
|
34 |
+
)
|
35 |
+
;
|
includes/vendor/geoip2/geoip2/CHANGELOG.md
CHANGED
@@ -1,262 +1,262 @@
|
|
1 |
-
CHANGELOG
|
2 |
-
=========
|
3 |
-
|
4 |
-
2.9.0 (2018-04-10)
|
5 |
-
------------------
|
6 |
-
|
7 |
-
* Refer to account IDs using the terminology "account" rather than "user".
|
8 |
-
|
9 |
-
2.8.0 (2018-01-18)
|
10 |
-
------------------
|
11 |
-
|
12 |
-
* The `isInEuropeanUnion` property was added to `GeoIp2\Record\Country`
|
13 |
-
and `GeoIp2\Record\RepresentedCountry`. This property is `true` if the
|
14 |
-
country is a member state of the European Union.
|
15 |
-
|
16 |
-
2.7.0 (2017-10-27)
|
17 |
-
------------------
|
18 |
-
|
19 |
-
* The following new anonymizer properties were added to `GeoIp2\Record\Traits`
|
20 |
-
for use with GeoIP2 Precision Insights: `isAnonymous`, `isAnonymousVpn`,
|
21 |
-
`isHostingProvider`, `isPublicProxy`, and `isTorExitNode`.
|
22 |
-
|
23 |
-
2.6.0 (2017-07-10)
|
24 |
-
-----------------
|
25 |
-
|
26 |
-
* Code clean-up and tidying.
|
27 |
-
* Set minimum required PHP version to 5.4 in `composer.json`. Previously,
|
28 |
-
5.3 would work but was not tested. Now 5.4 is hard minimum version.
|
29 |
-
|
30 |
-
2.5.0 (2017-05-08)
|
31 |
-
------------------
|
32 |
-
|
33 |
-
* Support for PHP 5.3 was dropped.
|
34 |
-
* Added support for GeoLite2 ASN database.
|
35 |
-
|
36 |
-
2.4.5 (2017-01-31)
|
37 |
-
------------------
|
38 |
-
|
39 |
-
* Additional error checking on the data returned from `MaxMind\Db\Reader`
|
40 |
-
was added to help detect corrupt databases. GitHub #83.
|
41 |
-
|
42 |
-
2.4.4 (2016-10-11)
|
43 |
-
------------------
|
44 |
-
|
45 |
-
* `isset()` on `mostSpecificSubdivision` attribute now returns the
|
46 |
-
correct value. Reported by Juan Francisco Giordana. GitHub #81.
|
47 |
-
|
48 |
-
2.4.3 (2016-10-11)
|
49 |
-
------------------
|
50 |
-
|
51 |
-
* `isset()` on `name` attribute now returns the correct value. Reported by
|
52 |
-
Juan Francisco Giordana. GitHub #79.
|
53 |
-
|
54 |
-
2.4.2 (2016-08-17)
|
55 |
-
------------------
|
56 |
-
|
57 |
-
* Updated documentation to clarify what the accuracy radius refers to.
|
58 |
-
* Upgraded `maxmind/web-service-common` to 0.3.0. This version uses
|
59 |
-
`composer/ca-bundle` rather than our own CA bundle. GitHub #75.
|
60 |
-
* Improved PHP documentation generation.
|
61 |
-
|
62 |
-
2.4.1 (2016-06-10)
|
63 |
-
------------------
|
64 |
-
|
65 |
-
* Corrected type annotations in documentation. GitHub #66.
|
66 |
-
* Updated documentation to reflect that the accuracy radius is now included
|
67 |
-
in City.
|
68 |
-
* Upgraded web service client, which supports setting a proxy. GitHub #59.
|
69 |
-
|
70 |
-
2.4.0 (2016-04-15)
|
71 |
-
------------------
|
72 |
-
|
73 |
-
* Added support for the GeoIP2 Enterprise database.
|
74 |
-
|
75 |
-
2.3.3 (2015-09-24)
|
76 |
-
------------------
|
77 |
-
|
78 |
-
* Corrected case on `JsonSerializable` interface. Reported by Axel Etcheverry.
|
79 |
-
GitHub #56.
|
80 |
-
|
81 |
-
2.3.2 (2015-09-23)
|
82 |
-
------------------
|
83 |
-
|
84 |
-
* `JsonSerializable` compatibility interface was moved to `GeoIp2\Compat`
|
85 |
-
rather than the global namespace to prevent autoloading issues. Reported by
|
86 |
-
Tomas Buteler. GitHub #54.
|
87 |
-
* Missing documentation for the `$postal` property was added to the
|
88 |
-
`GeoIp2\Model\City` class. Fix by Roy Sindre Norangshol. GitHub #51.
|
89 |
-
* In the Phar distribution, source files for this module no longer have their
|
90 |
-
documentation stripped, allowing IDE introspection to work properly.
|
91 |
-
Reported by Dominic Black. GitHub #52.
|
92 |
-
|
93 |
-
2.3.1 (2015-06-30)
|
94 |
-
------------------
|
95 |
-
|
96 |
-
* Updated `maxmind/web-service-common` to version with fixes for PHP 5.3 and
|
97 |
-
5.4.
|
98 |
-
|
99 |
-
2.3.0 (2015-06-29)
|
100 |
-
------------------
|
101 |
-
|
102 |
-
* Support for demographics fields `averageIncome` and `populationDensity` in
|
103 |
-
the `Location` record, returned by the Insights endpoint.
|
104 |
-
* The `isAnonymousProxy` and `isSatelliteProvider` properties on
|
105 |
-
`GeoIP2\Record\Traits` have been deprecated. Please use our [GeoIP2
|
106 |
-
Anonymous IP database](https://www.maxmind.com/en/geoip2-anonymous-ip-database)
|
107 |
-
to determine whether an IP address is used by an anonymizing service.
|
108 |
-
|
109 |
-
2.2.0-beta1 (2015-06-09)
|
110 |
-
------------------------
|
111 |
-
|
112 |
-
* Typo fix in documentation.
|
113 |
-
|
114 |
-
2.2.0-alpha2 (2015-06-01)
|
115 |
-
-------------------------
|
116 |
-
|
117 |
-
* `maxmind-ws/web-service-common` was renamed to `maxmind/web-service-common`.
|
118 |
-
|
119 |
-
2.2.0-alpha1 (2015-05-22)
|
120 |
-
-------------------------
|
121 |
-
|
122 |
-
* The library no longer uses Guzzle and instead uses curl directly.
|
123 |
-
* Support for `timeout` and `connectTimout` were added to the `$options` array
|
124 |
-
passed to the `GeoIp2\WebService\Client` constructor. Pull request by Will
|
125 |
-
Bradley. GitHub #36.
|
126 |
-
|
127 |
-
2.1.1 (2014-12-03)
|
128 |
-
------------------
|
129 |
-
|
130 |
-
* The 2.1.0 Phar builds included a shebang line, causing issues when loading
|
131 |
-
it as a library. This has been corrected. GitHub #33.
|
132 |
-
|
133 |
-
2.1.0 (2014-10-29)
|
134 |
-
------------------
|
135 |
-
|
136 |
-
* Update ApiGen dependency to version that isn't broken on case sensitive
|
137 |
-
file systems.
|
138 |
-
* Added support for the GeoIP2 Anonymous IP database. The
|
139 |
-
`GeoIP2\Database\Reader` class now has an `anonymousIp` method which returns
|
140 |
-
a `GeoIP2\Model\AnonymousIp` object.
|
141 |
-
* Boolean attributes like those in the `GeoIP2\Record\Traits` class now return
|
142 |
-
`false` instead of `null` when they were not true.
|
143 |
-
|
144 |
-
2.0.0 (2014-09-22)
|
145 |
-
------------------
|
146 |
-
|
147 |
-
* First production release.
|
148 |
-
|
149 |
-
0.9.0 (2014-09-15)
|
150 |
-
------------------
|
151 |
-
|
152 |
-
* IMPORTANT: The deprecated `omni()` and `cityIspOrg()` methods have been
|
153 |
-
removed from `GeoIp2\WebService\Client`.
|
154 |
-
|
155 |
-
0.8.1 (2014-09-12)
|
156 |
-
------------------
|
157 |
-
|
158 |
-
* The check added to the `GeoIP2\Database\Reader` lookup methods in 0.8.0 did
|
159 |
-
not work with the GeoIP2 City Database Subset by Continent with World
|
160 |
-
Countries. This has been fixed. Fixes GitHub issue #23.
|
161 |
-
|
162 |
-
0.8.0 (2014-09-10)
|
163 |
-
------------------
|
164 |
-
|
165 |
-
* The `GeoIp2\Database\Reader` lookup methods (e.g., `city()`, `isp()`) now
|
166 |
-
throw a `BadMethodCallException` if they are used with a database that
|
167 |
-
does not match the method. In particular, doing a `city()` lookup on a
|
168 |
-
GeoIP2 Country database will result in an exception, and vice versa.
|
169 |
-
* A `metadata()` method has been added to the `GeoIP2\Database\Reader` class.
|
170 |
-
This returns a `MaxMind\Db\Reader\Metadata` class with information about the
|
171 |
-
database.
|
172 |
-
* The name attribute was missing from the RepresentedCountry class.
|
173 |
-
|
174 |
-
0.7.0 (2014-07-22)
|
175 |
-
------------------
|
176 |
-
|
177 |
-
* The web service client API has been updated for the v2.1 release of the web
|
178 |
-
service. In particular, the `cityIspOrg` and `omni` methods on
|
179 |
-
`GeoIp2\WebService\Client` should be considered deprecated. The `city`
|
180 |
-
method now provides all of the data formerly provided by `cityIspOrg`, and
|
181 |
-
the `omni` method has been replaced by the `insights` method.
|
182 |
-
* Support was added for GeoIP2 Connection Type, Domain and ISP databases.
|
183 |
-
|
184 |
-
|
185 |
-
0.6.3 (2014-05-12)
|
186 |
-
------------------
|
187 |
-
|
188 |
-
* With the previous Phar builds, some users received `phar error: invalid url
|
189 |
-
or non-existent phar` errors. The correct alias is now used for the Phar,
|
190 |
-
and this should no longer be an issue.
|
191 |
-
|
192 |
-
0.6.2 (2014-05-08)
|
193 |
-
------------------
|
194 |
-
|
195 |
-
* The Phar build was broken with Guzzle 3.9.0+. This has been fixed.
|
196 |
-
|
197 |
-
0.6.1 (2014-05-01)
|
198 |
-
------------------
|
199 |
-
|
200 |
-
* This API now officially supports HHVM.
|
201 |
-
* The `maxmind-db/reader` dependency was updated to a version that does not
|
202 |
-
require BC Math.
|
203 |
-
* The Composer compatibility autoload rules are now targeted more narrowly.
|
204 |
-
* A `box.json` file is included to build a Phar package.
|
205 |
-
|
206 |
-
0.6.0 (2014-02-19)
|
207 |
-
------------------
|
208 |
-
|
209 |
-
* This API is now licensed under the Apache License, Version 2.0.
|
210 |
-
* Model and record classes now implement `JsonSerializable`.
|
211 |
-
* `isset` now works with model and record classes.
|
212 |
-
|
213 |
-
0.5.0 (2013-10-21)
|
214 |
-
------------------
|
215 |
-
|
216 |
-
* Renamed $languages constructor parameters to $locales for both the Client
|
217 |
-
and Reader classes.
|
218 |
-
* Documentation and code clean-up (Ben Morel).
|
219 |
-
* Added the interface `GeoIp2\ProviderInterface`, which is implemented by both
|
220 |
-
`\GeoIp2\Database\Reader` and `\GeoIp2\WebService\Client`.
|
221 |
-
|
222 |
-
0.4.0 (2013-07-16)
|
223 |
-
------------------
|
224 |
-
|
225 |
-
* This is the first release with the GeoIP2 database reader. Please see the
|
226 |
-
`README.md` file and the `\GeoIp2\Database\Reader` class.
|
227 |
-
* The general exception classes were replaced with specific exception classes
|
228 |
-
representing particular types of errors, such as an authentication error.
|
229 |
-
|
230 |
-
0.3.0 (2013-07-12)
|
231 |
-
------------------
|
232 |
-
|
233 |
-
* In namespaces and class names, "GeoIP2" was renamed to "GeoIp2" to improve
|
234 |
-
consistency.
|
235 |
-
|
236 |
-
0.2.1 (2013-06-10)
|
237 |
-
------------------
|
238 |
-
|
239 |
-
* First official beta release.
|
240 |
-
* Documentation updates and corrections.
|
241 |
-
|
242 |
-
0.2.0 (2013-05-29)
|
243 |
-
------------------
|
244 |
-
|
245 |
-
* `GenericException` was renamed to `GeoIP2Exception`.
|
246 |
-
* We now support more languages. The new languages are de, es, fr, and pt-BR.
|
247 |
-
* The REST API now returns a record with data about your account. There is
|
248 |
-
a new `GeoIP\Records\MaxMind` class for this data.
|
249 |
-
* The `continentCode` attribute on `Continent` was renamed to `code`.
|
250 |
-
* Documentation updates.
|
251 |
-
|
252 |
-
0.1.1 (2013-05-14)
|
253 |
-
------------------
|
254 |
-
|
255 |
-
* Updated Guzzle version requirement.
|
256 |
-
* Fixed Composer example in README.md.
|
257 |
-
|
258 |
-
|
259 |
-
0.1.0 (2013-05-13)
|
260 |
-
------------------
|
261 |
-
|
262 |
-
* Initial release.
|
1 |
+
CHANGELOG
|
2 |
+
=========
|
3 |
+
|
4 |
+
2.9.0 (2018-04-10)
|
5 |
+
------------------
|
6 |
+
|
7 |
+
* Refer to account IDs using the terminology "account" rather than "user".
|
8 |
+
|
9 |
+
2.8.0 (2018-01-18)
|
10 |
+
------------------
|
11 |
+
|
12 |
+
* The `isInEuropeanUnion` property was added to `GeoIp2\Record\Country`
|
13 |
+
and `GeoIp2\Record\RepresentedCountry`. This property is `true` if the
|
14 |
+
country is a member state of the European Union.
|
15 |
+
|
16 |
+
2.7.0 (2017-10-27)
|
17 |
+
------------------
|
18 |
+
|
19 |
+
* The following new anonymizer properties were added to `GeoIp2\Record\Traits`
|
20 |
+
for use with GeoIP2 Precision Insights: `isAnonymous`, `isAnonymousVpn`,
|
21 |
+
`isHostingProvider`, `isPublicProxy`, and `isTorExitNode`.
|
22 |
+
|
23 |
+
2.6.0 (2017-07-10)
|
24 |
+
-----------------
|
25 |
+
|
26 |
+
* Code clean-up and tidying.
|
27 |
+
* Set minimum required PHP version to 5.4 in `composer.json`. Previously,
|
28 |
+
5.3 would work but was not tested. Now 5.4 is hard minimum version.
|
29 |
+
|
30 |
+
2.5.0 (2017-05-08)
|
31 |
+
------------------
|
32 |
+
|
33 |
+
* Support for PHP 5.3 was dropped.
|
34 |
+
* Added support for GeoLite2 ASN database.
|
35 |
+
|
36 |
+
2.4.5 (2017-01-31)
|
37 |
+
------------------
|
38 |
+
|
39 |
+
* Additional error checking on the data returned from `MaxMind\Db\Reader`
|
40 |
+
was added to help detect corrupt databases. GitHub #83.
|
41 |
+
|
42 |
+
2.4.4 (2016-10-11)
|
43 |
+
------------------
|
44 |
+
|
45 |
+
* `isset()` on `mostSpecificSubdivision` attribute now returns the
|
46 |
+
correct value. Reported by Juan Francisco Giordana. GitHub #81.
|
47 |
+
|
48 |
+
2.4.3 (2016-10-11)
|
49 |
+
------------------
|
50 |
+
|
51 |
+
* `isset()` on `name` attribute now returns the correct value. Reported by
|
52 |
+
Juan Francisco Giordana. GitHub #79.
|
53 |
+
|
54 |
+
2.4.2 (2016-08-17)
|
55 |
+
------------------
|
56 |
+
|
57 |
+
* Updated documentation to clarify what the accuracy radius refers to.
|
58 |
+
* Upgraded `maxmind/web-service-common` to 0.3.0. This version uses
|
59 |
+
`composer/ca-bundle` rather than our own CA bundle. GitHub #75.
|
60 |
+
* Improved PHP documentation generation.
|
61 |
+
|
62 |
+
2.4.1 (2016-06-10)
|
63 |
+
------------------
|
64 |
+
|
65 |
+
* Corrected type annotations in documentation. GitHub #66.
|
66 |
+
* Updated documentation to reflect that the accuracy radius is now included
|
67 |
+
in City.
|
68 |
+
* Upgraded web service client, which supports setting a proxy. GitHub #59.
|
69 |
+
|
70 |
+
2.4.0 (2016-04-15)
|
71 |
+
------------------
|
72 |
+
|
73 |
+
* Added support for the GeoIP2 Enterprise database.
|
74 |
+
|
75 |
+
2.3.3 (2015-09-24)
|
76 |
+
------------------
|
77 |
+
|
78 |
+
* Corrected case on `JsonSerializable` interface. Reported by Axel Etcheverry.
|
79 |
+
GitHub #56.
|
80 |
+
|
81 |
+
2.3.2 (2015-09-23)
|
82 |
+
------------------
|
83 |
+
|
84 |
+
* `JsonSerializable` compatibility interface was moved to `GeoIp2\Compat`
|
85 |
+
rather than the global namespace to prevent autoloading issues. Reported by
|
86 |
+
Tomas Buteler. GitHub #54.
|
87 |
+
* Missing documentation for the `$postal` property was added to the
|
88 |
+
`GeoIp2\Model\City` class. Fix by Roy Sindre Norangshol. GitHub #51.
|
89 |
+
* In the Phar distribution, source files for this module no longer have their
|
90 |
+
documentation stripped, allowing IDE introspection to work properly.
|
91 |
+
Reported by Dominic Black. GitHub #52.
|
92 |
+
|
93 |
+
2.3.1 (2015-06-30)
|
94 |
+
------------------
|
95 |
+
|
96 |
+
* Updated `maxmind/web-service-common` to version with fixes for PHP 5.3 and
|
97 |
+
5.4.
|
98 |
+
|
99 |
+
2.3.0 (2015-06-29)
|
100 |
+
------------------
|
101 |
+
|
102 |
+
* Support for demographics fields `averageIncome` and `populationDensity` in
|
103 |
+
the `Location` record, returned by the Insights endpoint.
|
104 |
+
* The `isAnonymousProxy` and `isSatelliteProvider` properties on
|
105 |
+
`GeoIP2\Record\Traits` have been deprecated. Please use our [GeoIP2
|
106 |
+
Anonymous IP database](https://www.maxmind.com/en/geoip2-anonymous-ip-database)
|
107 |
+
to determine whether an IP address is used by an anonymizing service.
|
108 |
+
|
109 |
+
2.2.0-beta1 (2015-06-09)
|
110 |
+
------------------------
|
111 |
+
|
112 |
+
* Typo fix in documentation.
|
113 |
+
|
114 |
+
2.2.0-alpha2 (2015-06-01)
|
115 |
+
-------------------------
|
116 |
+
|
117 |
+
* `maxmind-ws/web-service-common` was renamed to `maxmind/web-service-common`.
|
118 |
+
|
119 |
+
2.2.0-alpha1 (2015-05-22)
|
120 |
+
-------------------------
|
121 |
+
|
122 |
+
* The library no longer uses Guzzle and instead uses curl directly.
|
123 |
+
* Support for `timeout` and `connectTimout` were added to the `$options` array
|
124 |
+
passed to the `GeoIp2\WebService\Client` constructor. Pull request by Will
|
125 |
+
Bradley. GitHub #36.
|
126 |
+
|
127 |
+
2.1.1 (2014-12-03)
|
128 |
+
------------------
|
129 |
+
|
130 |
+
* The 2.1.0 Phar builds included a shebang line, causing issues when loading
|
131 |
+
it as a library. This has been corrected. GitHub #33.
|
132 |
+
|
133 |
+
2.1.0 (2014-10-29)
|
134 |
+
------------------
|
135 |
+
|
136 |
+
* Update ApiGen dependency to version that isn't broken on case sensitive
|
137 |
+
file systems.
|
138 |
+
* Added support for the GeoIP2 Anonymous IP database. The
|
139 |
+
`GeoIP2\Database\Reader` class now has an `anonymousIp` method which returns
|
140 |
+
a `GeoIP2\Model\AnonymousIp` object.
|
141 |
+
* Boolean attributes like those in the `GeoIP2\Record\Traits` class now return
|
142 |
+
`false` instead of `null` when they were not true.
|
143 |
+
|
144 |
+
2.0.0 (2014-09-22)
|
145 |
+
------------------
|
146 |
+
|
147 |
+
* First production release.
|
148 |
+
|
149 |
+
0.9.0 (2014-09-15)
|
150 |
+
------------------
|
151 |
+
|
152 |
+
* IMPORTANT: The deprecated `omni()` and `cityIspOrg()` methods have been
|
153 |
+
removed from `GeoIp2\WebService\Client`.
|
154 |
+
|
155 |
+
0.8.1 (2014-09-12)
|
156 |
+
------------------
|
157 |
+
|
158 |
+
* The check added to the `GeoIP2\Database\Reader` lookup methods in 0.8.0 did
|
159 |
+
not work with the GeoIP2 City Database Subset by Continent with World
|
160 |
+
Countries. This has been fixed. Fixes GitHub issue #23.
|
161 |
+
|
162 |
+
0.8.0 (2014-09-10)
|
163 |
+
------------------
|
164 |
+
|
165 |
+
* The `GeoIp2\Database\Reader` lookup methods (e.g., `city()`, `isp()`) now
|
166 |
+
throw a `BadMethodCallException` if they are used with a database that
|
167 |
+
does not match the method. In particular, doing a `city()` lookup on a
|
168 |
+
GeoIP2 Country database will result in an exception, and vice versa.
|
169 |
+
* A `metadata()` method has been added to the `GeoIP2\Database\Reader` class.
|
170 |
+
This returns a `MaxMind\Db\Reader\Metadata` class with information about the
|
171 |
+
database.
|
172 |
+
* The name attribute was missing from the RepresentedCountry class.
|
173 |
+
|
174 |
+
0.7.0 (2014-07-22)
|
175 |
+
------------------
|
176 |
+
|
177 |
+
* The web service client API has been updated for the v2.1 release of the web
|
178 |
+
service. In particular, the `cityIspOrg` and `omni` methods on
|
179 |
+
`GeoIp2\WebService\Client` should be considered deprecated. The `city`
|
180 |
+
method now provides all of the data formerly provided by `cityIspOrg`, and
|
181 |
+
the `omni` method has been replaced by the `insights` method.
|
182 |
+
* Support was added for GeoIP2 Connection Type, Domain and ISP databases.
|
183 |
+
|
184 |
+
|
185 |
+
0.6.3 (2014-05-12)
|
186 |
+
------------------
|
187 |
+
|
188 |
+
* With the previous Phar builds, some users received `phar error: invalid url
|
189 |
+
or non-existent phar` errors. The correct alias is now used for the Phar,
|
190 |
+
and this should no longer be an issue.
|
191 |
+
|
192 |
+
0.6.2 (2014-05-08)
|
193 |
+
------------------
|
194 |
+
|
195 |
+
* The Phar build was broken with Guzzle 3.9.0+. This has been fixed.
|
196 |
+
|
197 |
+
0.6.1 (2014-05-01)
|
198 |
+
------------------
|
199 |
+
|
200 |
+
* This API now officially supports HHVM.
|
201 |
+
* The `maxmind-db/reader` dependency was updated to a version that does not
|
202 |
+
require BC Math.
|
203 |
+
* The Composer compatibility autoload rules are now targeted more narrowly.
|
204 |
+
* A `box.json` file is included to build a Phar package.
|
205 |
+
|
206 |
+
0.6.0 (2014-02-19)
|
207 |
+
------------------
|
208 |
+
|
209 |
+
* This API is now licensed under the Apache License, Version 2.0.
|
210 |
+
* Model and record classes now implement `JsonSerializable`.
|
211 |
+
* `isset` now works with model and record classes.
|
212 |
+
|
213 |
+
0.5.0 (2013-10-21)
|
214 |
+
------------------
|
215 |
+
|
216 |
+
* Renamed $languages constructor parameters to $locales for both the Client
|
217 |
+
and Reader classes.
|
218 |
+
* Documentation and code clean-up (Ben Morel).
|
219 |
+
* Added the interface `GeoIp2\ProviderInterface`, which is implemented by both
|
220 |
+
`\GeoIp2\Database\Reader` and `\GeoIp2\WebService\Client`.
|
221 |
+
|
222 |
+
0.4.0 (2013-07-16)
|
223 |
+
------------------
|
224 |
+
|
225 |
+
* This is the first release with the GeoIP2 database reader. Please see the
|
226 |
+
`README.md` file and the `\GeoIp2\Database\Reader` class.
|
227 |
+
* The general exception classes were replaced with specific exception classes
|
228 |
+
representing particular types of errors, such as an authentication error.
|
229 |
+
|
230 |
+
0.3.0 (2013-07-12)
|
231 |
+
------------------
|
232 |
+
|
233 |
+
* In namespaces and class names, "GeoIP2" was renamed to "GeoIp2" to improve
|
234 |
+
consistency.
|
235 |
+
|
236 |
+
0.2.1 (2013-06-10)
|
237 |
+
------------------
|
238 |
+
|
239 |
+
* First official beta release.
|
240 |
+
* Documentation updates and corrections.
|
241 |
+
|
242 |
+
0.2.0 (2013-05-29)
|
243 |
+
------------------
|
244 |
+
|
245 |
+
* `GenericException` was renamed to `GeoIP2Exception`.
|
246 |
+
* We now support more languages. The new languages are de, es, fr, and pt-BR.
|
247 |
+
* The REST API now returns a record with data about your account. There is
|
248 |
+
a new `GeoIP\Records\MaxMind` class for this data.
|
249 |
+
* The `continentCode` attribute on `Continent` was renamed to `code`.
|
250 |
+
* Documentation updates.
|
251 |
+
|
252 |
+
0.1.1 (2013-05-14)
|
253 |
+
------------------
|
254 |
+
|
255 |
+
* Updated Guzzle version requirement.
|
256 |
+
* Fixed Composer example in README.md.
|
257 |
+
|
258 |
+
|
259 |
+
0.1.0 (2013-05-13)
|
260 |
+
------------------
|
261 |
+
|
262 |
+
* Initial release.
|
includes/vendor/geoip2/geoip2/LICENSE
CHANGED
@@ -1,202 +1,202 @@
|
|
1 |
-
|
2 |
-
Apache License
|
3 |
-
Version 2.0, January 2004
|
4 |
-
http://www.apache.org/licenses/
|
5 |
-
|
6 |
-
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
7 |
-
|
8 |
-
1. Definitions.
|
9 |
-
|
10 |
-
"License" shall mean the terms and conditions for use, reproduction,
|
11 |
-
and distribution as defined by Sections 1 through 9 of this document.
|
12 |
-
|
13 |
-
"Licensor" shall mean the copyright owner or entity authorized by
|
14 |
-
the copyright owner that is granting the License.
|
15 |
-
|
16 |
-
"Legal Entity" shall mean the union of the acting entity and all
|
17 |
-
other entities that control, are controlled by, or are under common
|
18 |
-
control with that entity. For the purposes of this definition,
|
19 |
-
"control" means (i) the power, direct or indirect, to cause the
|
20 |
-
direction or management of such entity, whether by contract or
|
21 |
-
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
22 |
-
outstanding shares, or (iii) beneficial ownership of such entity.
|
23 |
-
|
24 |
-
"You" (or "Your") shall mean an individual or Legal Entity
|
25 |
-
exercising permissions granted by this License.
|
26 |
-
|
27 |
-
"Source" form shall mean the preferred form for making modifications,
|
28 |
-
including but not limited to software source code, documentation
|
29 |
-
source, and configuration files.
|
30 |
-
|
31 |
-
"Object" form shall mean any form resulting from mechanical
|
32 |
-
transformation or translation of a Source form, including but
|
33 |
-
not limited to compiled object code, generated documentation,
|
34 |
-
and conversions to other media types.
|
35 |
-
|
36 |
-
"Work" shall mean the work of authorship, whether in Source or
|
37 |
-
Object form, made available under the License, as indicated by a
|
38 |
-
copyright notice that is included in or attached to the work
|
39 |
-
(an example is provided in the Appendix below).
|
40 |
-
|
41 |
-
"Derivative Works" shall mean any work, whether in Source or Object
|
42 |
-
form, that is based on (or derived from) the Work and for which the
|
43 |
-
editorial revisions, annotations, elaborations, or other modifications
|
44 |
-
represent, as a whole, an original work of authorship. For the purposes
|
45 |
-
of this License, Derivative Works shall not include works that remain
|
46 |
-
separable from, or merely link (or bind by name) to the interfaces of,
|
47 |
-
the Work and Derivative Works thereof.
|
48 |
-
|
49 |
-
"Contribution" shall mean any work of authorship, including
|
50 |
-
the original version of the Work and any modifications or additions
|
51 |
-
to that Work or Derivative Works thereof, that is intentionally
|
52 |
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
53 |
-
or by an individual or Legal Entity authorized to submit on behalf of
|
54 |
-
the copyright owner. For the purposes of this definition, "submitted"
|
55 |
-
means any form of electronic, verbal, or written communication sent
|
56 |
-
to the Licensor or its representatives, including but not limited to
|
57 |
-
communication on electronic mailing lists, source code control systems,
|
58 |
-
and issue tracking systems that are managed by, or on behalf of, the
|
59 |
-
Licensor for the purpose of discussing and improving the Work, but
|
60 |
-
excluding communication that is conspicuously marked or otherwise
|
61 |
-
designated in writing by the copyright owner as "Not a Contribution."
|
62 |
-
|
63 |
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
64 |
-
on behalf of whom a Contribution has been received by Licensor and
|
65 |
-
subsequently incorporated within the Work.
|
66 |
-
|
67 |
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
68 |
-
this License, each Contributor hereby grants to You a perpetual,
|
69 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
70 |
-
copyright license to reproduce, prepare Derivative Works of,
|
71 |
-
publicly display, publicly perform, sublicense, and distribute the
|
72 |
-
Work and such Derivative Works in Source or Object form.
|
73 |
-
|
74 |
-
3. Grant of Patent License. Subject to the terms and conditions of
|
75 |
-
this License, each Contributor hereby grants to You a perpetual,
|
76 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
77 |
-
(except as stated in this section) patent license to make, have made,
|
78 |
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
79 |
-
where such license applies only to those patent claims licensable
|
80 |
-
by such Contributor that are necessarily infringed by their
|
81 |
-
Contribution(s) alone or by combination of their Contribution(s)
|
82 |
-
with the Work to which such Contribution(s) was submitted. If You
|
83 |
-
institute patent litigation against any entity (including a
|
84 |
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
85 |
-
or a Contribution incorporated within the Work constitutes direct
|
86 |
-
or contributory patent infringement, then any patent licenses
|
87 |
-
granted to You under this License for that Work shall terminate
|
88 |
-
as of the date such litigation is filed.
|
89 |
-
|
90 |
-
4. Redistribution. You may reproduce and distribute copies of the
|
91 |
-
Work or Derivative Works thereof in any medium, with or without
|
92 |
-
modifications, and in Source or Object form, provided that You
|
93 |
-
meet the following conditions:
|
94 |
-
|
95 |
-
(a) You must give any other recipients of the Work or
|
96 |
-
Derivative Works a copy of this License; and
|
97 |
-
|
98 |
-
(b) You must cause any modified files to carry prominent notices
|
99 |
-
stating that You changed the files; and
|
100 |
-
|
101 |
-
(c) You must retain, in the Source form of any Derivative Works
|
102 |
-
that You distribute, all copyright, patent, trademark, and
|
103 |
-
attribution notices from the Source form of the Work,
|
104 |
-
excluding those notices that do not pertain to any part of
|
105 |
-
the Derivative Works; and
|
106 |
-
|
107 |
-
(d) If the Work includes a "NOTICE" text file as part of its
|
108 |
-
distribution, then any Derivative Works that You distribute must
|
109 |
-
include a readable copy of the attribution notices contained
|
110 |
-
within such NOTICE file, excluding those notices that do not
|
111 |
-
pertain to any part of the Derivative Works, in at least one
|
112 |
-
of the following places: within a NOTICE text file distributed
|
113 |
-
as part of the Derivative Works; within the Source form or
|
114 |
-
documentation, if provided along with the Derivative Works; or,
|
115 |
-
within a display generated by the Derivative Works, if and
|
116 |
-
wherever such third-party notices normally appear. The contents
|
117 |
-
of the NOTICE file are for informational purposes only and
|
118 |
-
do not modify the License. You may add Your own attribution
|
119 |
-
notices within Derivative Works that You distribute, alongside
|
120 |
-
or as an addendum to the NOTICE text from the Work, provided
|
121 |
-
that such additional attribution notices cannot be construed
|
122 |
-
as modifying the License.
|
123 |
-
|
124 |
-
You may add Your own copyright statement to Your modifications and
|
125 |
-
may provide additional or different license terms and conditions
|
126 |
-
for use, reproduction, or distribution of Your modifications, or
|
127 |
-
for any such Derivative Works as a whole, provided Your use,
|
128 |
-
reproduction, and distribution of the Work otherwise complies with
|
129 |
-
the conditions stated in this License.
|
130 |
-
|
131 |
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
132 |
-
any Contribution intentionally submitted for inclusion in the Work
|
133 |
-
by You to the Licensor shall be under the terms and conditions of
|
134 |
-
this License, without any additional terms or conditions.
|
135 |
-
Notwithstanding the above, nothing herein shall supersede or modify
|
136 |
-
the terms of any separate license agreement you may have executed
|
137 |
-
with Licensor regarding such Contributions.
|
138 |
-
|
139 |
-
6. Trademarks. This License does not grant permission to use the trade
|
140 |
-
names, trademarks, service marks, or product names of the Licensor,
|
141 |
-
except as required for reasonable and customary use in describing the
|
142 |
-
origin of the Work and reproducing the content of the NOTICE file.
|
143 |
-
|
144 |
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
145 |
-
agreed to in writing, Licensor provides the Work (and each
|
146 |
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
147 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
148 |
-
implied, including, without limitation, any warranties or conditions
|
149 |
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
150 |
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
151 |
-
appropriateness of using or redistributing the Work and assume any
|
152 |
-
risks associated with Your exercise of permissions under this License.
|
153 |
-
|
154 |
-
8. Limitation of Liability. In no event and under no legal theory,
|
155 |
-
whether in tort (including negligence), contract, or otherwise,
|
156 |
-
unless required by applicable law (such as deliberate and grossly
|
157 |
-
negligent acts) or agreed to in writing, shall any Contributor be
|
158 |
-
liable to You for damages, including any direct, indirect, special,
|
159 |
-
incidental, or consequential damages of any character arising as a
|
160 |
-
result of this License or out of the use or inability to use the
|
161 |
-
Work (including but not limited to damages for loss of goodwill,
|
162 |
-
work stoppage, computer failure or malfunction, or any and all
|
163 |
-
other commercial damages or losses), even if such Contributor
|
164 |
-
has been advised of the possibility of such damages.
|
165 |
-
|
166 |
-
9. Accepting Warranty or Additional Liability. While redistributing
|
167 |
-
the Work or Derivative Works thereof, You may choose to offer,
|
168 |
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
169 |
-
or other liability obligations and/or rights consistent with this
|
170 |
-
License. However, in accepting such obligations, You may act only
|
171 |
-
on Your own behalf and on Your sole responsibility, not on behalf
|
172 |
-
of any other Contributor, and only if You agree to indemnify,
|
173 |
-
defend, and hold each Contributor harmless for any liability
|
174 |
-
incurred by, or claims asserted against, such Contributor by reason
|
175 |
-
of your accepting any such warranty or additional liability.
|
176 |
-
|
177 |
-
END OF TERMS AND CONDITIONS
|
178 |
-
|
179 |
-
APPENDIX: How to apply the Apache License to your work.
|
180 |
-
|
181 |
-
To apply the Apache License to your work, attach the following
|
182 |
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
183 |
-
replaced with your own identifying information. (Don't include
|
184 |
-
the brackets!) The text should be enclosed in the appropriate
|
185 |
-
comment syntax for the file format. We also recommend that a
|
186 |
-
file or class name and description of purpose be included on the
|
187 |
-
same "printed page" as the copyright notice for easier
|
188 |
-
identification within third-party archives.
|
189 |
-
|
190 |
-
Copyright [yyyy] [name of copyright owner]
|
191 |
-
|
192 |
-
Licensed under the Apache License, Version 2.0 (the "License");
|
193 |
-
you may not use this file except in compliance with the License.
|
194 |
-
You may obtain a copy of the License at
|
195 |
-
|
196 |
-
http://www.apache.org/licenses/LICENSE-2.0
|
197 |
-
|
198 |
-
Unless required by applicable law or agreed to in writing, software
|
199 |
-
distributed under the License is distributed on an "AS IS" BASIS,
|
200 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
201 |
-
See the License for the specific language governing permissions and
|
202 |
-
limitations under the License.
|
1 |
+
|
2 |
+
Apache License
|
3 |
+
Version 2.0, January 2004
|
4 |
+
http://www.apache.org/licenses/
|
5 |
+
|
6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
7 |
+
|
8 |
+
1. Definitions.
|
9 |
+
|
10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
12 |
+
|
13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
14 |
+
the copyright owner that is granting the License.
|
15 |
+
|
16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
17 |
+
other entities that control, are controlled by, or are under common
|
18 |
+
control with that entity. For the purposes of this definition,
|
19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
20 |
+
direction or management of such entity, whether by contract or
|
21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
23 |
+
|
24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
25 |
+
exercising permissions granted by this License.
|
26 |
+
|
27 |
+
"Source" form shall mean the preferred form for making modifications,
|
28 |
+
including but not limited to software source code, documentation
|
29 |
+
source, and configuration files.
|
30 |
+
|
31 |
+
"Object" form shall mean any form resulting from mechanical
|
32 |
+
transformation or translation of a Source form, including but
|
33 |
+
not limited to compiled object code, generated documentation,
|
34 |
+
and conversions to other media types.
|
35 |
+
|
36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
37 |
+
Object form, made available under the License, as indicated by a
|
38 |
+
copyright notice that is included in or attached to the work
|
39 |
+
(an example is provided in the Appendix below).
|
40 |
+
|
41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
42 |
+
form, that is based on (or derived from) the Work and for which the
|
43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
45 |
+
of this License, Derivative Works shall not include works that remain
|
46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
47 |
+
the Work and Derivative Works thereof.
|
48 |
+
|
49 |
+
"Contribution" shall mean any work of authorship, including
|
50 |
+
the original version of the Work and any modifications or additions
|
51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
55 |
+
means any form of electronic, verbal, or written communication sent
|
56 |
+
to the Licensor or its representatives, including but not limited to
|
57 |
+
communication on electronic mailing lists, source code control systems,
|
58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
60 |
+
excluding communication that is conspicuously marked or otherwise
|
61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
62 |
+
|
63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
65 |
+
subsequently incorporated within the Work.
|
66 |
+
|
67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
72 |
+
Work and such Derivative Works in Source or Object form.
|
73 |
+
|
74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
77 |
+
(except as stated in this section) patent license to make, have made,
|
78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
79 |
+
where such license applies only to those patent claims licensable
|
80 |
+
by such Contributor that are necessarily infringed by their
|
81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
83 |
+
institute patent litigation against any entity (including a
|
84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
85 |
+
or a Contribution incorporated within the Work constitutes direct
|
86 |
+
or contributory patent infringement, then any patent licenses
|
87 |
+
granted to You under this License for that Work shall terminate
|
88 |
+
as of the date such litigation is filed.
|
89 |
+
|
90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
91 |
+
Work or Derivative Works thereof in any medium, with or without
|
92 |
+
modifications, and in Source or Object form, provided that You
|
93 |
+
meet the following conditions:
|
94 |
+
|
95 |
+
(a) You must give any other recipients of the Work or
|
96 |
+
Derivative Works a copy of this License; and
|
97 |
+
|
98 |
+
(b) You must cause any modified files to carry prominent notices
|
99 |
+
stating that You changed the files; and
|
100 |
+
|
101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
102 |
+
that You distribute, all copyright, patent, trademark, and
|
103 |
+
attribution notices from the Source form of the Work,
|
104 |
+
excluding those notices that do not pertain to any part of
|
105 |
+
the Derivative Works; and
|
106 |
+
|
107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
108 |
+
distribution, then any Derivative Works that You distribute must
|
109 |
+
include a readable copy of the attribution notices contained
|
110 |
+
within such NOTICE file, excluding those notices that do not
|
111 |
+
pertain to any part of the Derivative Works, in at least one
|
112 |
+
of the following places: within a NOTICE text file distributed
|
113 |
+
as part of the Derivative Works; within the Source form or
|
114 |
+
documentation, if provided along with the Derivative Works; or,
|
115 |
+
within a display generated by the Derivative Works, if and
|
116 |
+
wherever such third-party notices normally appear. The contents
|
117 |
+
of the NOTICE file are for informational purposes only and
|
118 |
+
do not modify the License. You may add Your own attribution
|
119 |
+
notices within Derivative Works that You distribute, alongside
|
120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
121 |
+
that such additional attribution notices cannot be construed
|
122 |
+
as modifying the License.
|
123 |
+
|
124 |
+
You may add Your own copyright statement to Your modifications and
|
125 |
+
may provide additional or different license terms and conditions
|
126 |
+
for use, reproduction, or distribution of Your modifications, or
|
127 |
+
for any such Derivative Works as a whole, provided Your use,
|
128 |
+
reproduction, and distribution of the Work otherwise complies with
|
129 |
+
the conditions stated in this License.
|
130 |
+
|
131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
133 |
+
by You to the Licensor shall be under the terms and conditions of
|
134 |
+
this License, without any additional terms or conditions.
|
135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
136 |
+
the terms of any separate license agreement you may have executed
|
137 |
+
with Licensor regarding such Contributions.
|
138 |
+
|
139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
141 |
+
except as required for reasonable and customary use in describing the
|
142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
143 |
+
|
144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
145 |
+
agreed to in writing, Licensor provides the Work (and each
|
146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
148 |
+
implied, including, without limitation, any warranties or conditions
|
149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
151 |
+
appropriateness of using or redistributing the Work and assume any
|
152 |
+
risks associated with Your exercise of permissions under this License.
|
153 |
+
|
154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
155 |
+
whether in tort (including negligence), contract, or otherwise,
|
156 |
+
unless required by applicable law (such as deliberate and grossly
|
157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
158 |
+
liable to You for damages, including any direct, indirect, special,
|
159 |
+
incidental, or consequential damages of any character arising as a
|
160 |
+
result of this License or out of the use or inability to use the
|
161 |
+
Work (including but not limited to damages for loss of goodwill,
|
162 |
+
work stoppage, computer failure or malfunction, or any and all
|
163 |
+
other commercial damages or losses), even if such Contributor
|
164 |
+
has been advised of the possibility of such damages.
|
165 |
+
|
166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
169 |
+
or other liability obligations and/or rights consistent with this
|
170 |
+
License. However, in accepting such obligations, You may act only
|
171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
172 |
+
of any other Contributor, and only if You agree to indemnify,
|
173 |
+
defend, and hold each Contributor harmless for any liability
|
174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
175 |
+
of your accepting any such warranty or additional liability.
|
176 |
+
|
177 |
+
END OF TERMS AND CONDITIONS
|
178 |
+
|
179 |
+
APPENDIX: How to apply the Apache License to your work.
|
180 |
+
|
181 |
+
To apply the Apache License to your work, attach the following
|
182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
183 |
+
replaced with your own identifying information. (Don't include
|
184 |
+
the brackets!) The text should be enclosed in the appropriate
|
185 |
+
comment syntax for the file format. We also recommend that a
|
186 |
+
file or class name and description of purpose be included on the
|
187 |
+
same "printed page" as the copyright notice for easier
|
188 |
+
identification within third-party archives.
|
189 |
+
|
190 |
+
Copyright [yyyy] [name of copyright owner]
|
191 |
+
|
192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
193 |
+
you may not use this file except in compliance with the License.
|
194 |
+
You may obtain a copy of the License at
|
195 |
+
|
196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
197 |
+
|
198 |
+
Unless required by applicable law or agreed to in writing, software
|
199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
201 |
+
See the License for the specific language governing permissions and
|
202 |
+
limitations under the License.
|
includes/vendor/geoip2/geoip2/README.md
CHANGED
@@ -1,401 +1,401 @@
|
|
1 |
-
# GeoIP2 PHP API #
|
2 |
-
|
3 |
-
## Description ##
|
4 |
-
|
5 |
-
This package provides an API for the GeoIP2
|
6 |
-
[web services](http://dev.maxmind.com/geoip/geoip2/web-services) and
|
7 |
-
[databases](http://dev.maxmind.com/geoip/geoip2/downloadable). The API also
|
8 |
-
works with the free
|
9 |
-
[GeoLite2 databases](http://dev.maxmind.com/geoip/geoip2/geolite2/).
|
10 |
-
|
11 |
-
## Install via Composer ##
|
12 |
-
|
13 |
-
We recommend installing this package with [Composer](http://getcomposer.org/).
|
14 |
-
|
15 |
-
### Download Composer ###
|
16 |
-
|
17 |
-
To download Composer, run in the root directory of your project:
|
18 |
-
|
19 |
-
```bash
|
20 |
-
curl -sS https://getcomposer.org/installer | php
|
21 |
-
```
|
22 |
-
|
23 |
-
You should now have the file `composer.phar` in your project directory.
|
24 |
-
|
25 |
-
### Install Dependencies ###
|
26 |
-
|
27 |
-
Run in your project root:
|
28 |
-
|
29 |
-
```
|
30 |
-
php composer.phar require geoip2/geoip2:~2.0
|
31 |
-
```
|
32 |
-
|
33 |
-
You should now have the files `composer.json` and `composer.lock` as well as
|
34 |
-
the directory `vendor` in your project directory. If you use a version control
|
35 |
-
system, `composer.json` should be added to it.
|
36 |
-
|
37 |
-
### Require Autoloader ###
|
38 |
-
|
39 |
-
After installing the dependencies, you need to require the Composer autoloader
|
40 |
-
from your code:
|
41 |
-
|
42 |
-
```php
|
43 |
-
require 'vendor/autoload.php';
|
44 |
-
```
|
45 |
-
|
46 |
-
## Install via Phar ##
|
47 |
-
|
48 |
-
Although we strongly recommend using Composer, we also provide a
|
49 |
-
[phar archive](http://php.net/manual/en/book.phar.php) containing most of the
|
50 |
-
dependencies for GeoIP2. Our latest phar archive is available on
|
51 |
-
[our releases page](https://github.com/maxmind/GeoIP2-php/releases).
|
52 |
-
|
53 |
-
### Install Dependencies ###
|
54 |
-
|
55 |
-
In order to use the phar archive, you must have the PHP
|
56 |
-
[Phar extension](http://php.net/manual/en/book.phar.php) installed and
|
57 |
-
enabled.
|
58 |
-
|
59 |
-
If you will be making web service requests, you must have the PHP
|
60 |
-
[cURL extension](http://php.net/manual/en/book.curl.php)
|
61 |
-
installed to use this archive. For Debian based distributions, this can
|
62 |
-
typically be found in the the `php-curl` package. For other operating
|
63 |
-
systems, please consult the relevant documentation. After installing the
|
64 |
-
extension you may need to restart your web server.
|
65 |
-
|
66 |
-
If you are missing this extension, you will see errors like the following:
|
67 |
-
|
68 |
-
```
|
69 |
-
PHP Fatal error: Uncaught Error: Call to undefined function MaxMind\WebService\curl_version()
|
70 |
-
```
|
71 |
-
|
72 |
-
### Require Package ###
|
73 |
-
|
74 |
-
To use the archive, just require it from your script:
|
75 |
-
|
76 |
-
```php
|
77 |
-
require 'geoip2.phar';
|
78 |
-
```
|
79 |
-
|
80 |
-
## Optional C Extension ##
|
81 |
-
|
82 |
-
The [MaxMind DB API](https://github.com/maxmind/MaxMind-DB-Reader-php)
|
83 |
-
includes an optional C extension that you may install to dramatically increase
|
84 |
-
the performance of lookups in GeoIP2 or GeoLite2 databases. To install, please
|
85 |
-
follow the instructions included with that API.
|
86 |
-
|
87 |
-
The extension has no effect on web-service lookups.
|
88 |
-
|
89 |
-
## IP Geolocation Usage ##
|
90 |
-
|
91 |
-
IP geolocation is inherently imprecise. Locations are often near the center of
|
92 |
-
the population. Any location provided by a GeoIP2 database or web service
|
93 |
-
should not be used to identify a particular address or household.
|
94 |
-
|
95 |
-
## Database Reader ##
|
96 |
-
|
97 |
-
### Usage ###
|
98 |
-
|
99 |
-
To use this API, you must create a new `\GeoIp2\Database\Reader` object with
|
100 |
-
the path to the database file as the first argument to the constructor. You
|
101 |
-
may then call the method corresponding to the database you are using.
|
102 |
-
|
103 |
-
If the lookup succeeds, the method call will return a model class for the
|
104 |
-
record in the database. This model in turn contains multiple container
|
105 |
-
classes for the different parts of the data such as the city in which the
|
106 |
-
IP address is located.
|
107 |
-
|
108 |
-
If the record is not found, a `\GeoIp2\Exception\AddressNotFoundException`
|
109 |
-
is thrown. If the database is invalid or corrupt, a
|
110 |
-
`\MaxMind\Db\InvalidDatabaseException` will be thrown.
|
111 |
-
|
112 |
-
See the API documentation for more details.
|
113 |
-
|
114 |
-
### City Example ###
|
115 |
-
|
116 |
-
```php
|
117 |
-
<?php
|
118 |
-
require_once 'vendor/autoload.php';
|
119 |
-
use GeoIp2\Database\Reader;
|
120 |
-
|
121 |
-
// This creates the Reader object, which should be reused across
|
122 |
-
// lookups.
|
123 |
-
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-City.mmdb');
|
124 |
-
|
125 |
-
// Replace "city" with the appropriate method for your database, e.g.,
|
126 |
-
// "country".
|
127 |
-
$record = $reader->city('128.101.101.101');
|
128 |
-
|
129 |
-
print($record->country->isoCode . "\n"); // 'US'
|
130 |
-
print($record->country->name . "\n"); // 'United States'
|
131 |
-
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
132 |
-
|
133 |
-
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
134 |
-
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
135 |
-
|
136 |
-
print($record->city->name . "\n"); // 'Minneapolis'
|
137 |
-
|
138 |
-
print($record->postal->code . "\n"); // '55455'
|
139 |
-
|
140 |
-
print($record->location->latitude . "\n"); // 44.9733
|
141 |
-
print($record->location->longitude . "\n"); // -93.2323
|
142 |
-
|
143 |
-
```
|
144 |
-
|
145 |
-
### Anonymous IP Example ###
|
146 |
-
|
147 |
-
```php
|
148 |
-
<?php
|
149 |
-
require_once 'vendor/autoload.php';
|
150 |
-
use GeoIp2\Database\Reader;
|
151 |
-
|
152 |
-
// This creates the Reader object, which should be reused across
|
153 |
-
// lookups.
|
154 |
-
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Anonymous-IP.mmdb');
|
155 |
-
|
156 |
-
$record = $reader->anonymousIp('128.101.101.101');
|
157 |
-
|
158 |
-
if ($record->isAnonymous) { print "anon\n"; }
|
159 |
-
print($record->ipAddress . "\n"); // '128.101.101.101'
|
160 |
-
|
161 |
-
```
|
162 |
-
|
163 |
-
### Connection-Type Example ###
|
164 |
-
|
165 |
-
```php
|
166 |
-
<?php
|
167 |
-
require_once 'vendor/autoload.php';
|
168 |
-
use GeoIp2\Database\Reader;
|
169 |
-
|
170 |
-
// This creates the Reader object, which should be reused across
|
171 |
-
// lookups.
|
172 |
-
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Connection-Type.mmdb');
|
173 |
-
|
174 |
-
$record = $reader->connectionType('128.101.101.101');
|
175 |
-
|
176 |
-
print($record->connectionType . "\n"); // 'Corporate'
|
177 |
-
print($record->ipAddress . "\n"); // '128.101.101.101'
|
178 |
-
|
179 |
-
```
|
180 |
-
|
181 |
-
### Domain Example ###
|
182 |
-
|
183 |
-
```php
|
184 |
-
<?php
|
185 |
-
require_once 'vendor/autoload.php';
|
186 |
-
use GeoIp2\Database\Reader;
|
187 |
-
|
188 |
-
// This creates the Reader object, which should be reused across
|
189 |
-
// lookups.
|
190 |
-
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Domain.mmdb');
|
191 |
-
|
192 |
-
$record = $reader->domain('128.101.101.101');
|
193 |
-
|
194 |
-
print($record->domain . "\n"); // 'umn.edu'
|
195 |
-
print($record->ipAddress . "\n"); // '128.101.101.101'
|
196 |
-
|
197 |
-
```
|
198 |
-
|
199 |
-
### Enterprise Example ###
|
200 |
-
|
201 |
-
```php
|
202 |
-
<?php
|
203 |
-
require_once 'vendor/autoload.php';
|
204 |
-
use GeoIp2\Database\Reader;
|
205 |
-
|
206 |
-
// This creates the Reader object, which should be reused across
|
207 |
-
// lookups.
|
208 |
-
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Enterprise.mmdb');
|
209 |
-
|
210 |
-
// Use the ->enterprise method to do a lookup in the Enterprise database
|
211 |
-
$record = $reader->enterprise('128.101.101.101');
|
212 |
-
|
213 |
-
print($record->country->confidence . "\n"); // 99
|
214 |
-
print($record->country->isoCode . "\n"); // 'US'
|
215 |
-
print($record->country->name . "\n"); // 'United States'
|
216 |
-
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
217 |
-
|
218 |
-
print($record->mostSpecificSubdivision->confidence . "\n"); // 77
|
219 |
-
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
220 |
-
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
221 |
-
|
222 |
-
print($record->city->confidence . "\n"); // 60
|
223 |
-
print($record->city->name . "\n"); // 'Minneapolis'
|
224 |
-
|
225 |
-
print($record->postal->code . "\n"); // '55455'
|
226 |
-
|
227 |
-
print($record->location->accuracyRadius . "\n"); // 50
|
228 |
-
print($record->location->latitude . "\n"); // 44.9733
|
229 |
-
print($record->location->longitude . "\n"); // -93.2323
|
230 |
-
|
231 |
-
```
|
232 |
-
|
233 |
-
### ISP Example ###
|
234 |
-
|
235 |
-
```php
|
236 |
-
<?php
|
237 |
-
require_once 'vendor/autoload.php';
|
238 |
-
use GeoIp2\Database\Reader;
|
239 |
-
|
240 |
-
// This creates the Reader object, which should be reused across
|
241 |
-
// lookups.
|
242 |
-
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-ISP.mmdb');
|
243 |
-
|
244 |
-
$record = $reader->isp('128.101.101.101');
|
245 |
-
|
246 |
-
print($record->autonomousSystemNumber . "\n"); // 217
|
247 |
-
print($record->autonomousSystemOrganization . "\n"); // 'University of Minnesota'
|
248 |
-
print($record->isp . "\n"); // 'University of Minnesota'
|
249 |
-
print($record->organization . "\n"); // 'University of Minnesota'
|
250 |
-
|
251 |
-
print($record->ipAddress . "\n"); // '128.101.101.101'
|
252 |
-
|
253 |
-
```
|
254 |
-
|
255 |
-
## Web Service Client ##
|
256 |
-
|
257 |
-
### Usage ###
|
258 |
-
|
259 |
-
To use this API, you must create a new `\GeoIp2\WebService\Client`
|
260 |
-
object with your `$accountId` and `$licenseKey`, then you call the method
|
261 |
-
corresponding to a specific end point, passing it the IP address you want to
|
262 |
-
look up.
|
263 |
-
|
264 |
-
If the request succeeds, the method call will return a model class for the end
|
265 |
-
point you called. This model in turn contains multiple record classes, each of
|
266 |
-
which represents part of the data returned by the web service.
|
267 |
-
|
268 |
-
If there is an error, a structured exception is thrown.
|
269 |
-
|
270 |
-
See the API documentation for more details.
|
271 |
-
|
272 |
-
### Example ###
|
273 |
-
|
274 |
-
```php
|
275 |
-
<?php
|
276 |
-
require_once 'vendor/autoload.php';
|
277 |
-
use GeoIp2\WebService\Client;
|
278 |
-
|
279 |
-
// This creates a Client object that can be reused across requests.
|
280 |
-
// Replace "42" with your account ID and "license_key" with your license
|
281 |
-
// key.
|
282 |
-
$client = new Client(42, 'abcdef123456');
|
283 |
-
|
284 |
-
// Replace "city" with the method corresponding to the web service that
|
285 |
-
// you are using, e.g., "country", "insights".
|
286 |
-
$record = $client->city('128.101.101.101');
|
287 |
-
|
288 |
-
print($record->country->isoCode . "\n"); // 'US'
|
289 |
-
print($record->country->name . "\n"); // 'United States'
|
290 |
-
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
291 |
-
|
292 |
-
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
293 |
-
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
294 |
-
|
295 |
-
print($record->city->name . "\n"); // 'Minneapolis'
|
296 |
-
|
297 |
-
print($record->postal->code . "\n"); // '55455'
|
298 |
-
|
299 |
-
print($record->location->latitude . "\n"); // 44.9733
|
300 |
-
print($record->location->longitude . "\n"); // -93.2323
|
301 |
-
|
302 |
-
```
|
303 |
-
|
304 |
-
## Values to use for Database or Array Keys ##
|
305 |
-
|
306 |
-
**We strongly discourage you from using a value from any `names` property as
|
307 |
-
a key in a database or array.**
|
308 |
-
|
309 |
-
These names may change between releases. Instead we recommend using one of the
|
310 |
-
following:
|
311 |
-
|
312 |
-
* `GeoIp2\Record\City` - `$city->geonameId`
|
313 |
-
* `GeoIp2\Record\Continent` - `$continent->code` or `$continent->geonameId`
|
314 |
-
* `GeoIp2\Record\Country` and `GeoIp2\Record\RepresentedCountry` -
|
315 |
-
`$country->isoCode` or `$country->geonameId`
|
316 |
-
* `GeoIp2\Record\Subdivision` - `$subdivision->isoCode` or `$subdivision->geonameId`
|
317 |
-
|
318 |
-
### What data is returned? ###
|
319 |
-
|
320 |
-
While many of the end points return the same basic records, the attributes
|
321 |
-
which can be populated vary between end points. In addition, while an end
|
322 |
-
point may offer a particular piece of data, MaxMind does not always have every
|
323 |
-
piece of data for any given IP address.
|
324 |
-
|
325 |
-
Because of these factors, it is possible for any end point to return a record
|
326 |
-
where some or all of the attributes are unpopulated.
|
327 |
-
|
328 |
-
See the
|
329 |
-
[GeoIP2 Precision web service docs](http://dev.maxmind.com/geoip/geoip2/web-services)
|
330 |
-
for details on what data each end point may return.
|
331 |
-
|
332 |
-
The only piece of data which is always returned is the `ipAddress`
|
333 |
-
attribute in the `GeoIp2\Record\Traits` record.
|
334 |
-
|
335 |
-
## Integration with GeoNames ##
|
336 |
-
|
337 |
-
[GeoNames](http://www.geonames.org/) offers web services and downloadable
|
338 |
-
databases with data on geographical features around the world, including
|
339 |
-
populated places. They offer both free and paid premium data. Each
|
340 |
-
feature is unique identified by a `geonameId`, which is an integer.
|
341 |
-
|
342 |
-
Many of the records returned by the GeoIP2 web services and databases
|
343 |
-
include a `geonameId` property. This is the ID of a geographical feature
|
344 |
-
(city, region, country, etc.) in the GeoNames database.
|
345 |
-
|
346 |
-
Some of the data that MaxMind provides is also sourced from GeoNames. We
|
347 |
-
source things like place names, ISO codes, and other similar data from
|
348 |
-
the GeoNames premium data set.
|
349 |
-
|
350 |
-
## Reporting data problems ##
|
351 |
-
|
352 |
-
If the problem you find is that an IP address is incorrectly mapped,
|
353 |
-
please
|
354 |
-
[submit your correction to MaxMind](http://www.maxmind.com/en/correction).
|
355 |
-
|
356 |
-
If you find some other sort of mistake, like an incorrect spelling,
|
357 |
-
please check the [GeoNames site](http://www.geonames.org/) first. Once
|
358 |
-
you've searched for a place and found it on the GeoNames map view, there
|
359 |
-
are a number of links you can use to correct data ("move", "edit",
|
360 |
-
"alternate names", etc.). Once the correction is part of the GeoNames
|
361 |
-
data set, it will be automatically incorporated into future MaxMind
|
362 |
-
releases.
|
363 |
-
|
364 |
-
If you are a paying MaxMind customer and you're not sure where to submit
|
365 |
-
a correction, please
|
366 |
-
[contact MaxMind support](http://www.maxmind.com/en/support) for help.
|
367 |
-
|
368 |
-
## Other Support ##
|
369 |
-
|
370 |
-
Please report all issues with this code using the
|
371 |
-
[GitHub issue tracker](https://github.com/maxmind/GeoIP2-php/issues).
|
372 |
-
|
373 |
-
If you are having an issue with a MaxMind service that is not specific
|
374 |
-
to the client API, please see
|
375 |
-
[our support page](http://www.maxmind.com/en/support).
|
376 |
-
|
377 |
-
## Requirements ##
|
378 |
-
|
379 |
-
This library requires PHP 5.4 or greater. This library works and is tested
|
380 |
-
with HHVM.
|
381 |
-
|
382 |
-
This library also relies on the [MaxMind DB Reader](https://github.com/maxmind/MaxMind-DB-Reader-php).
|
383 |
-
|
384 |
-
## Contributing ##
|
385 |
-
|
386 |
-
Patches and pull requests are encouraged. All code should follow the PSR-2
|
387 |
-
style guidelines. Please include unit tests whenever possible. You may obtain
|
388 |
-
the test data for the maxmind-db folder by running `git submodule update
|
389 |
-
--init --recursive` or adding `--recursive` to your initial clone, or from
|
390 |
-
https://github.com/maxmind/MaxMind-DB
|
391 |
-
|
392 |
-
## Versioning ##
|
393 |
-
|
394 |
-
The GeoIP2 PHP API uses [Semantic Versioning](http://semver.org/).
|
395 |
-
|
396 |
-
## Copyright and License ##
|
397 |
-
|
398 |
-
This software is Copyright (c) 2013-2018 by MaxMind, Inc.
|
399 |
-
|
400 |
-
This is free software, licensed under the Apache License, Version 2.0.
|
401 |
-
|
1 |
+
# GeoIP2 PHP API #
|
2 |
+
|
3 |
+
## Description ##
|
4 |
+
|
5 |
+
This package provides an API for the GeoIP2
|
6 |
+
[web services](http://dev.maxmind.com/geoip/geoip2/web-services) and
|
7 |
+
[databases](http://dev.maxmind.com/geoip/geoip2/downloadable). The API also
|
8 |
+
works with the free
|
9 |
+
[GeoLite2 databases](http://dev.maxmind.com/geoip/geoip2/geolite2/).
|
10 |
+
|
11 |
+
## Install via Composer ##
|
12 |
+
|
13 |
+
We recommend installing this package with [Composer](http://getcomposer.org/).
|
14 |
+
|
15 |
+
### Download Composer ###
|
16 |
+
|
17 |
+
To download Composer, run in the root directory of your project:
|
18 |
+
|
19 |
+
```bash
|
20 |
+
curl -sS https://getcomposer.org/installer | php
|
21 |
+
```
|
22 |
+
|
23 |
+
You should now have the file `composer.phar` in your project directory.
|
24 |
+
|
25 |
+
### Install Dependencies ###
|
26 |
+
|
27 |
+
Run in your project root:
|
28 |
+
|
29 |
+
```
|
30 |
+
php composer.phar require geoip2/geoip2:~2.0
|
31 |
+
```
|
32 |
+
|
33 |
+
You should now have the files `composer.json` and `composer.lock` as well as
|
34 |
+
the directory `vendor` in your project directory. If you use a version control
|
35 |
+
system, `composer.json` should be added to it.
|
36 |
+
|
37 |
+
### Require Autoloader ###
|
38 |
+
|
39 |
+
After installing the dependencies, you need to require the Composer autoloader
|
40 |
+
from your code:
|
41 |
+
|
42 |
+
```php
|
43 |
+
require 'vendor/autoload.php';
|
44 |
+
```
|
45 |
+
|
46 |
+
## Install via Phar ##
|
47 |
+
|
48 |
+
Although we strongly recommend using Composer, we also provide a
|
49 |
+
[phar archive](http://php.net/manual/en/book.phar.php) containing most of the
|
50 |
+
dependencies for GeoIP2. Our latest phar archive is available on
|
51 |
+
[our releases page](https://github.com/maxmind/GeoIP2-php/releases).
|
52 |
+
|
53 |
+
### Install Dependencies ###
|
54 |
+
|
55 |
+
In order to use the phar archive, you must have the PHP
|
56 |
+
[Phar extension](http://php.net/manual/en/book.phar.php) installed and
|
57 |
+
enabled.
|
58 |
+
|
59 |
+
If you will be making web service requests, you must have the PHP
|
60 |
+
[cURL extension](http://php.net/manual/en/book.curl.php)
|
61 |
+
installed to use this archive. For Debian based distributions, this can
|
62 |
+
typically be found in the the `php-curl` package. For other operating
|
63 |
+
systems, please consult the relevant documentation. After installing the
|
64 |
+
extension you may need to restart your web server.
|
65 |
+
|
66 |
+
If you are missing this extension, you will see errors like the following:
|
67 |
+
|
68 |
+
```
|
69 |
+
PHP Fatal error: Uncaught Error: Call to undefined function MaxMind\WebService\curl_version()
|
70 |
+
```
|
71 |
+
|
72 |
+
### Require Package ###
|
73 |
+
|
74 |
+
To use the archive, just require it from your script:
|
75 |
+
|
76 |
+
```php
|
77 |
+
require 'geoip2.phar';
|
78 |
+
```
|
79 |
+
|
80 |
+
## Optional C Extension ##
|
81 |
+
|
82 |
+
The [MaxMind DB API](https://github.com/maxmind/MaxMind-DB-Reader-php)
|
83 |
+
includes an optional C extension that you may install to dramatically increase
|
84 |
+
the performance of lookups in GeoIP2 or GeoLite2 databases. To install, please
|
85 |
+
follow the instructions included with that API.
|
86 |
+
|
87 |
+
The extension has no effect on web-service lookups.
|
88 |
+
|
89 |
+
## IP Geolocation Usage ##
|
90 |
+
|
91 |
+
IP geolocation is inherently imprecise. Locations are often near the center of
|
92 |
+
the population. Any location provided by a GeoIP2 database or web service
|
93 |
+
should not be used to identify a particular address or household.
|
94 |
+
|
95 |
+
## Database Reader ##
|
96 |
+
|
97 |
+
### Usage ###
|
98 |
+
|
99 |
+
To use this API, you must create a new `\GeoIp2\Database\Reader` object with
|
100 |
+
the path to the database file as the first argument to the constructor. You
|
101 |
+
may then call the method corresponding to the database you are using.
|
102 |
+
|
103 |
+
If the lookup succeeds, the method call will return a model class for the
|
104 |
+
record in the database. This model in turn contains multiple container
|
105 |
+
classes for the different parts of the data such as the city in which the
|
106 |
+
IP address is located.
|
107 |
+
|
108 |
+
If the record is not found, a `\GeoIp2\Exception\AddressNotFoundException`
|
109 |
+
is thrown. If the database is invalid or corrupt, a
|
110 |
+
`\MaxMind\Db\InvalidDatabaseException` will be thrown.
|
111 |
+
|
112 |
+
See the API documentation for more details.
|
113 |
+
|
114 |
+
### City Example ###
|
115 |
+
|
116 |
+
```php
|
117 |
+
<?php
|
118 |
+
require_once 'vendor/autoload.php';
|
119 |
+
use GeoIp2\Database\Reader;
|
120 |
+
|
121 |
+
// This creates the Reader object, which should be reused across
|
122 |
+
// lookups.
|
123 |
+
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-City.mmdb');
|
124 |
+
|
125 |
+
// Replace "city" with the appropriate method for your database, e.g.,
|
126 |
+
// "country".
|
127 |
+
$record = $reader->city('128.101.101.101');
|
128 |
+
|
129 |
+
print($record->country->isoCode . "\n"); // 'US'
|
130 |
+
print($record->country->name . "\n"); // 'United States'
|
131 |
+
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
132 |
+
|
133 |
+
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
134 |
+
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
135 |
+
|
136 |
+
print($record->city->name . "\n"); // 'Minneapolis'
|
137 |
+
|
138 |
+
print($record->postal->code . "\n"); // '55455'
|
139 |
+
|
140 |
+
print($record->location->latitude . "\n"); // 44.9733
|
141 |
+
print($record->location->longitude . "\n"); // -93.2323
|
142 |
+
|
143 |
+
```
|
144 |
+
|
145 |
+
### Anonymous IP Example ###
|
146 |
+
|
147 |
+
```php
|
148 |
+
<?php
|
149 |
+
require_once 'vendor/autoload.php';
|
150 |
+
use GeoIp2\Database\Reader;
|
151 |
+
|
152 |
+
// This creates the Reader object, which should be reused across
|
153 |
+
// lookups.
|
154 |
+
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Anonymous-IP.mmdb');
|
155 |
+
|
156 |
+
$record = $reader->anonymousIp('128.101.101.101');
|
157 |
+
|
158 |
+
if ($record->isAnonymous) { print "anon\n"; }
|
159 |
+
print($record->ipAddress . "\n"); // '128.101.101.101'
|
160 |
+
|
161 |
+
```
|
162 |
+
|
163 |
+
### Connection-Type Example ###
|
164 |
+
|
165 |
+
```php
|
166 |
+
<?php
|
167 |
+
require_once 'vendor/autoload.php';
|
168 |
+
use GeoIp2\Database\Reader;
|
169 |
+
|
170 |
+
// This creates the Reader object, which should be reused across
|
171 |
+
// lookups.
|
172 |
+
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Connection-Type.mmdb');
|
173 |
+
|
174 |
+
$record = $reader->connectionType('128.101.101.101');
|
175 |
+
|
176 |
+
print($record->connectionType . "\n"); // 'Corporate'
|
177 |
+
print($record->ipAddress . "\n"); // '128.101.101.101'
|
178 |
+
|
179 |
+
```
|
180 |
+
|
181 |
+
### Domain Example ###
|
182 |
+
|
183 |
+
```php
|
184 |
+
<?php
|
185 |
+
require_once 'vendor/autoload.php';
|
186 |
+
use GeoIp2\Database\Reader;
|
187 |
+
|
188 |
+
// This creates the Reader object, which should be reused across
|
189 |
+
// lookups.
|
190 |
+
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Domain.mmdb');
|
191 |
+
|
192 |
+
$record = $reader->domain('128.101.101.101');
|
193 |
+
|
194 |
+
print($record->domain . "\n"); // 'umn.edu'
|
195 |
+
print($record->ipAddress . "\n"); // '128.101.101.101'
|
196 |
+
|
197 |
+
```
|
198 |
+
|
199 |
+
### Enterprise Example ###
|
200 |
+
|
201 |
+
```php
|
202 |
+
<?php
|
203 |
+
require_once 'vendor/autoload.php';
|
204 |
+
use GeoIp2\Database\Reader;
|
205 |
+
|
206 |
+
// This creates the Reader object, which should be reused across
|
207 |
+
// lookups.
|
208 |
+
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Enterprise.mmdb');
|
209 |
+
|
210 |
+
// Use the ->enterprise method to do a lookup in the Enterprise database
|
211 |
+
$record = $reader->enterprise('128.101.101.101');
|
212 |
+
|
213 |
+
print($record->country->confidence . "\n"); // 99
|
214 |
+
print($record->country->isoCode . "\n"); // 'US'
|
215 |
+
print($record->country->name . "\n"); // 'United States'
|
216 |
+
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
217 |
+
|
218 |
+
print($record->mostSpecificSubdivision->confidence . "\n"); // 77
|
219 |
+
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
220 |
+
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
221 |
+
|
222 |
+
print($record->city->confidence . "\n"); // 60
|
223 |
+
print($record->city->name . "\n"); // 'Minneapolis'
|
224 |
+
|
225 |
+
print($record->postal->code . "\n"); // '55455'
|
226 |
+
|
227 |
+
print($record->location->accuracyRadius . "\n"); // 50
|
228 |
+
print($record->location->latitude . "\n"); // 44.9733
|
229 |
+
print($record->location->longitude . "\n"); // -93.2323
|
230 |
+
|
231 |
+
```
|
232 |
+
|
233 |
+
### ISP Example ###
|
234 |
+
|
235 |
+
```php
|
236 |
+
<?php
|
237 |
+
require_once 'vendor/autoload.php';
|
238 |
+
use GeoIp2\Database\Reader;
|
239 |
+
|
240 |
+
// This creates the Reader object, which should be reused across
|
241 |
+
// lookups.
|
242 |
+
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-ISP.mmdb');
|
243 |
+
|
244 |
+
$record = $reader->isp('128.101.101.101');
|
245 |
+
|
246 |
+
print($record->autonomousSystemNumber . "\n"); // 217
|
247 |
+
print($record->autonomousSystemOrganization . "\n"); // 'University of Minnesota'
|
248 |
+
print($record->isp . "\n"); // 'University of Minnesota'
|
249 |
+
print($record->organization . "\n"); // 'University of Minnesota'
|
250 |
+
|
251 |
+
print($record->ipAddress . "\n"); // '128.101.101.101'
|
252 |
+
|
253 |
+
```
|
254 |
+
|
255 |
+
## Web Service Client ##
|
256 |
+
|
257 |
+
### Usage ###
|
258 |
+
|
259 |
+
To use this API, you must create a new `\GeoIp2\WebService\Client`
|
260 |
+
object with your `$accountId` and `$licenseKey`, then you call the method
|
261 |
+
corresponding to a specific end point, passing it the IP address you want to
|
262 |
+
look up.
|
263 |
+
|
264 |
+
If the request succeeds, the method call will return a model class for the end
|
265 |
+
point you called. This model in turn contains multiple record classes, each of
|
266 |
+
which represents part of the data returned by the web service.
|
267 |
+
|
268 |
+
If there is an error, a structured exception is thrown.
|
269 |
+
|
270 |
+
See the API documentation for more details.
|
271 |
+
|
272 |
+
### Example ###
|
273 |
+
|
274 |
+
```php
|
275 |
+
<?php
|
276 |
+
require_once 'vendor/autoload.php';
|
277 |
+
use GeoIp2\WebService\Client;
|
278 |
+
|
279 |
+
// This creates a Client object that can be reused across requests.
|
280 |
+
// Replace "42" with your account ID and "license_key" with your license
|
281 |
+
// key.
|
282 |
+
$client = new Client(42, 'abcdef123456');
|
283 |
+
|
284 |
+
// Replace "city" with the method corresponding to the web service that
|
285 |
+
// you are using, e.g., "country", "insights".
|
286 |
+
$record = $client->city('128.101.101.101');
|
287 |
+
|
288 |
+
print($record->country->isoCode . "\n"); // 'US'
|
289 |
+
print($record->country->name . "\n"); // 'United States'
|
290 |
+
print($record->country->names['zh-CN'] . "\n"); // '美国'
|
291 |
+
|
292 |
+
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
|
293 |
+
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
|
294 |
+
|
295 |
+
print($record->city->name . "\n"); // 'Minneapolis'
|
296 |
+
|
297 |
+
print($record->postal->code . "\n"); // '55455'
|
298 |
+
|
299 |
+
print($record->location->latitude . "\n"); // 44.9733
|
300 |
+
print($record->location->longitude . "\n"); // -93.2323
|
301 |
+
|
302 |
+
```
|
303 |
+
|
304 |
+
## Values to use for Database or Array Keys ##
|
305 |
+
|
306 |
+
**We strongly discourage you from using a value from any `names` property as
|
307 |
+
a key in a database or array.**
|
308 |
+
|
309 |
+
These names may change between releases. Instead we recommend using one of the
|
310 |
+
following:
|
311 |
+
|
312 |
+
* `GeoIp2\Record\City` - `$city->geonameId`
|
313 |
+
* `GeoIp2\Record\Continent` - `$continent->code` or `$continent->geonameId`
|
314 |
+
* `GeoIp2\Record\Country` and `GeoIp2\Record\RepresentedCountry` -
|
315 |
+
`$country->isoCode` or `$country->geonameId`
|
316 |
+
* `GeoIp2\Record\Subdivision` - `$subdivision->isoCode` or `$subdivision->geonameId`
|
317 |
+
|
318 |
+
### What data is returned? ###
|
319 |
+
|
320 |
+
While many of the end points return the same basic records, the attributes
|
321 |
+
which can be populated vary between end points. In addition, while an end
|
322 |
+
point may offer a particular piece of data, MaxMind does not always have every
|
323 |
+
piece of data for any given IP address.
|
324 |
+
|
325 |
+
Because of these factors, it is possible for any end point to return a record
|
326 |
+
where some or all of the attributes are unpopulated.
|
327 |
+
|
328 |
+
See the
|
329 |
+
[GeoIP2 Precision web service docs](http://dev.maxmind.com/geoip/geoip2/web-services)
|
330 |
+
for details on what data each end point may return.
|
331 |
+
|
332 |
+
The only piece of data which is always returned is the `ipAddress`
|
333 |
+
attribute in the `GeoIp2\Record\Traits` record.
|
334 |
+
|
335 |
+
## Integration with GeoNames ##
|
336 |
+
|
337 |
+
[GeoNames](http://www.geonames.org/) offers web services and downloadable
|
338 |
+
databases with data on geographical features around the world, including
|
339 |
+
populated places. They offer both free and paid premium data. Each
|
340 |
+
feature is unique identified by a `geonameId`, which is an integer.
|
341 |
+
|
342 |
+
Many of the records returned by the GeoIP2 web services and databases
|
343 |
+
include a `geonameId` property. This is the ID of a geographical feature
|
344 |
+
(city, region, country, etc.) in the GeoNames database.
|
345 |
+
|
346 |
+
Some of the data that MaxMind provides is also sourced from GeoNames. We
|
347 |
+
source things like place names, ISO codes, and other similar data from
|
348 |
+
the GeoNames premium data set.
|
349 |
+
|
350 |
+
## Reporting data problems ##
|
351 |
+
|
352 |
+
If the problem you find is that an IP address is incorrectly mapped,
|
353 |
+
please
|
354 |
+
[submit your correction to MaxMind](http://www.maxmind.com/en/correction).
|
355 |
+
|
356 |
+
If you find some other sort of mistake, like an incorrect spelling,
|
357 |
+
please check the [GeoNames site](http://www.geonames.org/) first. Once
|
358 |
+
you've searched for a place and found it on the GeoNames map view, there
|
359 |
+
are a number of links you can use to correct data ("move", "edit",
|
360 |
+
"alternate names", etc.). Once the correction is part of the GeoNames
|
361 |
+
data set, it will be automatically incorporated into future MaxMind
|
362 |
+
releases.
|
363 |
+
|
364 |
+
If you are a paying MaxMind customer and you're not sure where to submit
|
365 |
+
a correction, please
|
366 |
+
[contact MaxMind support](http://www.maxmind.com/en/support) for help.
|
367 |
+
|
368 |
+
## Other Support ##
|
369 |
+
|
370 |
+
Please report all issues with this code using the
|
371 |
+
[GitHub issue tracker](https://github.com/maxmind/GeoIP2-php/issues).
|
372 |
+
|
373 |
+
If you are having an issue with a MaxMind service that is not specific
|
374 |
+
to the client API, please see
|
375 |
+
[our support page](http://www.maxmind.com/en/support).
|
376 |
+
|
377 |
+
## Requirements ##
|
378 |
+
|
379 |
+
This library requires PHP 5.4 or greater. This library works and is tested
|
380 |
+
with HHVM.
|
381 |
+
|
382 |
+
This library also relies on the [MaxMind DB Reader](https://github.com/maxmind/MaxMind-DB-Reader-php).
|
383 |
+
|
384 |
+
## Contributing ##
|
385 |
+
|
386 |
+
Patches and pull requests are encouraged. All code should follow the PSR-2
|
387 |
+
style guidelines. Please include unit tests whenever possible. You may obtain
|
388 |
+
the test data for the maxmind-db folder by running `git submodule update
|
389 |
+
--init --recursive` or adding `--recursive` to your initial clone, or from
|
390 |
+
https://github.com/maxmind/MaxMind-DB
|
391 |
+
|
392 |
+
## Versioning ##
|
393 |
+
|
394 |
+
The GeoIP2 PHP API uses [Semantic Versioning](http://semver.org/).
|
395 |
+
|
396 |
+
## Copyright and License ##
|
397 |
+
|
398 |
+
This software is Copyright (c) 2013-2018 by MaxMind, Inc.
|
399 |
+
|
400 |
+
This is free software, licensed under the Apache License, Version 2.0.
|
401 |
+
|
includes/vendor/geoip2/geoip2/composer.json
CHANGED
@@ -1,30 +1,30 @@
|
|
1 |
-
{
|
2 |
-
"name": "geoip2/geoip2",
|
3 |
-
"description": "MaxMind GeoIP2 PHP API",
|
4 |
-
"keywords": ["geoip", "geoip2", "geolocation", "ip", "maxmind"],
|
5 |
-
"homepage": "https://github.com/maxmind/GeoIP2-php",
|
6 |
-
"type": "library",
|
7 |
-
"license": "Apache-2.0",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "Gregory J. Oschwald",
|
11 |
-
"email": "goschwald@maxmind.com",
|
12 |
-
"homepage": "http://www.maxmind.com/"
|
13 |
-
}
|
14 |
-
],
|
15 |
-
"require": {
|
16 |
-
"maxmind-db/reader": "~1.0",
|
17 |
-
"maxmind/web-service-common": "~0.5",
|
18 |
-
"php": ">=5.4"
|
19 |
-
},
|
20 |
-
"require-dev": {
|
21 |
-
"friendsofphp/php-cs-fixer": "2.*",
|
22 |
-
"phpunit/phpunit": "4.*",
|
23 |
-
"squizlabs/php_codesniffer": "3.*"
|
24 |
-
},
|
25 |
-
"autoload": {
|
26 |
-
"psr-4": {
|
27 |
-
"GeoIp2\\": "src"
|
28 |
-
}
|
29 |
-
}
|
30 |
-
}
|
1 |
+
{
|
2 |
+
"name": "geoip2/geoip2",
|
3 |
+
"description": "MaxMind GeoIP2 PHP API",
|
4 |
+
"keywords": ["geoip", "geoip2", "geolocation", "ip", "maxmind"],
|
5 |
+
"homepage": "https://github.com/maxmind/GeoIP2-php",
|
6 |
+
"type": "library",
|
7 |
+
"license": "Apache-2.0",
|
8 |
+
"authors": [
|
9 |
+
{
|
10 |
+
"name": "Gregory J. Oschwald",
|
11 |
+
"email": "goschwald@maxmind.com",
|
12 |
+
"homepage": "http://www.maxmind.com/"
|
13 |
+
}
|
14 |
+
],
|
15 |
+
"require": {
|
16 |
+
"maxmind-db/reader": "~1.0",
|
17 |
+
"maxmind/web-service-common": "~0.5",
|
18 |
+
"php": ">=5.4"
|
19 |
+
},
|
20 |
+
"require-dev": {
|
21 |
+
"friendsofphp/php-cs-fixer": "2.*",
|
22 |
+
"phpunit/phpunit": "4.*",
|
23 |
+
"squizlabs/php_codesniffer": "3.*"
|
24 |
+
},
|
25 |
+
"autoload": {
|
26 |
+
"psr-4": {
|
27 |
+
"GeoIp2\\": "src"
|
28 |
+
}
|
29 |
+
}
|
30 |
+
}
|
includes/vendor/geoip2/geoip2/src/Database/Reader.php
CHANGED
@@ -1,283 +1,283 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Database;
|
4 |
-
|
5 |
-
use GeoIp2\Exception\AddressNotFoundException;
|
6 |
-
use GeoIp2\ProviderInterface;
|
7 |
-
use MaxMind\Db\Reader as DbReader;
|
8 |
-
use MaxMind\Db\Reader\InvalidDatabaseException;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Instances of this class provide a reader for the GeoIP2 database format.
|
12 |
-
* IP addresses can be looked up using the database specific methods.
|
13 |
-
*
|
14 |
-
* ## Usage ##
|
15 |
-
*
|
16 |
-
* The basic API for this class is the same for every database. First, you
|
17 |
-
* create a reader object, specifying a file name. You then call the method
|
18 |
-
* corresponding to the specific database, passing it the IP address you want
|
19 |
-
* to look up.
|
20 |
-
*
|
21 |
-
* If the request succeeds, the method call will return a model class for
|
22 |
-
* the method you called. This model in turn contains multiple record classes,
|
23 |
-
* each of which represents part of the data returned by the database. If
|
24 |
-
* the database does not contain the requested information, the attributes
|
25 |
-
* on the record class will have a `null` value.
|
26 |
-
*
|
27 |
-
* If the address is not in the database, an
|
28 |
-
* {@link \GeoIp2\Exception\AddressNotFoundException} exception will be
|
29 |
-
* thrown. If an invalid IP address is passed to one of the methods, a
|
30 |
-
* SPL {@link \InvalidArgumentException} will be thrown. If the database is
|
31 |
-
* corrupt or invalid, a {@link \MaxMind\Db\Reader\InvalidDatabaseException}
|
32 |
-
* will be thrown.
|
33 |
-
*/
|
34 |
-
class Reader implements ProviderInterface
|
35 |
-
{
|
36 |
-
private $dbReader;
|
37 |
-
private $locales;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Constructor.
|
41 |
-
*
|
42 |
-
* @param string $filename the path to the GeoIP2 database file
|
43 |
-
* @param array $locales list of locale codes to use in name property
|
44 |
-
* from most preferred to least preferred
|
45 |
-
*
|
46 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
47 |
-
* is corrupt or invalid
|
48 |
-
*/
|
49 |
-
public function __construct(
|
50 |
-
$filename,
|
51 |
-
$locales = ['en']
|
52 |
-
) {
|
53 |
-
$this->dbReader = new DbReader($filename);
|
54 |
-
$this->locales = $locales;
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* This method returns a GeoIP2 City model.
|
59 |
-
*
|
60 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
61 |
-
*
|
62 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
63 |
-
* not in the database
|
64 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
65 |
-
* is corrupt or invalid
|
66 |
-
*
|
67 |
-
* @return \GeoIp2\Model\City
|
68 |
-
*/
|
69 |
-
public function city($ipAddress)
|
70 |
-
{
|
71 |
-
return $this->modelFor('City', 'City', $ipAddress);
|
72 |
-
}
|
73 |
-
|
74 |
-
/**
|
75 |
-
* This method returns a GeoIP2 Country model.
|
76 |
-
*
|
77 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
78 |
-
*
|
79 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
80 |
-
* not in the database
|
81 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
82 |
-
* is corrupt or invalid
|
83 |
-
*
|
84 |
-
* @return \GeoIp2\Model\Country
|
85 |
-
*/
|
86 |
-
public function country($ipAddress)
|
87 |
-
{
|
88 |
-
return $this->modelFor('Country', 'Country', $ipAddress);
|
89 |
-
}
|
90 |
-
|
91 |
-
/**
|
92 |
-
* This method returns a GeoIP2 Anonymous IP model.
|
93 |
-
*
|
94 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
95 |
-
*
|
96 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
97 |
-
* not in the database
|
98 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
99 |
-
* is corrupt or invalid
|
100 |
-
*
|
101 |
-
* @return \GeoIp2\Model\AnonymousIp
|
102 |
-
*/
|
103 |
-
public function anonymousIp($ipAddress)
|
104 |
-
{
|
105 |
-
return $this->flatModelFor(
|
106 |
-
'AnonymousIp',
|
107 |
-
'GeoIP2-Anonymous-IP',
|
108 |
-
$ipAddress
|
109 |
-
);
|
110 |
-
}
|
111 |
-
|
112 |
-
/**
|
113 |
-
* This method returns a GeoLite2 ASN model.
|
114 |
-
*
|
115 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
116 |
-
*
|
117 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
118 |
-
* not in the database
|
119 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
120 |
-
* is corrupt or invalid
|
121 |
-
*
|
122 |
-
* @return \GeoIp2\Model\Asn
|
123 |
-
*/
|
124 |
-
public function asn($ipAddress)
|
125 |
-
{
|
126 |
-
return $this->flatModelFor(
|
127 |
-
'Asn',
|
128 |
-
'GeoLite2-ASN',
|
129 |
-
$ipAddress
|
130 |
-
);
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* This method returns a GeoIP2 Connection Type model.
|
135 |
-
*
|
136 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
137 |
-
*
|
138 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
139 |
-
* not in the database
|
140 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
141 |
-
* is corrupt or invalid
|
142 |
-
*
|
143 |
-
* @return \GeoIp2\Model\ConnectionType
|
144 |
-
*/
|
145 |
-
public function connectionType($ipAddress)
|
146 |
-
{
|
147 |
-
return $this->flatModelFor(
|
148 |
-
'ConnectionType',
|
149 |
-
'GeoIP2-Connection-Type',
|
150 |
-
$ipAddress
|
151 |
-
);
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* This method returns a GeoIP2 Domain model.
|
156 |
-
*
|
157 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
158 |
-
*
|
159 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
160 |
-
* not in the database
|
161 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
162 |
-
* is corrupt or invalid
|
163 |
-
*
|
164 |
-
* @return \GeoIp2\Model\Domain
|
165 |
-
*/
|
166 |
-
public function domain($ipAddress)
|
167 |
-
{
|
168 |
-
return $this->flatModelFor(
|
169 |
-
'Domain',
|
170 |
-
'GeoIP2-Domain',
|
171 |
-
$ipAddress
|
172 |
-
);
|
173 |
-
}
|
174 |
-
|
175 |
-
/**
|
176 |
-
* This method returns a GeoIP2 Enterprise model.
|
177 |
-
*
|
178 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
179 |
-
*
|
180 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
181 |
-
* not in the database
|
182 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
183 |
-
* is corrupt or invalid
|
184 |
-
*
|
185 |
-
* @return \GeoIp2\Model\Enterprise
|
186 |
-
*/
|
187 |
-
public function enterprise($ipAddress)
|
188 |
-
{
|
189 |
-
return $this->modelFor('Enterprise', 'Enterprise', $ipAddress);
|
190 |
-
}
|
191 |
-
|
192 |
-
/**
|
193 |
-
* This method returns a GeoIP2 ISP model.
|
194 |
-
*
|
195 |
-
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
196 |
-
*
|
197 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
198 |
-
* not in the database
|
199 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
200 |
-
* is corrupt or invalid
|
201 |
-
*
|
202 |
-
* @return \GeoIp2\Model\Isp
|
203 |
-
*/
|
204 |
-
public function isp($ipAddress)
|
205 |
-
{
|
206 |
-
return $this->flatModelFor(
|
207 |
-
'Isp',
|
208 |
-
'GeoIP2-ISP',
|
209 |
-
$ipAddress
|
210 |
-
);
|
211 |
-
}
|
212 |
-
|
213 |
-
private function modelFor($class, $type, $ipAddress)
|
214 |
-
{
|
215 |
-
$record = $this->getRecord($class, $type, $ipAddress);
|
216 |
-
|
217 |
-
$record['traits']['ip_address'] = $ipAddress;
|
218 |
-
$class = 'GeoIp2\\Model\\' . $class;
|
219 |
-
|
220 |
-
return new $class($record, $this->locales);
|
221 |
-
}
|
222 |
-
|
223 |
-
private function flatModelFor($class, $type, $ipAddress)
|
224 |
-
{
|
225 |
-
$record = $this->getRecord($class, $type, $ipAddress);
|
226 |
-
|
227 |
-
$record['ip_address'] = $ipAddress;
|
228 |
-
$class = 'GeoIp2\\Model\\' . $class;
|
229 |
-
|
230 |
-
return new $class($record);
|
231 |
-
}
|
232 |
-
|
233 |
-
private function getRecord($class, $type, $ipAddress)
|
234 |
-
{
|
235 |
-
if (strpos($this->metadata()->databaseType, $type) === false) {
|
236 |
-
$method = lcfirst($class);
|
237 |
-
throw new \BadMethodCallException(
|
238 |
-
"The $method method cannot be used to open a "
|
239 |
-
. $this->metadata()->databaseType . ' database'
|
240 |
-
);
|
241 |
-
}
|
242 |
-
$record = $this->dbReader->get($ipAddress);
|
243 |
-
if ($record === null) {
|
244 |
-
throw new AddressNotFoundException(
|
245 |
-
"The address $ipAddress is not in the database."
|
246 |
-
);
|
247 |
-
}
|
248 |
-
if (!is_array($record)) {
|
249 |
-
// This can happen on corrupt databases. Generally,
|
250 |
-
// MaxMind\Db\Reader will throw a
|
251 |
-
// MaxMind\Db\Reader\InvalidDatabaseException, but occasionally
|
252 |
-
// the lookup may result in a record that looks valid but is not
|
253 |
-
// an array. This mostly happens when the user is ignoring all
|
254 |
-
// exceptions and the more frequent InvalidDatabaseException
|
255 |
-
// exceptions go unnoticed.
|
256 |
-
throw new InvalidDatabaseException(
|
257 |
-
"Expected an array when looking up $ipAddress but received: "
|
258 |
-
. gettype($record)
|
259 |
-
);
|
260 |
-
}
|
261 |
-
|
262 |
-
return $record;
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* @throws \InvalidArgumentException if arguments are passed to the method
|
267 |
-
* @throws \BadMethodCallException if the database has been closed
|
268 |
-
*
|
269 |
-
* @return \MaxMind\Db\Reader\Metadata object for the database
|
270 |
-
*/
|
271 |
-
public function metadata()
|
272 |
-
{
|
273 |
-
return $this->dbReader->metadata();
|
274 |
-
}
|
275 |
-
|
276 |
-
/**
|
277 |
-
* Closes the GeoIP2 database and returns the resources to the system.
|
278 |
-
*/
|
279 |
-
public function close()
|
280 |
-
{
|
281 |
-
$this->dbReader->close();
|
282 |
-
}
|
283 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Database;
|
4 |
+
|
5 |
+
use GeoIp2\Exception\AddressNotFoundException;
|
6 |
+
use GeoIp2\ProviderInterface;
|
7 |
+
use MaxMind\Db\Reader as DbReader;
|
8 |
+
use MaxMind\Db\Reader\InvalidDatabaseException;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Instances of this class provide a reader for the GeoIP2 database format.
|
12 |
+
* IP addresses can be looked up using the database specific methods.
|
13 |
+
*
|
14 |
+
* ## Usage ##
|
15 |
+
*
|
16 |
+
* The basic API for this class is the same for every database. First, you
|
17 |
+
* create a reader object, specifying a file name. You then call the method
|
18 |
+
* corresponding to the specific database, passing it the IP address you want
|
19 |
+
* to look up.
|
20 |
+
*
|
21 |
+
* If the request succeeds, the method call will return a model class for
|
22 |
+
* the method you called. This model in turn contains multiple record classes,
|
23 |
+
* each of which represents part of the data returned by the database. If
|
24 |
+
* the database does not contain the requested information, the attributes
|
25 |
+
* on the record class will have a `null` value.
|
26 |
+
*
|
27 |
+
* If the address is not in the database, an
|
28 |
+
* {@link \GeoIp2\Exception\AddressNotFoundException} exception will be
|
29 |
+
* thrown. If an invalid IP address is passed to one of the methods, a
|
30 |
+
* SPL {@link \InvalidArgumentException} will be thrown. If the database is
|
31 |
+
* corrupt or invalid, a {@link \MaxMind\Db\Reader\InvalidDatabaseException}
|
32 |
+
* will be thrown.
|
33 |
+
*/
|
34 |
+
class Reader implements ProviderInterface
|
35 |
+
{
|
36 |
+
private $dbReader;
|
37 |
+
private $locales;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Constructor.
|
41 |
+
*
|
42 |
+
* @param string $filename the path to the GeoIP2 database file
|
43 |
+
* @param array $locales list of locale codes to use in name property
|
44 |
+
* from most preferred to least preferred
|
45 |
+
*
|
46 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
47 |
+
* is corrupt or invalid
|
48 |
+
*/
|
49 |
+
public function __construct(
|
50 |
+
$filename,
|
51 |
+
$locales = ['en']
|
52 |
+
) {
|
53 |
+
$this->dbReader = new DbReader($filename);
|
54 |
+
$this->locales = $locales;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* This method returns a GeoIP2 City model.
|
59 |
+
*
|
60 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
61 |
+
*
|
62 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
63 |
+
* not in the database
|
64 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
65 |
+
* is corrupt or invalid
|
66 |
+
*
|
67 |
+
* @return \GeoIp2\Model\City
|
68 |
+
*/
|
69 |
+
public function city($ipAddress)
|
70 |
+
{
|
71 |
+
return $this->modelFor('City', 'City', $ipAddress);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* This method returns a GeoIP2 Country model.
|
76 |
+
*
|
77 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
78 |
+
*
|
79 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
80 |
+
* not in the database
|
81 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
82 |
+
* is corrupt or invalid
|
83 |
+
*
|
84 |
+
* @return \GeoIp2\Model\Country
|
85 |
+
*/
|
86 |
+
public function country($ipAddress)
|
87 |
+
{
|
88 |
+
return $this->modelFor('Country', 'Country', $ipAddress);
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* This method returns a GeoIP2 Anonymous IP model.
|
93 |
+
*
|
94 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
95 |
+
*
|
96 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
97 |
+
* not in the database
|
98 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
99 |
+
* is corrupt or invalid
|
100 |
+
*
|
101 |
+
* @return \GeoIp2\Model\AnonymousIp
|
102 |
+
*/
|
103 |
+
public function anonymousIp($ipAddress)
|
104 |
+
{
|
105 |
+
return $this->flatModelFor(
|
106 |
+
'AnonymousIp',
|
107 |
+
'GeoIP2-Anonymous-IP',
|
108 |
+
$ipAddress
|
109 |
+
);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* This method returns a GeoLite2 ASN model.
|
114 |
+
*
|
115 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
116 |
+
*
|
117 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
118 |
+
* not in the database
|
119 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
120 |
+
* is corrupt or invalid
|
121 |
+
*
|
122 |
+
* @return \GeoIp2\Model\Asn
|
123 |
+
*/
|
124 |
+
public function asn($ipAddress)
|
125 |
+
{
|
126 |
+
return $this->flatModelFor(
|
127 |
+
'Asn',
|
128 |
+
'GeoLite2-ASN',
|
129 |
+
$ipAddress
|
130 |
+
);
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* This method returns a GeoIP2 Connection Type model.
|
135 |
+
*
|
136 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
137 |
+
*
|
138 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
139 |
+
* not in the database
|
140 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
141 |
+
* is corrupt or invalid
|
142 |
+
*
|
143 |
+
* @return \GeoIp2\Model\ConnectionType
|
144 |
+
*/
|
145 |
+
public function connectionType($ipAddress)
|
146 |
+
{
|
147 |
+
return $this->flatModelFor(
|
148 |
+
'ConnectionType',
|
149 |
+
'GeoIP2-Connection-Type',
|
150 |
+
$ipAddress
|
151 |
+
);
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* This method returns a GeoIP2 Domain model.
|
156 |
+
*
|
157 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
158 |
+
*
|
159 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
160 |
+
* not in the database
|
161 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
162 |
+
* is corrupt or invalid
|
163 |
+
*
|
164 |
+
* @return \GeoIp2\Model\Domain
|
165 |
+
*/
|
166 |
+
public function domain($ipAddress)
|
167 |
+
{
|
168 |
+
return $this->flatModelFor(
|
169 |
+
'Domain',
|
170 |
+
'GeoIP2-Domain',
|
171 |
+
$ipAddress
|
172 |
+
);
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* This method returns a GeoIP2 Enterprise model.
|
177 |
+
*
|
178 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
179 |
+
*
|
180 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
181 |
+
* not in the database
|
182 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
183 |
+
* is corrupt or invalid
|
184 |
+
*
|
185 |
+
* @return \GeoIp2\Model\Enterprise
|
186 |
+
*/
|
187 |
+
public function enterprise($ipAddress)
|
188 |
+
{
|
189 |
+
return $this->modelFor('Enterprise', 'Enterprise', $ipAddress);
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* This method returns a GeoIP2 ISP model.
|
194 |
+
*
|
195 |
+
* @param string $ipAddress an IPv4 or IPv6 address as a string
|
196 |
+
*
|
197 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
|
198 |
+
* not in the database
|
199 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
|
200 |
+
* is corrupt or invalid
|
201 |
+
*
|
202 |
+
* @return \GeoIp2\Model\Isp
|
203 |
+
*/
|
204 |
+
public function isp($ipAddress)
|
205 |
+
{
|
206 |
+
return $this->flatModelFor(
|
207 |
+
'Isp',
|
208 |
+
'GeoIP2-ISP',
|
209 |
+
$ipAddress
|
210 |
+
);
|
211 |
+
}
|
212 |
+
|
213 |
+
private function modelFor($class, $type, $ipAddress)
|
214 |
+
{
|
215 |
+
$record = $this->getRecord($class, $type, $ipAddress);
|
216 |
+
|
217 |
+
$record['traits']['ip_address'] = $ipAddress;
|
218 |
+
$class = 'GeoIp2\\Model\\' . $class;
|
219 |
+
|
220 |
+
return new $class($record, $this->locales);
|
221 |
+
}
|
222 |
+
|
223 |
+
private function flatModelFor($class, $type, $ipAddress)
|
224 |
+
{
|
225 |
+
$record = $this->getRecord($class, $type, $ipAddress);
|
226 |
+
|
227 |
+
$record['ip_address'] = $ipAddress;
|
228 |
+
$class = 'GeoIp2\\Model\\' . $class;
|
229 |
+
|
230 |
+
return new $class($record);
|
231 |
+
}
|
232 |
+
|
233 |
+
private function getRecord($class, $type, $ipAddress)
|
234 |
+
{
|
235 |
+
if (strpos($this->metadata()->databaseType, $type) === false) {
|
236 |
+
$method = lcfirst($class);
|
237 |
+
throw new \BadMethodCallException(
|
238 |
+
"The $method method cannot be used to open a "
|
239 |
+
. $this->metadata()->databaseType . ' database'
|
240 |
+
);
|
241 |
+
}
|
242 |
+
$record = $this->dbReader->get($ipAddress);
|
243 |
+
if ($record === null) {
|
244 |
+
throw new AddressNotFoundException(
|
245 |
+
"The address $ipAddress is not in the database."
|
246 |
+
);
|
247 |
+
}
|
248 |
+
if (!is_array($record)) {
|
249 |
+
// This can happen on corrupt databases. Generally,
|
250 |
+
// MaxMind\Db\Reader will throw a
|
251 |
+
// MaxMind\Db\Reader\InvalidDatabaseException, but occasionally
|
252 |
+
// the lookup may result in a record that looks valid but is not
|
253 |
+
// an array. This mostly happens when the user is ignoring all
|
254 |
+
// exceptions and the more frequent InvalidDatabaseException
|
255 |
+
// exceptions go unnoticed.
|
256 |
+
throw new InvalidDatabaseException(
|
257 |
+
"Expected an array when looking up $ipAddress but received: "
|
258 |
+
. gettype($record)
|
259 |
+
);
|
260 |
+
}
|
261 |
+
|
262 |
+
return $record;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* @throws \InvalidArgumentException if arguments are passed to the method
|
267 |
+
* @throws \BadMethodCallException if the database has been closed
|
268 |
+
*
|
269 |
+
* @return \MaxMind\Db\Reader\Metadata object for the database
|
270 |
+
*/
|
271 |
+
public function metadata()
|
272 |
+
{
|
273 |
+
return $this->dbReader->metadata();
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Closes the GeoIP2 database and returns the resources to the system.
|
278 |
+
*/
|
279 |
+
public function close()
|
280 |
+
{
|
281 |
+
$this->dbReader->close();
|
282 |
+
}
|
283 |
+
}
|
includes/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents a generic error.
|
7 |
-
*/
|
8 |
-
class AddressNotFoundException extends GeoIp2Exception
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents a generic error.
|
7 |
+
*/
|
8 |
+
class AddressNotFoundException extends GeoIp2Exception
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents a generic error.
|
7 |
-
*/
|
8 |
-
class AuthenticationException extends GeoIp2Exception
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents a generic error.
|
7 |
+
*/
|
8 |
+
class AuthenticationException extends GeoIp2Exception
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents a generic error.
|
7 |
-
*/
|
8 |
-
class GeoIp2Exception extends \Exception
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents a generic error.
|
7 |
+
*/
|
8 |
+
class GeoIp2Exception extends \Exception
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/geoip2/geoip2/src/Exception/HttpException.php
CHANGED
@@ -1,24 +1,24 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents an HTTP transport error.
|
7 |
-
*/
|
8 |
-
class HttpException extends GeoIp2Exception
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* The URI queried.
|
12 |
-
*/
|
13 |
-
public $uri;
|
14 |
-
|
15 |
-
public function __construct(
|
16 |
-
$message,
|
17 |
-
$httpStatus,
|
18 |
-
$uri,
|
19 |
-
\Exception $previous = null
|
20 |
-
) {
|
21 |
-
$this->uri = $uri;
|
22 |
-
parent::__construct($message, $httpStatus, $previous);
|
23 |
-
}
|
24 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents an HTTP transport error.
|
7 |
+
*/
|
8 |
+
class HttpException extends GeoIp2Exception
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* The URI queried.
|
12 |
+
*/
|
13 |
+
public $uri;
|
14 |
+
|
15 |
+
public function __construct(
|
16 |
+
$message,
|
17 |
+
$httpStatus,
|
18 |
+
$uri,
|
19 |
+
\Exception $previous = null
|
20 |
+
) {
|
21 |
+
$this->uri = $uri;
|
22 |
+
parent::__construct($message, $httpStatus, $previous);
|
23 |
+
}
|
24 |
+
}
|
includes/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php
CHANGED
@@ -1,26 +1,26 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents an error returned by MaxMind's GeoIP2
|
7 |
-
* web service.
|
8 |
-
*/
|
9 |
-
class InvalidRequestException extends HttpException
|
10 |
-
{
|
11 |
-
/**
|
12 |
-
* The code returned by the MaxMind web service.
|
13 |
-
*/
|
14 |
-
public $error;
|
15 |
-
|
16 |
-
public function __construct(
|
17 |
-
$message,
|
18 |
-
$error,
|
19 |
-
$httpStatus,
|
20 |
-
$uri,
|
21 |
-
\Exception $previous = null
|
22 |
-
) {
|
23 |
-
$this->error = $error;
|
24 |
-
parent::__construct($message, $httpStatus, $uri, $previous);
|
25 |
-
}
|
26 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents an error returned by MaxMind's GeoIP2
|
7 |
+
* web service.
|
8 |
+
*/
|
9 |
+
class InvalidRequestException extends HttpException
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* The code returned by the MaxMind web service.
|
13 |
+
*/
|
14 |
+
public $error;
|
15 |
+
|
16 |
+
public function __construct(
|
17 |
+
$message,
|
18 |
+
$error,
|
19 |
+
$httpStatus,
|
20 |
+
$uri,
|
21 |
+
\Exception $previous = null
|
22 |
+
) {
|
23 |
+
$this->error = $error;
|
24 |
+
parent::__construct($message, $httpStatus, $uri, $previous);
|
25 |
+
}
|
26 |
+
}
|
includes/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents a generic error.
|
7 |
-
*/
|
8 |
-
class OutOfQueriesException extends GeoIp2Exception
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents a generic error.
|
7 |
+
*/
|
8 |
+
class OutOfQueriesException extends GeoIp2Exception
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/AbstractModel.php
CHANGED
@@ -1,67 +1,67 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* @ignore
|
7 |
-
*/
|
8 |
-
abstract class AbstractModel implements \JsonSerializable
|
9 |
-
{
|
10 |
-
protected $raw;
|
11 |
-
|
12 |
-
/**
|
13 |
-
* @ignore
|
14 |
-
*
|
15 |
-
* @param mixed $raw
|
16 |
-
*/
|
17 |
-
public function __construct($raw)
|
18 |
-
{
|
19 |
-
$this->raw = $raw;
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @ignore
|
24 |
-
*
|
25 |
-
* @param mixed $field
|
26 |
-
*/
|
27 |
-
protected function get($field)
|
28 |
-
{
|
29 |
-
if (isset($this->raw[$field])) {
|
30 |
-
return $this->raw[$field];
|
31 |
-
}
|
32 |
-
if (preg_match('/^is_/', $field)) {
|
33 |
-
return false;
|
34 |
-
}
|
35 |
-
|
36 |
-
return null;
|
37 |
-
}
|
38 |
-
|
39 |
-
/**
|
40 |
-
* @ignore
|
41 |
-
*
|
42 |
-
* @param mixed $attr
|
43 |
-
*/
|
44 |
-
public function __get($attr)
|
45 |
-
{
|
46 |
-
if ($attr !== 'instance' && property_exists($this, $attr)) {
|
47 |
-
return $this->$attr;
|
48 |
-
}
|
49 |
-
|
50 |
-
throw new \RuntimeException("Unknown attribute: $attr");
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* @ignore
|
55 |
-
*
|
56 |
-
* @param mixed $attr
|
57 |
-
*/
|
58 |
-
public function __isset($attr)
|
59 |
-
{
|
60 |
-
return $attr !== 'instance' && isset($this->$attr);
|
61 |
-
}
|
62 |
-
|
63 |
-
public function jsonSerialize()
|
64 |
-
{
|
65 |
-
return $this->raw;
|
66 |
-
}
|
67 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @ignore
|
7 |
+
*/
|
8 |
+
abstract class AbstractModel implements \JsonSerializable
|
9 |
+
{
|
10 |
+
protected $raw;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @ignore
|
14 |
+
*
|
15 |
+
* @param mixed $raw
|
16 |
+
*/
|
17 |
+
public function __construct($raw)
|
18 |
+
{
|
19 |
+
$this->raw = $raw;
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @ignore
|
24 |
+
*
|
25 |
+
* @param mixed $field
|
26 |
+
*/
|
27 |
+
protected function get($field)
|
28 |
+
{
|
29 |
+
if (isset($this->raw[$field])) {
|
30 |
+
return $this->raw[$field];
|
31 |
+
}
|
32 |
+
if (preg_match('/^is_/', $field)) {
|
33 |
+
return false;
|
34 |
+
}
|
35 |
+
|
36 |
+
return null;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @ignore
|
41 |
+
*
|
42 |
+
* @param mixed $attr
|
43 |
+
*/
|
44 |
+
public function __get($attr)
|
45 |
+
{
|
46 |
+
if ($attr !== 'instance' && property_exists($this, $attr)) {
|
47 |
+
return $this->$attr;
|
48 |
+
}
|
49 |
+
|
50 |
+
throw new \RuntimeException("Unknown attribute: $attr");
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @ignore
|
55 |
+
*
|
56 |
+
* @param mixed $attr
|
57 |
+
*/
|
58 |
+
public function __isset($attr)
|
59 |
+
{
|
60 |
+
return $attr !== 'instance' && isset($this->$attr);
|
61 |
+
}
|
62 |
+
|
63 |
+
public function jsonSerialize()
|
64 |
+
{
|
65 |
+
return $this->raw;
|
66 |
+
}
|
67 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/AnonymousIp.php
CHANGED
@@ -1,46 +1,46 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class provides the GeoIP2 Anonymous IP model.
|
7 |
-
*
|
8 |
-
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
9 |
-
* any sort of anonymous network.
|
10 |
-
* @property-read bool $isAnonymousVpn This is true if the IP address belongs to
|
11 |
-
* an anonymous VPN system.
|
12 |
-
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
13 |
-
* to a hosting provider.
|
14 |
-
* @property-read bool $isPublicProxy This is true if the IP address belongs to
|
15 |
-
* a public proxy.
|
16 |
-
* @property-read bool $isTorExitNode This is true if the IP address is a Tor
|
17 |
-
* exit node.
|
18 |
-
* @property-read string $ipAddress The IP address that the data in the model is
|
19 |
-
* for.
|
20 |
-
*/
|
21 |
-
class AnonymousIp extends AbstractModel
|
22 |
-
{
|
23 |
-
protected $isAnonymous;
|
24 |
-
protected $isAnonymousVpn;
|
25 |
-
protected $isHostingProvider;
|
26 |
-
protected $isPublicProxy;
|
27 |
-
protected $isTorExitNode;
|
28 |
-
protected $ipAddress;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* @ignore
|
32 |
-
*
|
33 |
-
* @param mixed $raw
|
34 |
-
*/
|
35 |
-
public function __construct($raw)
|
36 |
-
{
|
37 |
-
parent::__construct($raw);
|
38 |
-
|
39 |
-
$this->isAnonymous = $this->get('is_anonymous');
|
40 |
-
$this->isAnonymousVpn = $this->get('is_anonymous_vpn');
|
41 |
-
$this->isHostingProvider = $this->get('is_hosting_provider');
|
42 |
-
$this->isPublicProxy = $this->get('is_public_proxy');
|
43 |
-
$this->isTorExitNode = $this->get('is_tor_exit_node');
|
44 |
-
$this->ipAddress = $this->get('ip_address');
|
45 |
-
}
|
46 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class provides the GeoIP2 Anonymous IP model.
|
7 |
+
*
|
8 |
+
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
9 |
+
* any sort of anonymous network.
|
10 |
+
* @property-read bool $isAnonymousVpn This is true if the IP address belongs to
|
11 |
+
* an anonymous VPN system.
|
12 |
+
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
13 |
+
* to a hosting provider.
|
14 |
+
* @property-read bool $isPublicProxy This is true if the IP address belongs to
|
15 |
+
* a public proxy.
|
16 |
+
* @property-read bool $isTorExitNode This is true if the IP address is a Tor
|
17 |
+
* exit node.
|
18 |
+
* @property-read string $ipAddress The IP address that the data in the model is
|
19 |
+
* for.
|
20 |
+
*/
|
21 |
+
class AnonymousIp extends AbstractModel
|
22 |
+
{
|
23 |
+
protected $isAnonymous;
|
24 |
+
protected $isAnonymousVpn;
|
25 |
+
protected $isHostingProvider;
|
26 |
+
protected $isPublicProxy;
|
27 |
+
protected $isTorExitNode;
|
28 |
+
protected $ipAddress;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @ignore
|
32 |
+
*
|
33 |
+
* @param mixed $raw
|
34 |
+
*/
|
35 |
+
public function __construct($raw)
|
36 |
+
{
|
37 |
+
parent::__construct($raw);
|
38 |
+
|
39 |
+
$this->isAnonymous = $this->get('is_anonymous');
|
40 |
+
$this->isAnonymousVpn = $this->get('is_anonymous_vpn');
|
41 |
+
$this->isHostingProvider = $this->get('is_hosting_provider');
|
42 |
+
$this->isPublicProxy = $this->get('is_public_proxy');
|
43 |
+
$this->isTorExitNode = $this->get('is_tor_exit_node');
|
44 |
+
$this->ipAddress = $this->get('ip_address');
|
45 |
+
}
|
46 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/Asn.php
CHANGED
@@ -1,35 +1,35 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class provides the GeoLite2 ASN model.
|
7 |
-
*
|
8 |
-
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
9 |
-
* associated with the IP address.
|
10 |
-
* @property-read string|null $autonomousSystemOrganization The organization
|
11 |
-
* associated with the registered autonomous system number for the IP
|
12 |
-
* address.
|
13 |
-
* @property-read string $ipAddress The IP address that the data in the model is
|
14 |
-
* for.
|
15 |
-
*/
|
16 |
-
class Asn extends AbstractModel
|
17 |
-
{
|
18 |
-
protected $autonomousSystemNumber;
|
19 |
-
protected $autonomousSystemOrganization;
|
20 |
-
protected $ipAddress;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @ignore
|
24 |
-
*
|
25 |
-
* @param mixed $raw
|
26 |
-
*/
|
27 |
-
public function __construct($raw)
|
28 |
-
{
|
29 |
-
parent::__construct($raw);
|
30 |
-
$this->autonomousSystemNumber = $this->get('autonomous_system_number');
|
31 |
-
$this->autonomousSystemOrganization =
|
32 |
-
$this->get('autonomous_system_organization');
|
33 |
-
$this->ipAddress = $this->get('ip_address');
|
34 |
-
}
|
35 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class provides the GeoLite2 ASN model.
|
7 |
+
*
|
8 |
+
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
9 |
+
* associated with the IP address.
|
10 |
+
* @property-read string|null $autonomousSystemOrganization The organization
|
11 |
+
* associated with the registered autonomous system number for the IP
|
12 |
+
* address.
|
13 |
+
* @property-read string $ipAddress The IP address that the data in the model is
|
14 |
+
* for.
|
15 |
+
*/
|
16 |
+
class Asn extends AbstractModel
|
17 |
+
{
|
18 |
+
protected $autonomousSystemNumber;
|
19 |
+
protected $autonomousSystemOrganization;
|
20 |
+
protected $ipAddress;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @ignore
|
24 |
+
*
|
25 |
+
* @param mixed $raw
|
26 |
+
*/
|
27 |
+
public function __construct($raw)
|
28 |
+
{
|
29 |
+
parent::__construct($raw);
|
30 |
+
$this->autonomousSystemNumber = $this->get('autonomous_system_number');
|
31 |
+
$this->autonomousSystemOrganization =
|
32 |
+
$this->get('autonomous_system_organization');
|
33 |
+
$this->ipAddress = $this->get('ip_address');
|
34 |
+
}
|
35 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/City.php
CHANGED
@@ -1,133 +1,133 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Model class for the data returned by GeoIP2 City web service and database.
|
7 |
-
*
|
8 |
-
* The only difference between the City and Insights model classes is which
|
9 |
-
* fields in each record may be populated. See
|
10 |
-
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
-
*
|
12 |
-
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
13 |
-
* address.
|
14 |
-
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
15 |
-
* requested IP address.
|
16 |
-
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
17 |
-
* IP address. This object represents the country where MaxMind believes the
|
18 |
-
* end user is located.
|
19 |
-
* @property-read \GeoIp2\Record\Location $location Location data for the
|
20 |
-
* requested IP address.
|
21 |
-
* @property-read \GeoIp2\Record\Postal $postal Postal data for the
|
22 |
-
* requested IP address.
|
23 |
-
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
24 |
-
* account.
|
25 |
-
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
26 |
-
* data for the requested IP address. This record represents the country
|
27 |
-
* where the ISP has registered a given IP block and may differ from the
|
28 |
-
* user's country.
|
29 |
-
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
30 |
-
* Represented country data for the requested IP address. The represented
|
31 |
-
* country is used for things like military bases. It is only present when
|
32 |
-
* the represented country differs from the country.
|
33 |
-
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
34 |
-
* objects representing the country subdivisions for the requested IP
|
35 |
-
* address. The number and type of subdivisions varies by country, but a
|
36 |
-
* subdivision is typically a state, province, county, etc. Subdivisions
|
37 |
-
* are ordered from most general (largest) to most specific (smallest).
|
38 |
-
* If the response did not contain any subdivisions, this method returns
|
39 |
-
* an empty array.
|
40 |
-
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
41 |
-
* representing the most specific subdivision returned. If the response
|
42 |
-
* did not contain any subdivisions, this method returns an empty
|
43 |
-
* {@link \GeoIp2\Record\Subdivision} object.
|
44 |
-
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
45 |
-
* requested IP address.
|
46 |
-
*/
|
47 |
-
class City extends Country
|
48 |
-
{
|
49 |
-
/**
|
50 |
-
* @ignore
|
51 |
-
*/
|
52 |
-
protected $city;
|
53 |
-
/**
|
54 |
-
* @ignore
|
55 |
-
*/
|
56 |
-
protected $location;
|
57 |
-
/**
|
58 |
-
* @ignore
|
59 |
-
*/
|
60 |
-
protected $postal;
|
61 |
-
/**
|
62 |
-
* @ignore
|
63 |
-
*/
|
64 |
-
protected $subdivisions = [];
|
65 |
-
|
66 |
-
/**
|
67 |
-
* @ignore
|
68 |
-
*
|
69 |
-
* @param mixed $raw
|
70 |
-
* @param mixed $locales
|
71 |
-
*/
|
72 |
-
public function __construct($raw, $locales = ['en'])
|
73 |
-
{
|
74 |
-
parent::__construct($raw, $locales);
|
75 |
-
|
76 |
-
$this->city = new \GeoIp2\Record\City($this->get('city'), $locales);
|
77 |
-
$this->location = new \GeoIp2\Record\Location($this->get('location'));
|
78 |
-
$this->postal = new \GeoIp2\Record\Postal($this->get('postal'));
|
79 |
-
|
80 |
-
$this->createSubdivisions($raw, $locales);
|
81 |
-
}
|
82 |
-
|
83 |
-
private function createSubdivisions($raw, $locales)
|
84 |
-
{
|
85 |
-
if (!isset($raw['subdivisions'])) {
|
86 |
-
return;
|
87 |
-
}
|
88 |
-
|
89 |
-
foreach ($raw['subdivisions'] as $sub) {
|
90 |
-
array_push(
|
91 |
-
$this->subdivisions,
|
92 |
-
new \GeoIp2\Record\Subdivision($sub, $locales)
|
93 |
-
);
|
94 |
-
}
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* @ignore
|
99 |
-
*
|
100 |
-
* @param mixed $attr
|
101 |
-
*/
|
102 |
-
public function __get($attr)
|
103 |
-
{
|
104 |
-
if ($attr === 'mostSpecificSubdivision') {
|
105 |
-
return $this->$attr();
|
106 |
-
}
|
107 |
-
|
108 |
-
return parent::__get($attr);
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* @ignore
|
113 |
-
*
|
114 |
-
* @param mixed $attr
|
115 |
-
*/
|
116 |
-
public function __isset($attr)
|
117 |
-
{
|
118 |
-
if ($attr === 'mostSpecificSubdivision') {
|
119 |
-
// We always return a mostSpecificSubdivision, even if it is the
|
120 |
-
// empty subdivision
|
121 |
-
return true;
|
122 |
-
}
|
123 |
-
|
124 |
-
return parent::__isset($attr);
|
125 |
-
}
|
126 |
-
|
127 |
-
private function mostSpecificSubdivision()
|
128 |
-
{
|
129 |
-
return empty($this->subdivisions) ?
|
130 |
-
new \GeoIp2\Record\Subdivision([], $this->locales) :
|
131 |
-
end($this->subdivisions);
|
132 |
-
}
|
133 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Model class for the data returned by GeoIP2 City web service and database.
|
7 |
+
*
|
8 |
+
* The only difference between the City and Insights model classes is which
|
9 |
+
* fields in each record may be populated. See
|
10 |
+
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
+
*
|
12 |
+
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
13 |
+
* address.
|
14 |
+
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
15 |
+
* requested IP address.
|
16 |
+
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
17 |
+
* IP address. This object represents the country where MaxMind believes the
|
18 |
+
* end user is located.
|
19 |
+
* @property-read \GeoIp2\Record\Location $location Location data for the
|
20 |
+
* requested IP address.
|
21 |
+
* @property-read \GeoIp2\Record\Postal $postal Postal data for the
|
22 |
+
* requested IP address.
|
23 |
+
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
24 |
+
* account.
|
25 |
+
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
26 |
+
* data for the requested IP address. This record represents the country
|
27 |
+
* where the ISP has registered a given IP block and may differ from the
|
28 |
+
* user's country.
|
29 |
+
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
30 |
+
* Represented country data for the requested IP address. The represented
|
31 |
+
* country is used for things like military bases. It is only present when
|
32 |
+
* the represented country differs from the country.
|
33 |
+
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
34 |
+
* objects representing the country subdivisions for the requested IP
|
35 |
+
* address. The number and type of subdivisions varies by country, but a
|
36 |
+
* subdivision is typically a state, province, county, etc. Subdivisions
|
37 |
+
* are ordered from most general (largest) to most specific (smallest).
|
38 |
+
* If the response did not contain any subdivisions, this method returns
|
39 |
+
* an empty array.
|
40 |
+
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
41 |
+
* representing the most specific subdivision returned. If the response
|
42 |
+
* did not contain any subdivisions, this method returns an empty
|
43 |
+
* {@link \GeoIp2\Record\Subdivision} object.
|
44 |
+
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
45 |
+
* requested IP address.
|
46 |
+
*/
|
47 |
+
class City extends Country
|
48 |
+
{
|
49 |
+
/**
|
50 |
+
* @ignore
|
51 |
+
*/
|
52 |
+
protected $city;
|
53 |
+
/**
|
54 |
+
* @ignore
|
55 |
+
*/
|
56 |
+
protected $location;
|
57 |
+
/**
|
58 |
+
* @ignore
|
59 |
+
*/
|
60 |
+
protected $postal;
|
61 |
+
/**
|
62 |
+
* @ignore
|
63 |
+
*/
|
64 |
+
protected $subdivisions = [];
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @ignore
|
68 |
+
*
|
69 |
+
* @param mixed $raw
|
70 |
+
* @param mixed $locales
|
71 |
+
*/
|
72 |
+
public function __construct($raw, $locales = ['en'])
|
73 |
+
{
|
74 |
+
parent::__construct($raw, $locales);
|
75 |
+
|
76 |
+
$this->city = new \GeoIp2\Record\City($this->get('city'), $locales);
|
77 |
+
$this->location = new \GeoIp2\Record\Location($this->get('location'));
|
78 |
+
$this->postal = new \GeoIp2\Record\Postal($this->get('postal'));
|
79 |
+
|
80 |
+
$this->createSubdivisions($raw, $locales);
|
81 |
+
}
|
82 |
+
|
83 |
+
private function createSubdivisions($raw, $locales)
|
84 |
+
{
|
85 |
+
if (!isset($raw['subdivisions'])) {
|
86 |
+
return;
|
87 |
+
}
|
88 |
+
|
89 |
+
foreach ($raw['subdivisions'] as $sub) {
|
90 |
+
array_push(
|
91 |
+
$this->subdivisions,
|
92 |
+
new \GeoIp2\Record\Subdivision($sub, $locales)
|
93 |
+
);
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* @ignore
|
99 |
+
*
|
100 |
+
* @param mixed $attr
|
101 |
+
*/
|
102 |
+
public function __get($attr)
|
103 |
+
{
|
104 |
+
if ($attr === 'mostSpecificSubdivision') {
|
105 |
+
return $this->$attr();
|
106 |
+
}
|
107 |
+
|
108 |
+
return parent::__get($attr);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* @ignore
|
113 |
+
*
|
114 |
+
* @param mixed $attr
|
115 |
+
*/
|
116 |
+
public function __isset($attr)
|
117 |
+
{
|
118 |
+
if ($attr === 'mostSpecificSubdivision') {
|
119 |
+
// We always return a mostSpecificSubdivision, even if it is the
|
120 |
+
// empty subdivision
|
121 |
+
return true;
|
122 |
+
}
|
123 |
+
|
124 |
+
return parent::__isset($attr);
|
125 |
+
}
|
126 |
+
|
127 |
+
private function mostSpecificSubdivision()
|
128 |
+
{
|
129 |
+
return empty($this->subdivisions) ?
|
130 |
+
new \GeoIp2\Record\Subdivision([], $this->locales) :
|
131 |
+
end($this->subdivisions);
|
132 |
+
}
|
133 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/ConnectionType.php
CHANGED
@@ -1,31 +1,31 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class provides the GeoIP2 Connection-Type model.
|
7 |
-
*
|
8 |
-
* @property-read string|null $connectionType The connection type may take the
|
9 |
-
* following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
|
10 |
-
* Additional values may be added in the future.
|
11 |
-
* @property-read string $ipAddress The IP address that the data in the model is
|
12 |
-
* for.
|
13 |
-
*/
|
14 |
-
class ConnectionType extends AbstractModel
|
15 |
-
{
|
16 |
-
protected $connectionType;
|
17 |
-
protected $ipAddress;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @ignore
|
21 |
-
*
|
22 |
-
* @param mixed $raw
|
23 |
-
*/
|
24 |
-
public function __construct($raw)
|
25 |
-
{
|
26 |
-
parent::__construct($raw);
|
27 |
-
|
28 |
-
$this->connectionType = $this->get('connection_type');
|
29 |
-
$this->ipAddress = $this->get('ip_address');
|
30 |
-
}
|
31 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class provides the GeoIP2 Connection-Type model.
|
7 |
+
*
|
8 |
+
* @property-read string|null $connectionType The connection type may take the
|
9 |
+
* following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
|
10 |
+
* Additional values may be added in the future.
|
11 |
+
* @property-read string $ipAddress The IP address that the data in the model is
|
12 |
+
* for.
|
13 |
+
*/
|
14 |
+
class ConnectionType extends AbstractModel
|
15 |
+
{
|
16 |
+
protected $connectionType;
|
17 |
+
protected $ipAddress;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @ignore
|
21 |
+
*
|
22 |
+
* @param mixed $raw
|
23 |
+
*/
|
24 |
+
public function __construct($raw)
|
25 |
+
{
|
26 |
+
parent::__construct($raw);
|
27 |
+
|
28 |
+
$this->connectionType = $this->get('connection_type');
|
29 |
+
$this->ipAddress = $this->get('ip_address');
|
30 |
+
}
|
31 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/Country.php
CHANGED
@@ -1,71 +1,71 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Model class for the data returned by GeoIP2 Country web service and database.
|
7 |
-
*
|
8 |
-
* The only difference between the City and Insights model classes is which
|
9 |
-
* fields in each record may be populated. See
|
10 |
-
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
-
*
|
12 |
-
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
13 |
-
* requested IP address.
|
14 |
-
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
15 |
-
* IP address. This object represents the country where MaxMind believes the
|
16 |
-
* end user is located.
|
17 |
-
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
18 |
-
* account.
|
19 |
-
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
20 |
-
* data for the requested IP address. This record represents the country
|
21 |
-
* where the ISP has registered a given IP block and may differ from the
|
22 |
-
* user's country.
|
23 |
-
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
24 |
-
* Represented country data for the requested IP address. The represented
|
25 |
-
* country is used for things like military bases. It is only present when
|
26 |
-
* the represented country differs from the country.
|
27 |
-
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
28 |
-
* requested IP address.
|
29 |
-
*/
|
30 |
-
class Country extends AbstractModel
|
31 |
-
{
|
32 |
-
protected $continent;
|
33 |
-
protected $country;
|
34 |
-
protected $locales;
|
35 |
-
protected $maxmind;
|
36 |
-
protected $registeredCountry;
|
37 |
-
protected $representedCountry;
|
38 |
-
protected $traits;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* @ignore
|
42 |
-
*
|
43 |
-
* @param mixed $raw
|
44 |
-
* @param mixed $locales
|
45 |
-
*/
|
46 |
-
public function __construct($raw, $locales = ['en'])
|
47 |
-
{
|
48 |
-
parent::__construct($raw);
|
49 |
-
|
50 |
-
$this->continent = new \GeoIp2\Record\Continent(
|
51 |
-
$this->get('continent'),
|
52 |
-
$locales
|
53 |
-
);
|
54 |
-
$this->country = new \GeoIp2\Record\Country(
|
55 |
-
$this->get('country'),
|
56 |
-
$locales
|
57 |
-
);
|
58 |
-
$this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind'));
|
59 |
-
$this->registeredCountry = new \GeoIp2\Record\Country(
|
60 |
-
$this->get('registered_country'),
|
61 |
-
$locales
|
62 |
-
);
|
63 |
-
$this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
|
64 |
-
$this->get('represented_country'),
|
65 |
-
$locales
|
66 |
-
);
|
67 |
-
$this->traits = new \GeoIp2\Record\Traits($this->get('traits'));
|
68 |
-
|
69 |
-
$this->locales = $locales;
|
70 |
-
}
|
71 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Model class for the data returned by GeoIP2 Country web service and database.
|
7 |
+
*
|
8 |
+
* The only difference between the City and Insights model classes is which
|
9 |
+
* fields in each record may be populated. See
|
10 |
+
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
+
*
|
12 |
+
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
13 |
+
* requested IP address.
|
14 |
+
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
15 |
+
* IP address. This object represents the country where MaxMind believes the
|
16 |
+
* end user is located.
|
17 |
+
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
18 |
+
* account.
|
19 |
+
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
20 |
+
* data for the requested IP address. This record represents the country
|
21 |
+
* where the ISP has registered a given IP block and may differ from the
|
22 |
+
* user's country.
|
23 |
+
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
24 |
+
* Represented country data for the requested IP address. The represented
|
25 |
+
* country is used for things like military bases. It is only present when
|
26 |
+
* the represented country differs from the country.
|
27 |
+
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
28 |
+
* requested IP address.
|
29 |
+
*/
|
30 |
+
class Country extends AbstractModel
|
31 |
+
{
|
32 |
+
protected $continent;
|
33 |
+
protected $country;
|
34 |
+
protected $locales;
|
35 |
+
protected $maxmind;
|
36 |
+
protected $registeredCountry;
|
37 |
+
protected $representedCountry;
|
38 |
+
protected $traits;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @ignore
|
42 |
+
*
|
43 |
+
* @param mixed $raw
|
44 |
+
* @param mixed $locales
|
45 |
+
*/
|
46 |
+
public function __construct($raw, $locales = ['en'])
|
47 |
+
{
|
48 |
+
parent::__construct($raw);
|
49 |
+
|
50 |
+
$this->continent = new \GeoIp2\Record\Continent(
|
51 |
+
$this->get('continent'),
|
52 |
+
$locales
|
53 |
+
);
|
54 |
+
$this->country = new \GeoIp2\Record\Country(
|
55 |
+
$this->get('country'),
|
56 |
+
$locales
|
57 |
+
);
|
58 |
+
$this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind'));
|
59 |
+
$this->registeredCountry = new \GeoIp2\Record\Country(
|
60 |
+
$this->get('registered_country'),
|
61 |
+
$locales
|
62 |
+
);
|
63 |
+
$this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
|
64 |
+
$this->get('represented_country'),
|
65 |
+
$locales
|
66 |
+
);
|
67 |
+
$this->traits = new \GeoIp2\Record\Traits($this->get('traits'));
|
68 |
+
|
69 |
+
$this->locales = $locales;
|
70 |
+
}
|
71 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/Domain.php
CHANGED
@@ -1,31 +1,31 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class provides the GeoIP2 Domain model.
|
7 |
-
*
|
8 |
-
* @property-read string|null $domain The second level domain associated with the
|
9 |
-
* IP address. This will be something like "example.com" or
|
10 |
-
* "example.co.uk", not "foo.example.com".
|
11 |
-
* @property-read string $ipAddress The IP address that the data in the model is
|
12 |
-
* for.
|
13 |
-
*/
|
14 |
-
class Domain extends AbstractModel
|
15 |
-
{
|
16 |
-
protected $domain;
|
17 |
-
protected $ipAddress;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @ignore
|
21 |
-
*
|
22 |
-
* @param mixed $raw
|
23 |
-
*/
|
24 |
-
public function __construct($raw)
|
25 |
-
{
|
26 |
-
parent::__construct($raw);
|
27 |
-
|
28 |
-
$this->domain = $this->get('domain');
|
29 |
-
$this->ipAddress = $this->get('ip_address');
|
30 |
-
}
|
31 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class provides the GeoIP2 Domain model.
|
7 |
+
*
|
8 |
+
* @property-read string|null $domain The second level domain associated with the
|
9 |
+
* IP address. This will be something like "example.com" or
|
10 |
+
* "example.co.uk", not "foo.example.com".
|
11 |
+
* @property-read string $ipAddress The IP address that the data in the model is
|
12 |
+
* for.
|
13 |
+
*/
|
14 |
+
class Domain extends AbstractModel
|
15 |
+
{
|
16 |
+
protected $domain;
|
17 |
+
protected $ipAddress;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @ignore
|
21 |
+
*
|
22 |
+
* @param mixed $raw
|
23 |
+
*/
|
24 |
+
public function __construct($raw)
|
25 |
+
{
|
26 |
+
parent::__construct($raw);
|
27 |
+
|
28 |
+
$this->domain = $this->get('domain');
|
29 |
+
$this->ipAddress = $this->get('ip_address');
|
30 |
+
}
|
31 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/Enterprise.php
CHANGED
@@ -1,47 +1,47 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Model class for the data returned by GeoIP2 Enterprise database lookups.
|
7 |
-
*
|
8 |
-
* The only difference between the City and Enterprise model classes is which
|
9 |
-
* fields in each record may be populated. See
|
10 |
-
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
-
*
|
12 |
-
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
13 |
-
* address.
|
14 |
-
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
15 |
-
* requested IP address.
|
16 |
-
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
17 |
-
* IP address. This object represents the country where MaxMind believes the
|
18 |
-
* end user is located.
|
19 |
-
* @property-read \GeoIp2\Record\Location $location Location data for the
|
20 |
-
* requested IP address.
|
21 |
-
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
22 |
-
* account.
|
23 |
-
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
24 |
-
* data for the requested IP address. This record represents the country
|
25 |
-
* where the ISP has registered a given IP block and may differ from the
|
26 |
-
* user's country.
|
27 |
-
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
28 |
-
* Represented country data for the requested IP address. The represented
|
29 |
-
* country is used for things like military bases. It is only present when
|
30 |
-
* the represented country differs from the country.
|
31 |
-
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
32 |
-
* objects representing the country subdivisions for the requested IP
|
33 |
-
* address. The number and type of subdivisions varies by country, but a
|
34 |
-
* subdivision is typically a state, province, county, etc. Subdivisions
|
35 |
-
* are ordered from most general (largest) to most specific (smallest).
|
36 |
-
* If the response did not contain any subdivisions, this method returns
|
37 |
-
* an empty array.
|
38 |
-
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
39 |
-
* representing the most specific subdivision returned. If the response
|
40 |
-
* did not contain any subdivisions, this method returns an empty
|
41 |
-
* {@link \GeoIp2\Record\Subdivision} object.
|
42 |
-
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
43 |
-
* requested IP address.
|
44 |
-
*/
|
45 |
-
class Enterprise extends City
|
46 |
-
{
|
47 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Model class for the data returned by GeoIP2 Enterprise database lookups.
|
7 |
+
*
|
8 |
+
* The only difference between the City and Enterprise model classes is which
|
9 |
+
* fields in each record may be populated. See
|
10 |
+
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
+
*
|
12 |
+
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
13 |
+
* address.
|
14 |
+
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
15 |
+
* requested IP address.
|
16 |
+
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
17 |
+
* IP address. This object represents the country where MaxMind believes the
|
18 |
+
* end user is located.
|
19 |
+
* @property-read \GeoIp2\Record\Location $location Location data for the
|
20 |
+
* requested IP address.
|
21 |
+
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
22 |
+
* account.
|
23 |
+
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
24 |
+
* data for the requested IP address. This record represents the country
|
25 |
+
* where the ISP has registered a given IP block and may differ from the
|
26 |
+
* user's country.
|
27 |
+
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
28 |
+
* Represented country data for the requested IP address. The represented
|
29 |
+
* country is used for things like military bases. It is only present when
|
30 |
+
* the represented country differs from the country.
|
31 |
+
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
32 |
+
* objects representing the country subdivisions for the requested IP
|
33 |
+
* address. The number and type of subdivisions varies by country, but a
|
34 |
+
* subdivision is typically a state, province, county, etc. Subdivisions
|
35 |
+
* are ordered from most general (largest) to most specific (smallest).
|
36 |
+
* If the response did not contain any subdivisions, this method returns
|
37 |
+
* an empty array.
|
38 |
+
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
39 |
+
* representing the most specific subdivision returned. If the response
|
40 |
+
* did not contain any subdivisions, this method returns an empty
|
41 |
+
* {@link \GeoIp2\Record\Subdivision} object.
|
42 |
+
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
43 |
+
* requested IP address.
|
44 |
+
*/
|
45 |
+
class Enterprise extends City
|
46 |
+
{
|
47 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/Insights.php
CHANGED
@@ -1,47 +1,47 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Model class for the data returned by GeoIP2 Precision: Insights web service.
|
7 |
-
*
|
8 |
-
* The only difference between the City and Insights model classes is which
|
9 |
-
* fields in each record may be populated. See
|
10 |
-
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
-
*
|
12 |
-
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
13 |
-
* address.
|
14 |
-
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
15 |
-
* requested IP address.
|
16 |
-
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
17 |
-
* IP address. This object represents the country where MaxMind believes the
|
18 |
-
* end user is located.
|
19 |
-
* @property-read \GeoIp2\Record\Location $location Location data for the
|
20 |
-
* requested IP address.
|
21 |
-
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
22 |
-
* account.
|
23 |
-
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
24 |
-
* data for the requested IP address. This record represents the country
|
25 |
-
* where the ISP has registered a given IP block and may differ from the
|
26 |
-
* user's country.
|
27 |
-
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
28 |
-
* Represented country data for the requested IP address. The represented
|
29 |
-
* country is used for things like military bases. It is only present when
|
30 |
-
* the represented country differs from the country.
|
31 |
-
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
32 |
-
* objects representing the country subdivisions for the requested IP
|
33 |
-
* address. The number and type of subdivisions varies by country, but a
|
34 |
-
* subdivision is typically a state, province, county, etc. Subdivisions
|
35 |
-
* are ordered from most general (largest) to most specific (smallest).
|
36 |
-
* If the response did not contain any subdivisions, this method returns
|
37 |
-
* an empty array.
|
38 |
-
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
39 |
-
* representing the most specific subdivision returned. If the response
|
40 |
-
* did not contain any subdivisions, this method returns an empty
|
41 |
-
* {@link \GeoIp2\Record\Subdivision} object.
|
42 |
-
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
43 |
-
* requested IP address.
|
44 |
-
*/
|
45 |
-
class Insights extends City
|
46 |
-
{
|
47 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Model class for the data returned by GeoIP2 Precision: Insights web service.
|
7 |
+
*
|
8 |
+
* The only difference between the City and Insights model classes is which
|
9 |
+
* fields in each record may be populated. See
|
10 |
+
* http://dev.maxmind.com/geoip/geoip2/web-services more details.
|
11 |
+
*
|
12 |
+
* @property-read \GeoIp2\Record\City $city City data for the requested IP
|
13 |
+
* address.
|
14 |
+
* @property-read \GeoIp2\Record\Continent $continent Continent data for the
|
15 |
+
* requested IP address.
|
16 |
+
* @property-read \GeoIp2\Record\Country $country Country data for the requested
|
17 |
+
* IP address. This object represents the country where MaxMind believes the
|
18 |
+
* end user is located.
|
19 |
+
* @property-read \GeoIp2\Record\Location $location Location data for the
|
20 |
+
* requested IP address.
|
21 |
+
* @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
|
22 |
+
* account.
|
23 |
+
* @property-read \GeoIp2\Record\Country $registeredCountry Registered country
|
24 |
+
* data for the requested IP address. This record represents the country
|
25 |
+
* where the ISP has registered a given IP block and may differ from the
|
26 |
+
* user's country.
|
27 |
+
* @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
|
28 |
+
* Represented country data for the requested IP address. The represented
|
29 |
+
* country is used for things like military bases. It is only present when
|
30 |
+
* the represented country differs from the country.
|
31 |
+
* @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
|
32 |
+
* objects representing the country subdivisions for the requested IP
|
33 |
+
* address. The number and type of subdivisions varies by country, but a
|
34 |
+
* subdivision is typically a state, province, county, etc. Subdivisions
|
35 |
+
* are ordered from most general (largest) to most specific (smallest).
|
36 |
+
* If the response did not contain any subdivisions, this method returns
|
37 |
+
* an empty array.
|
38 |
+
* @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object
|
39 |
+
* representing the most specific subdivision returned. If the response
|
40 |
+
* did not contain any subdivisions, this method returns an empty
|
41 |
+
* {@link \GeoIp2\Record\Subdivision} object.
|
42 |
+
* @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
|
43 |
+
* requested IP address.
|
44 |
+
*/
|
45 |
+
class Insights extends City
|
46 |
+
{
|
47 |
+
}
|
includes/vendor/geoip2/geoip2/src/Model/Isp.php
CHANGED
@@ -1,44 +1,44 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Model;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class provides the GeoIP2 ISP model.
|
7 |
-
*
|
8 |
-
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
9 |
-
* associated with the IP address.
|
10 |
-
* @property-read string|null $autonomousSystemOrganization The organization
|
11 |
-
* associated with the registered autonomous system number for the IP
|
12 |
-
* address.
|
13 |
-
* @property-read string|null $isp The name of the ISP associated with the IP
|
14 |
-
* address.
|
15 |
-
* @property-read string|null $organization The name of the organization associated
|
16 |
-
* with the IP address.
|
17 |
-
* @property-read string $ipAddress The IP address that the data in the model is
|
18 |
-
* for.
|
19 |
-
*/
|
20 |
-
class Isp extends AbstractModel
|
21 |
-
{
|
22 |
-
protected $autonomousSystemNumber;
|
23 |
-
protected $autonomousSystemOrganization;
|
24 |
-
protected $isp;
|
25 |
-
protected $organization;
|
26 |
-
protected $ipAddress;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @ignore
|
30 |
-
*
|
31 |
-
* @param mixed $raw
|
32 |
-
*/
|
33 |
-
public function __construct($raw)
|
34 |
-
{
|
35 |
-
parent::__construct($raw);
|
36 |
-
$this->autonomousSystemNumber = $this->get('autonomous_system_number');
|
37 |
-
$this->autonomousSystemOrganization =
|
38 |
-
$this->get('autonomous_system_organization');
|
39 |
-
$this->isp = $this->get('isp');
|
40 |
-
$this->organization = $this->get('organization');
|
41 |
-
|
42 |
-
$this->ipAddress = $this->get('ip_address');
|
43 |
-
}
|
44 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Model;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class provides the GeoIP2 ISP model.
|
7 |
+
*
|
8 |
+
* @property-read int|null $autonomousSystemNumber The autonomous system number
|
9 |
+
* associated with the IP address.
|
10 |
+
* @property-read string|null $autonomousSystemOrganization The organization
|
11 |
+
* associated with the registered autonomous system number for the IP
|
12 |
+
* address.
|
13 |
+
* @property-read string|null $isp The name of the ISP associated with the IP
|
14 |
+
* address.
|
15 |
+
* @property-read string|null $organization The name of the organization associated
|
16 |
+
* with the IP address.
|
17 |
+
* @property-read string $ipAddress The IP address that the data in the model is
|
18 |
+
* for.
|
19 |
+
*/
|
20 |
+
class Isp extends AbstractModel
|
21 |
+
{
|
22 |
+
protected $autonomousSystemNumber;
|
23 |
+
protected $autonomousSystemOrganization;
|
24 |
+
protected $isp;
|
25 |
+
protected $organization;
|
26 |
+
protected $ipAddress;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @ignore
|
30 |
+
*
|
31 |
+
* @param mixed $raw
|
32 |
+
*/
|
33 |
+
public function __construct($raw)
|
34 |
+
{
|
35 |
+
parent::__construct($raw);
|
36 |
+
$this->autonomousSystemNumber = $this->get('autonomous_system_number');
|
37 |
+
$this->autonomousSystemOrganization =
|
38 |
+
$this->get('autonomous_system_organization');
|
39 |
+
$this->isp = $this->get('isp');
|
40 |
+
$this->organization = $this->get('organization');
|
41 |
+
|
42 |
+
$this->ipAddress = $this->get('ip_address');
|
43 |
+
}
|
44 |
+
}
|
includes/vendor/geoip2/geoip2/src/ProviderInterface.php
CHANGED
@@ -1,20 +1,20 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2;
|
4 |
-
|
5 |
-
interface ProviderInterface
|
6 |
-
{
|
7 |
-
/**
|
8 |
-
* @param string $ipAddress an IPv4 or IPv6 address to lookup
|
9 |
-
*
|
10 |
-
* @return \GeoIp2\Model\Country a Country model for the requested IP address
|
11 |
-
*/
|
12 |
-
public function country($ipAddress);
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @param string $ipAddress an IPv4 or IPv6 address to lookup
|
16 |
-
*
|
17 |
-
* @return \GeoIp2\Model\City a City model for the requested IP address
|
18 |
-
*/
|
19 |
-
public function city($ipAddress);
|
20 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2;
|
4 |
+
|
5 |
+
interface ProviderInterface
|
6 |
+
{
|
7 |
+
/**
|
8 |
+
* @param string $ipAddress an IPv4 or IPv6 address to lookup
|
9 |
+
*
|
10 |
+
* @return \GeoIp2\Model\Country a Country model for the requested IP address
|
11 |
+
*/
|
12 |
+
public function country($ipAddress);
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @param string $ipAddress an IPv4 or IPv6 address to lookup
|
16 |
+
*
|
17 |
+
* @return \GeoIp2\Model\City a City model for the requested IP address
|
18 |
+
*/
|
19 |
+
public function city($ipAddress);
|
20 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php
CHANGED
@@ -1,66 +1,66 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
abstract class AbstractPlaceRecord extends AbstractRecord
|
6 |
-
{
|
7 |
-
private $locales;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* @ignore
|
11 |
-
*
|
12 |
-
* @param mixed $record
|
13 |
-
* @param mixed $locales
|
14 |
-
*/
|
15 |
-
public function __construct($record, $locales = ['en'])
|
16 |
-
{
|
17 |
-
$this->locales = $locales;
|
18 |
-
parent::__construct($record);
|
19 |
-
}
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @ignore
|
23 |
-
*
|
24 |
-
* @param mixed $attr
|
25 |
-
*/
|
26 |
-
public function __get($attr)
|
27 |
-
{
|
28 |
-
if ($attr === 'name') {
|
29 |
-
return $this->name();
|
30 |
-
}
|
31 |
-
|
32 |
-
return parent::__get($attr);
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @ignore
|
37 |
-
*
|
38 |
-
* @param mixed $attr
|
39 |
-
*/
|
40 |
-
public function __isset($attr)
|
41 |
-
{
|
42 |
-
if ($attr === 'name') {
|
43 |
-
return $this->firstSetNameLocale() === null ? false : true;
|
44 |
-
}
|
45 |
-
|
46 |
-
return parent::__isset($attr);
|
47 |
-
}
|
48 |
-
|
49 |
-
private function name()
|
50 |
-
{
|
51 |
-
$locale = $this->firstSetNameLocale();
|
52 |
-
|
53 |
-
return $locale === null ? null : $this->names[$locale];
|
54 |
-
}
|
55 |
-
|
56 |
-
private function firstSetNameLocale()
|
57 |
-
{
|
58 |
-
foreach ($this->locales as $locale) {
|
59 |
-
if (isset($this->names[$locale])) {
|
60 |
-
return $locale;
|
61 |
-
}
|
62 |
-
}
|
63 |
-
|
64 |
-
return null;
|
65 |
-
}
|
66 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
abstract class AbstractPlaceRecord extends AbstractRecord
|
6 |
+
{
|
7 |
+
private $locales;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @ignore
|
11 |
+
*
|
12 |
+
* @param mixed $record
|
13 |
+
* @param mixed $locales
|
14 |
+
*/
|
15 |
+
public function __construct($record, $locales = ['en'])
|
16 |
+
{
|
17 |
+
$this->locales = $locales;
|
18 |
+
parent::__construct($record);
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @ignore
|
23 |
+
*
|
24 |
+
* @param mixed $attr
|
25 |
+
*/
|
26 |
+
public function __get($attr)
|
27 |
+
{
|
28 |
+
if ($attr === 'name') {
|
29 |
+
return $this->name();
|
30 |
+
}
|
31 |
+
|
32 |
+
return parent::__get($attr);
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @ignore
|
37 |
+
*
|
38 |
+
* @param mixed $attr
|
39 |
+
*/
|
40 |
+
public function __isset($attr)
|
41 |
+
{
|
42 |
+
if ($attr === 'name') {
|
43 |
+
return $this->firstSetNameLocale() === null ? false : true;
|
44 |
+
}
|
45 |
+
|
46 |
+
return parent::__isset($attr);
|
47 |
+
}
|
48 |
+
|
49 |
+
private function name()
|
50 |
+
{
|
51 |
+
$locale = $this->firstSetNameLocale();
|
52 |
+
|
53 |
+
return $locale === null ? null : $this->names[$locale];
|
54 |
+
}
|
55 |
+
|
56 |
+
private function firstSetNameLocale()
|
57 |
+
{
|
58 |
+
foreach ($this->locales as $locale) {
|
59 |
+
if (isset($this->names[$locale])) {
|
60 |
+
return $locale;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
return null;
|
65 |
+
}
|
66 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/AbstractRecord.php
CHANGED
@@ -1,61 +1,61 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
abstract class AbstractRecord implements \JsonSerializable
|
6 |
-
{
|
7 |
-
private $record;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* @ignore
|
11 |
-
*
|
12 |
-
* @param mixed $record
|
13 |
-
*/
|
14 |
-
public function __construct($record)
|
15 |
-
{
|
16 |
-
$this->record = isset($record) ? $record : [];
|
17 |
-
}
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @ignore
|
21 |
-
*
|
22 |
-
* @param mixed $attr
|
23 |
-
*/
|
24 |
-
public function __get($attr)
|
25 |
-
{
|
26 |
-
// XXX - kind of ugly but greatly reduces boilerplate code
|
27 |
-
$key = $this->attributeToKey($attr);
|
28 |
-
|
29 |
-
if ($this->__isset($attr)) {
|
30 |
-
return $this->record[$key];
|
31 |
-
} elseif ($this->validAttribute($attr)) {
|
32 |
-
if (preg_match('/^is_/', $key)) {
|
33 |
-
return false;
|
34 |
-
}
|
35 |
-
|
36 |
-
return null;
|
37 |
-
}
|
38 |
-
throw new \RuntimeException("Unknown attribute: $attr");
|
39 |
-
}
|
40 |
-
|
41 |
-
public function __isset($attr)
|
42 |
-
{
|
43 |
-
return $this->validAttribute($attr) &&
|
44 |
-
isset($this->record[$this->attributeToKey($attr)]);
|
45 |
-
}
|
46 |
-
|
47 |
-
private function attributeToKey($attr)
|
48 |
-
{
|
49 |
-
return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));
|
50 |
-
}
|
51 |
-
|
52 |
-
private function validAttribute($attr)
|
53 |
-
{
|
54 |
-
return in_array($attr, $this->validAttributes, true);
|
55 |
-
}
|
56 |
-
|
57 |
-
public function jsonSerialize()
|
58 |
-
{
|
59 |
-
return $this->record;
|
60 |
-
}
|
61 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
abstract class AbstractRecord implements \JsonSerializable
|
6 |
+
{
|
7 |
+
private $record;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @ignore
|
11 |
+
*
|
12 |
+
* @param mixed $record
|
13 |
+
*/
|
14 |
+
public function __construct($record)
|
15 |
+
{
|
16 |
+
$this->record = isset($record) ? $record : [];
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @ignore
|
21 |
+
*
|
22 |
+
* @param mixed $attr
|
23 |
+
*/
|
24 |
+
public function __get($attr)
|
25 |
+
{
|
26 |
+
// XXX - kind of ugly but greatly reduces boilerplate code
|
27 |
+
$key = $this->attributeToKey($attr);
|
28 |
+
|
29 |
+
if ($this->__isset($attr)) {
|
30 |
+
return $this->record[$key];
|
31 |
+
} elseif ($this->validAttribute($attr)) {
|
32 |
+
if (preg_match('/^is_/', $key)) {
|
33 |
+
return false;
|
34 |
+
}
|
35 |
+
|
36 |
+
return null;
|
37 |
+
}
|
38 |
+
throw new \RuntimeException("Unknown attribute: $attr");
|
39 |
+
}
|
40 |
+
|
41 |
+
public function __isset($attr)
|
42 |
+
{
|
43 |
+
return $this->validAttribute($attr) &&
|
44 |
+
isset($this->record[$this->attributeToKey($attr)]);
|
45 |
+
}
|
46 |
+
|
47 |
+
private function attributeToKey($attr)
|
48 |
+
{
|
49 |
+
return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));
|
50 |
+
}
|
51 |
+
|
52 |
+
private function validAttribute($attr)
|
53 |
+
{
|
54 |
+
return in_array($attr, $this->validAttributes, true);
|
55 |
+
}
|
56 |
+
|
57 |
+
public function jsonSerialize()
|
58 |
+
{
|
59 |
+
return $this->record;
|
60 |
+
}
|
61 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/City.php
CHANGED
@@ -1,29 +1,29 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* City-level data associated with an IP address.
|
7 |
-
*
|
8 |
-
* This record is returned by all location services and databases besides
|
9 |
-
* Country.
|
10 |
-
*
|
11 |
-
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
12 |
-
* confidence that the city is correct. This attribute is only available
|
13 |
-
* from the Insights service and the GeoIP2 Enterprise database.
|
14 |
-
* @property-read int|null $geonameId The GeoName ID for the city. This attribute
|
15 |
-
* is returned by all location services and databases.
|
16 |
-
* @property-read string|null $name The name of the city based on the locales list
|
17 |
-
* passed to the constructor. This attribute is returned by all location
|
18 |
-
* services and databases.
|
19 |
-
* @property-read array|null $names A array map where the keys are locale codes
|
20 |
-
* and the values are names. This attribute is returned by all location
|
21 |
-
* services and databases.
|
22 |
-
*/
|
23 |
-
class City extends AbstractPlaceRecord
|
24 |
-
{
|
25 |
-
/**
|
26 |
-
* @ignore
|
27 |
-
*/
|
28 |
-
protected $validAttributes = ['confidence', 'geonameId', 'names'];
|
29 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* City-level data associated with an IP address.
|
7 |
+
*
|
8 |
+
* This record is returned by all location services and databases besides
|
9 |
+
* Country.
|
10 |
+
*
|
11 |
+
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
12 |
+
* confidence that the city is correct. This attribute is only available
|
13 |
+
* from the Insights service and the GeoIP2 Enterprise database.
|
14 |
+
* @property-read int|null $geonameId The GeoName ID for the city. This attribute
|
15 |
+
* is returned by all location services and databases.
|
16 |
+
* @property-read string|null $name The name of the city based on the locales list
|
17 |
+
* passed to the constructor. This attribute is returned by all location
|
18 |
+
* services and databases.
|
19 |
+
* @property-read array|null $names A array map where the keys are locale codes
|
20 |
+
* and the values are names. This attribute is returned by all location
|
21 |
+
* services and databases.
|
22 |
+
*/
|
23 |
+
class City extends AbstractPlaceRecord
|
24 |
+
{
|
25 |
+
/**
|
26 |
+
* @ignore
|
27 |
+
*/
|
28 |
+
protected $validAttributes = ['confidence', 'geonameId', 'names'];
|
29 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/Continent.php
CHANGED
@@ -1,32 +1,32 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data for the continent record associated with an IP address.
|
7 |
-
*
|
8 |
-
* This record is returned by all location services and databases.
|
9 |
-
*
|
10 |
-
* @property-read string|null $code A two character continent code like "NA" (North
|
11 |
-
* America) or "OC" (Oceania). This attribute is returned by all location
|
12 |
-
* services and databases.
|
13 |
-
* @property-read int|null $geonameId The GeoName ID for the continent. This
|
14 |
-
* attribute is returned by all location services and databases.
|
15 |
-
* @property-read string|null $name Returns the name of the continent based on the
|
16 |
-
* locales list passed to the constructor. This attribute is returned by all location
|
17 |
-
* services and databases.
|
18 |
-
* @property-read array|null $names An array map where the keys are locale codes
|
19 |
-
* and the values are names. This attribute is returned by all location
|
20 |
-
* services and databases.
|
21 |
-
*/
|
22 |
-
class Continent extends AbstractPlaceRecord
|
23 |
-
{
|
24 |
-
/**
|
25 |
-
* @ignore
|
26 |
-
*/
|
27 |
-
protected $validAttributes = [
|
28 |
-
'code',
|
29 |
-
'geonameId',
|
30 |
-
'names',
|
31 |
-
];
|
32 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data for the continent record associated with an IP address.
|
7 |
+
*
|
8 |
+
* This record is returned by all location services and databases.
|
9 |
+
*
|
10 |
+
* @property-read string|null $code A two character continent code like "NA" (North
|
11 |
+
* America) or "OC" (Oceania). This attribute is returned by all location
|
12 |
+
* services and databases.
|
13 |
+
* @property-read int|null $geonameId The GeoName ID for the continent. This
|
14 |
+
* attribute is returned by all location services and databases.
|
15 |
+
* @property-read string|null $name Returns the name of the continent based on the
|
16 |
+
* locales list passed to the constructor. This attribute is returned by all location
|
17 |
+
* services and databases.
|
18 |
+
* @property-read array|null $names An array map where the keys are locale codes
|
19 |
+
* and the values are names. This attribute is returned by all location
|
20 |
+
* services and databases.
|
21 |
+
*/
|
22 |
+
class Continent extends AbstractPlaceRecord
|
23 |
+
{
|
24 |
+
/**
|
25 |
+
* @ignore
|
26 |
+
*/
|
27 |
+
protected $validAttributes = [
|
28 |
+
'code',
|
29 |
+
'geonameId',
|
30 |
+
'names',
|
31 |
+
];
|
32 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/Country.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data for the country record associated with an IP address.
|
7 |
-
*
|
8 |
-
* This record is returned by all location services and databases.
|
9 |
-
*
|
10 |
-
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
11 |
-
* confidence that the country is correct. This attribute is only available
|
12 |
-
* from the Insights service and the GeoIP2 Enterprise database.
|
13 |
-
* @property-read int|null $geonameId The GeoName ID for the country. This
|
14 |
-
* attribute is returned by all location services and databases.
|
15 |
-
* @property-read bool $isInEuropeanUnion This is true if the country is a
|
16 |
-
* member state of the European Union. This attribute is returned by all
|
17 |
-
* location services and databases.
|
18 |
-
* @property-read string|null $isoCode The
|
19 |
-
* {@link * http://en.wikipedia.org/wiki/ISO_3166-1 two-character ISO 3166-1 alpha
|
20 |
-
* code} for the country. This attribute is returned by all location services
|
21 |
-
* and databases.
|
22 |
-
* @property-read string|null $name The name of the country based on the locales
|
23 |
-
* list passed to the constructor. This attribute is returned by all location
|
24 |
-
* services and databases.
|
25 |
-
* @property-read array|null $names An array map where the keys are locale codes
|
26 |
-
* and the values are names. This attribute is returned by all location
|
27 |
-
* services and databases.
|
28 |
-
*/
|
29 |
-
class Country extends AbstractPlaceRecord
|
30 |
-
{
|
31 |
-
/**
|
32 |
-
* @ignore
|
33 |
-
*/
|
34 |
-
protected $validAttributes = [
|
35 |
-
'confidence',
|
36 |
-
'geonameId',
|
37 |
-
'isInEuropeanUnion',
|
38 |
-
'isoCode',
|
39 |
-
'names',
|
40 |
-
];
|
41 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data for the country record associated with an IP address.
|
7 |
+
*
|
8 |
+
* This record is returned by all location services and databases.
|
9 |
+
*
|
10 |
+
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
11 |
+
* confidence that the country is correct. This attribute is only available
|
12 |
+
* from the Insights service and the GeoIP2 Enterprise database.
|
13 |
+
* @property-read int|null $geonameId The GeoName ID for the country. This
|
14 |
+
* attribute is returned by all location services and databases.
|
15 |
+
* @property-read bool $isInEuropeanUnion This is true if the country is a
|
16 |
+
* member state of the European Union. This attribute is returned by all
|
17 |
+
* location services and databases.
|
18 |
+
* @property-read string|null $isoCode The
|
19 |
+
* {@link * http://en.wikipedia.org/wiki/ISO_3166-1 two-character ISO 3166-1 alpha
|
20 |
+
* code} for the country. This attribute is returned by all location services
|
21 |
+
* and databases.
|
22 |
+
* @property-read string|null $name The name of the country based on the locales
|
23 |
+
* list passed to the constructor. This attribute is returned by all location
|
24 |
+
* services and databases.
|
25 |
+
* @property-read array|null $names An array map where the keys are locale codes
|
26 |
+
* and the values are names. This attribute is returned by all location
|
27 |
+
* services and databases.
|
28 |
+
*/
|
29 |
+
class Country extends AbstractPlaceRecord
|
30 |
+
{
|
31 |
+
/**
|
32 |
+
* @ignore
|
33 |
+
*/
|
34 |
+
protected $validAttributes = [
|
35 |
+
'confidence',
|
36 |
+
'geonameId',
|
37 |
+
'isInEuropeanUnion',
|
38 |
+
'isoCode',
|
39 |
+
'names',
|
40 |
+
];
|
41 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/Location.php
CHANGED
@@ -1,52 +1,52 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data for the location record associated with an IP address.
|
7 |
-
*
|
8 |
-
* This record is returned by all location services and databases besides
|
9 |
-
* Country.
|
10 |
-
*
|
11 |
-
* @property-read int|null $averageIncome The average income in US dollars
|
12 |
-
* associated with the requested IP address. This attribute is only available
|
13 |
-
* from the Insights service.
|
14 |
-
* @property-read int|null $accuracyRadius The approximate accuracy radius in
|
15 |
-
* kilometers around the latitude and longitude for the IP address. This is
|
16 |
-
* the radius where we have a 67% confidence that the device using the IP
|
17 |
-
* address resides within the circle centered at the latitude and longitude
|
18 |
-
* with the provided radius.
|
19 |
-
* @property-read float|null $latitude The approximate latitude of the location
|
20 |
-
* associated with the IP address. This value is not precise and should not be
|
21 |
-
* used to identify a particular address or household.
|
22 |
-
* @property-read float|null $longitude The approximate longitude of the location
|
23 |
-
* associated with the IP address. This value is not precise and should not be
|
24 |
-
* used to identify a particular address or household.
|
25 |
-
* @property-read int|null $populationDensity The estimated population per square
|
26 |
-
* kilometer associated with the IP address. This attribute is only available
|
27 |
-
* from the Insights service.
|
28 |
-
* @property-read int|null $metroCode The metro code of the location if the location
|
29 |
-
* is in the US. MaxMind returns the same metro codes as the
|
30 |
-
* {@link * https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions
|
31 |
-
* Google AdWords API}.
|
32 |
-
* @property-read string|null $timeZone The time zone associated with location, as
|
33 |
-
* specified by the {@link http://www.iana.org/time-zones IANA Time Zone
|
34 |
-
* Database}, e.g., "America/New_York".
|
35 |
-
*/
|
36 |
-
class Location extends AbstractRecord
|
37 |
-
{
|
38 |
-
/**
|
39 |
-
* @ignore
|
40 |
-
*/
|
41 |
-
protected $validAttributes = [
|
42 |
-
'averageIncome',
|
43 |
-
'accuracyRadius',
|
44 |
-
'latitude',
|
45 |
-
'longitude',
|
46 |
-
'metroCode',
|
47 |
-
'populationDensity',
|
48 |
-
'postalCode',
|
49 |
-
'postalConfidence',
|
50 |
-
'timeZone',
|
51 |
-
];
|
52 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data for the location record associated with an IP address.
|
7 |
+
*
|
8 |
+
* This record is returned by all location services and databases besides
|
9 |
+
* Country.
|
10 |
+
*
|
11 |
+
* @property-read int|null $averageIncome The average income in US dollars
|
12 |
+
* associated with the requested IP address. This attribute is only available
|
13 |
+
* from the Insights service.
|
14 |
+
* @property-read int|null $accuracyRadius The approximate accuracy radius in
|
15 |
+
* kilometers around the latitude and longitude for the IP address. This is
|
16 |
+
* the radius where we have a 67% confidence that the device using the IP
|
17 |
+
* address resides within the circle centered at the latitude and longitude
|
18 |
+
* with the provided radius.
|
19 |
+
* @property-read float|null $latitude The approximate latitude of the location
|
20 |
+
* associated with the IP address. This value is not precise and should not be
|
21 |
+
* used to identify a particular address or household.
|
22 |
+
* @property-read float|null $longitude The approximate longitude of the location
|
23 |
+
* associated with the IP address. This value is not precise and should not be
|
24 |
+
* used to identify a particular address or household.
|
25 |
+
* @property-read int|null $populationDensity The estimated population per square
|
26 |
+
* kilometer associated with the IP address. This attribute is only available
|
27 |
+
* from the Insights service.
|
28 |
+
* @property-read int|null $metroCode The metro code of the location if the location
|
29 |
+
* is in the US. MaxMind returns the same metro codes as the
|
30 |
+
* {@link * https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions
|
31 |
+
* Google AdWords API}.
|
32 |
+
* @property-read string|null $timeZone The time zone associated with location, as
|
33 |
+
* specified by the {@link http://www.iana.org/time-zones IANA Time Zone
|
34 |
+
* Database}, e.g., "America/New_York".
|
35 |
+
*/
|
36 |
+
class Location extends AbstractRecord
|
37 |
+
{
|
38 |
+
/**
|
39 |
+
* @ignore
|
40 |
+
*/
|
41 |
+
protected $validAttributes = [
|
42 |
+
'averageIncome',
|
43 |
+
'accuracyRadius',
|
44 |
+
'latitude',
|
45 |
+
'longitude',
|
46 |
+
'metroCode',
|
47 |
+
'populationDensity',
|
48 |
+
'postalCode',
|
49 |
+
'postalConfidence',
|
50 |
+
'timeZone',
|
51 |
+
];
|
52 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/MaxMind.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data about your account.
|
7 |
-
*
|
8 |
-
* This record is returned by all location services and databases.
|
9 |
-
*
|
10 |
-
* @property-read int|null $queriesRemaining The number of remaining queries you
|
11 |
-
* have for the service you are calling.
|
12 |
-
*/
|
13 |
-
class MaxMind extends AbstractRecord
|
14 |
-
{
|
15 |
-
/**
|
16 |
-
* @ignore
|
17 |
-
*/
|
18 |
-
protected $validAttributes = ['queriesRemaining'];
|
19 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data about your account.
|
7 |
+
*
|
8 |
+
* This record is returned by all location services and databases.
|
9 |
+
*
|
10 |
+
* @property-read int|null $queriesRemaining The number of remaining queries you
|
11 |
+
* have for the service you are calling.
|
12 |
+
*/
|
13 |
+
class MaxMind extends AbstractRecord
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* @ignore
|
17 |
+
*/
|
18 |
+
protected $validAttributes = ['queriesRemaining'];
|
19 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/Postal.php
CHANGED
@@ -1,26 +1,26 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data for the postal record associated with an IP address.
|
7 |
-
*
|
8 |
-
* This record is returned by all location databases and services besides
|
9 |
-
* Country.
|
10 |
-
*
|
11 |
-
* @property-read string|null $code The postal code of the location. Postal codes
|
12 |
-
* are not available for all countries. In some countries, this will only
|
13 |
-
* contain part of the postal code. This attribute is returned by all location
|
14 |
-
* databases and services besides Country.
|
15 |
-
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
16 |
-
* confidence that the postal code is correct. This attribute is only
|
17 |
-
* available from the Insights service and the GeoIP2 Enterprise
|
18 |
-
* database.
|
19 |
-
*/
|
20 |
-
class Postal extends AbstractRecord
|
21 |
-
{
|
22 |
-
/**
|
23 |
-
* @ignore
|
24 |
-
*/
|
25 |
-
protected $validAttributes = ['code', 'confidence'];
|
26 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data for the postal record associated with an IP address.
|
7 |
+
*
|
8 |
+
* This record is returned by all location databases and services besides
|
9 |
+
* Country.
|
10 |
+
*
|
11 |
+
* @property-read string|null $code The postal code of the location. Postal codes
|
12 |
+
* are not available for all countries. In some countries, this will only
|
13 |
+
* contain part of the postal code. This attribute is returned by all location
|
14 |
+
* databases and services besides Country.
|
15 |
+
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
16 |
+
* confidence that the postal code is correct. This attribute is only
|
17 |
+
* available from the Insights service and the GeoIP2 Enterprise
|
18 |
+
* database.
|
19 |
+
*/
|
20 |
+
class Postal extends AbstractRecord
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* @ignore
|
24 |
+
*/
|
25 |
+
protected $validAttributes = ['code', 'confidence'];
|
26 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php
CHANGED
@@ -1,39 +1,39 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data for the represented country associated with an IP address.
|
7 |
-
*
|
8 |
-
* This class contains the country-level data associated with an IP address
|
9 |
-
* for the IP's represented country. The represented country is the country
|
10 |
-
* represented by something like a military base.
|
11 |
-
*
|
12 |
-
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
13 |
-
* confidence that the country is correct. This attribute is only available
|
14 |
-
* from the Insights service and the GeoIP2 Enterprise database.
|
15 |
-
* @property-read int|null $geonameId The GeoName ID for the country.
|
16 |
-
* @property-read bool $isInEuropeanUnion This is true if the country is a
|
17 |
-
* member state of the European Union. This attribute is returned by all
|
18 |
-
* location services and databases.
|
19 |
-
* @property-read string|null $isoCode The {@link http://en.wikipedia.org/wiki/ISO_3166-1
|
20 |
-
* two-character ISO 3166-1 alpha code} for the country.
|
21 |
-
* @property-read string|null $name The name of the country based on the locales list
|
22 |
-
* passed to the constructor.
|
23 |
-
* @property-read array|null $names An array map where the keys are locale codes and
|
24 |
-
* the values are names.
|
25 |
-
* @property-read string|null $type A string indicating the type of entity that is
|
26 |
-
* representing the country. Currently we only return <code>military</code>
|
27 |
-
* but this could expand to include other types in the future.
|
28 |
-
*/
|
29 |
-
class RepresentedCountry extends Country
|
30 |
-
{
|
31 |
-
protected $validAttributes = [
|
32 |
-
'confidence',
|
33 |
-
'geonameId',
|
34 |
-
'isInEuropeanUnion',
|
35 |
-
'isoCode',
|
36 |
-
'names',
|
37 |
-
'type',
|
38 |
-
];
|
39 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data for the represented country associated with an IP address.
|
7 |
+
*
|
8 |
+
* This class contains the country-level data associated with an IP address
|
9 |
+
* for the IP's represented country. The represented country is the country
|
10 |
+
* represented by something like a military base.
|
11 |
+
*
|
12 |
+
* @property-read int|null $confidence A value from 0-100 indicating MaxMind's
|
13 |
+
* confidence that the country is correct. This attribute is only available
|
14 |
+
* from the Insights service and the GeoIP2 Enterprise database.
|
15 |
+
* @property-read int|null $geonameId The GeoName ID for the country.
|
16 |
+
* @property-read bool $isInEuropeanUnion This is true if the country is a
|
17 |
+
* member state of the European Union. This attribute is returned by all
|
18 |
+
* location services and databases.
|
19 |
+
* @property-read string|null $isoCode The {@link http://en.wikipedia.org/wiki/ISO_3166-1
|
20 |
+
* two-character ISO 3166-1 alpha code} for the country.
|
21 |
+
* @property-read string|null $name The name of the country based on the locales list
|
22 |
+
* passed to the constructor.
|
23 |
+
* @property-read array|null $names An array map where the keys are locale codes and
|
24 |
+
* the values are names.
|
25 |
+
* @property-read string|null $type A string indicating the type of entity that is
|
26 |
+
* representing the country. Currently we only return <code>military</code>
|
27 |
+
* but this could expand to include other types in the future.
|
28 |
+
*/
|
29 |
+
class RepresentedCountry extends Country
|
30 |
+
{
|
31 |
+
protected $validAttributes = [
|
32 |
+
'confidence',
|
33 |
+
'geonameId',
|
34 |
+
'isInEuropeanUnion',
|
35 |
+
'isoCode',
|
36 |
+
'names',
|
37 |
+
'type',
|
38 |
+
];
|
39 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/Subdivision.php
CHANGED
@@ -1,40 +1,40 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data for the subdivisions associated with an IP address.
|
7 |
-
*
|
8 |
-
* This record is returned by all location databases and services besides
|
9 |
-
* Country.
|
10 |
-
*
|
11 |
-
* @property-read int|null $confidence This is a value from 0-100 indicating
|
12 |
-
* MaxMind's confidence that the subdivision is correct. This attribute is
|
13 |
-
* only available from the Insights service and the GeoIP2 Enterprise
|
14 |
-
* database.
|
15 |
-
* @property-read int|null $geonameId This is a GeoName ID for the subdivision.
|
16 |
-
* This attribute is returned by all location databases and services besides
|
17 |
-
* Country.
|
18 |
-
* @property-read string|null $isoCode This is a string up to three characters long
|
19 |
-
* contain the subdivision portion of the
|
20 |
-
* {@link * http://en.wikipedia.org/wiki/ISO_3166-2 ISO 3166-2 code}. This attribute
|
21 |
-
* is returned by all location databases and services except Country.
|
22 |
-
* @property-read string|null $name The name of the subdivision based on the
|
23 |
-
* locales list passed to the constructor. This attribute is returned by all
|
24 |
-
* location databases and services besides Country.
|
25 |
-
* @property-read array|null $names An array map where the keys are locale codes
|
26 |
-
* and the values are names. This attribute is returned by all location
|
27 |
-
* databases and services besides Country.
|
28 |
-
*/
|
29 |
-
class Subdivision extends AbstractPlaceRecord
|
30 |
-
{
|
31 |
-
/**
|
32 |
-
* @ignore
|
33 |
-
*/
|
34 |
-
protected $validAttributes = [
|
35 |
-
'confidence',
|
36 |
-
'geonameId',
|
37 |
-
'isoCode',
|
38 |
-
'names',
|
39 |
-
];
|
40 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data for the subdivisions associated with an IP address.
|
7 |
+
*
|
8 |
+
* This record is returned by all location databases and services besides
|
9 |
+
* Country.
|
10 |
+
*
|
11 |
+
* @property-read int|null $confidence This is a value from 0-100 indicating
|
12 |
+
* MaxMind's confidence that the subdivision is correct. This attribute is
|
13 |
+
* only available from the Insights service and the GeoIP2 Enterprise
|
14 |
+
* database.
|
15 |
+
* @property-read int|null $geonameId This is a GeoName ID for the subdivision.
|
16 |
+
* This attribute is returned by all location databases and services besides
|
17 |
+
* Country.
|
18 |
+
* @property-read string|null $isoCode This is a string up to three characters long
|
19 |
+
* contain the subdivision portion of the
|
20 |
+
* {@link * http://en.wikipedia.org/wiki/ISO_3166-2 ISO 3166-2 code}. This attribute
|
21 |
+
* is returned by all location databases and services except Country.
|
22 |
+
* @property-read string|null $name The name of the subdivision based on the
|
23 |
+
* locales list passed to the constructor. This attribute is returned by all
|
24 |
+
* location databases and services besides Country.
|
25 |
+
* @property-read array|null $names An array map where the keys are locale codes
|
26 |
+
* and the values are names. This attribute is returned by all location
|
27 |
+
* databases and services besides Country.
|
28 |
+
*/
|
29 |
+
class Subdivision extends AbstractPlaceRecord
|
30 |
+
{
|
31 |
+
/**
|
32 |
+
* @ignore
|
33 |
+
*/
|
34 |
+
protected $validAttributes = [
|
35 |
+
'confidence',
|
36 |
+
'geonameId',
|
37 |
+
'isoCode',
|
38 |
+
'names',
|
39 |
+
];
|
40 |
+
}
|
includes/vendor/geoip2/geoip2/src/Record/Traits.php
CHANGED
@@ -1,114 +1,114 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\Record;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Contains data for the traits record associated with an IP address.
|
7 |
-
*
|
8 |
-
* This record is returned by all location services and databases.
|
9 |
-
*
|
10 |
-
* @property-read int|null $autonomousSystemNumber The
|
11 |
-
* {@link * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
|
12 |
-
* system number} associated with the IP address. This attribute is only
|
13 |
-
* available from the City and Insights web service and the GeoIP2
|
14 |
-
* Enterprise database.
|
15 |
-
* @property-read string|null $autonomousSystemOrganization The organization
|
16 |
-
* associated with the registered {@link * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
|
17 |
-
* system number} for the IP address. This attribute is only available from
|
18 |
-
* the City and Insights web service and the GeoIP2 Enterprise
|
19 |
-
* database.
|
20 |
-
* @property-read string|null $connectionType The connection type may take the
|
21 |
-
* following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
|
22 |
-
* Additional values may be added in the future. This attribute is only
|
23 |
-
* available in the GeoIP2 Enterprise database.
|
24 |
-
* @property-read string|null $domain The second level domain associated with the
|
25 |
-
* IP address. This will be something like "example.com" or "example.co.uk",
|
26 |
-
* not "foo.example.com". This attribute is only available from the
|
27 |
-
* City and Insights web service and the GeoIP2 Enterprise
|
28 |
-
* database.
|
29 |
-
* @property-read string $ipAddress The IP address that the data in the model
|
30 |
-
* is for. If you performed a "me" lookup against the web service, this
|
31 |
-
* will be the externally routable IP address for the system the code is
|
32 |
-
* running on. If the system is behind a NAT, this may differ from the IP
|
33 |
-
* address locally assigned to it. This attribute is returned by all end
|
34 |
-
* points.
|
35 |
-
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
36 |
-
* any sort of anonymous network. This property is only available from GeoIP2
|
37 |
-
* Precision Insights.
|
38 |
-
* @property-read bool $isAnonymousProxy *Deprecated.* Please see our
|
39 |
-
* {@link * https://www.maxmind.com/en/geoip2-anonymous-ip-database GeoIP2
|
40 |
-
* Anonymous IP database} to determine whether the IP address is used by an
|
41 |
-
* anonymizing service.
|
42 |
-
* @property-read bool $isAnonymousVpn This is true if the IP address belongs to
|
43 |
-
* an anonymous VPN system. This property is only available from GeoIP2
|
44 |
-
* Precision Insights.
|
45 |
-
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
46 |
-
* to a hosting provider. This property is only available from GeoIP2
|
47 |
-
* Precision Insights.
|
48 |
-
* @property-read bool $isLegitimateProxy This attribute is true if MaxMind
|
49 |
-
* believes this IP address to be a legitimate proxy, such as an internal
|
50 |
-
* VPN used by a corporation. This attribute is only available in the GeoIP2
|
51 |
-
* Enterprise database.
|
52 |
-
* @property-read bool $isPublicProxy This is true if the IP address belongs to
|
53 |
-
* a public proxy. This property is only available from GeoIP2 Precision
|
54 |
-
* Insights.
|
55 |
-
* @property-read bool $isSatelliteProvider *Deprecated.* Due to the
|
56 |
-
* increased coverage by mobile carriers, very few satellite providers now
|
57 |
-
* serve multiple countries. As a result, the output does not provide
|
58 |
-
* sufficiently relevant data for us to maintain it.
|
59 |
-
* @property-read bool $isTorExitNode This is true if the IP address is a Tor
|
60 |
-
* exit node. This property is only available from GeoIP2 Precision Insights.
|
61 |
-
* @property-read string|null $isp The name of the ISP associated with the IP
|
62 |
-
* address. This attribute is only available from the City and Insights web
|
63 |
-
* services and the GeoIP2 Enterprise database.
|
64 |
-
* @property-read string|null $organization The name of the organization associated
|
65 |
-
* with the IP address. This attribute is only available from the City and
|
66 |
-
* Insights web services and the GeoIP2 Enterprise database.
|
67 |
-
* @property-read string|null $userType <p>The user type associated with the IP
|
68 |
-
* address. This can be one of the following values:</p>
|
69 |
-
* <ul>
|
70 |
-
* <li>business
|
71 |
-
* <li>cafe
|
72 |
-
* <li>cellular
|
73 |
-
* <li>college
|
74 |
-
* <li>content_delivery_network
|
75 |
-
* <li>dialup
|
76 |
-
* <li>government
|
77 |
-
* <li>hosting
|
78 |
-
* <li>library
|
79 |
-
* <li>military
|
80 |
-
* <li>residential
|
81 |
-
* <li>router
|
82 |
-
* <li>school
|
83 |
-
* <li>search_engine_spider
|
84 |
-
* <li>traveler
|
85 |
-
* </ul>
|
86 |
-
* <p>
|
87 |
-
* This attribute is only available from the Insights web service and the
|
88 |
-
* GeoIP2 Enterprise database.
|
89 |
-
* </p>
|
90 |
-
*/
|
91 |
-
class Traits extends AbstractRecord
|
92 |
-
{
|
93 |
-
/**
|
94 |
-
* @ignore
|
95 |
-
*/
|
96 |
-
protected $validAttributes = [
|
97 |
-
'autonomousSystemNumber',
|
98 |
-
'autonomousSystemOrganization',
|
99 |
-
'connectionType',
|
100 |
-
'domain',
|
101 |
-
'ipAddress',
|
102 |
-
'isAnonymous',
|
103 |
-
'isAnonymousProxy',
|
104 |
-
'isAnonymousVpn',
|
105 |
-
'isHostingProvider',
|
106 |
-
'isLegitimateProxy',
|
107 |
-
'isp',
|
108 |
-
'isPublicProxy',
|
109 |
-
'isSatelliteProvider',
|
110 |
-
'isTorExitNode',
|
111 |
-
'organization',
|
112 |
-
'userType',
|
113 |
-
];
|
114 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\Record;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains data for the traits record associated with an IP address.
|
7 |
+
*
|
8 |
+
* This record is returned by all location services and databases.
|
9 |
+
*
|
10 |
+
* @property-read int|null $autonomousSystemNumber The
|
11 |
+
* {@link * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
|
12 |
+
* system number} associated with the IP address. This attribute is only
|
13 |
+
* available from the City and Insights web service and the GeoIP2
|
14 |
+
* Enterprise database.
|
15 |
+
* @property-read string|null $autonomousSystemOrganization The organization
|
16 |
+
* associated with the registered {@link * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
|
17 |
+
* system number} for the IP address. This attribute is only available from
|
18 |
+
* the City and Insights web service and the GeoIP2 Enterprise
|
19 |
+
* database.
|
20 |
+
* @property-read string|null $connectionType The connection type may take the
|
21 |
+
* following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
|
22 |
+
* Additional values may be added in the future. This attribute is only
|
23 |
+
* available in the GeoIP2 Enterprise database.
|
24 |
+
* @property-read string|null $domain The second level domain associated with the
|
25 |
+
* IP address. This will be something like "example.com" or "example.co.uk",
|
26 |
+
* not "foo.example.com". This attribute is only available from the
|
27 |
+
* City and Insights web service and the GeoIP2 Enterprise
|
28 |
+
* database.
|
29 |
+
* @property-read string $ipAddress The IP address that the data in the model
|
30 |
+
* is for. If you performed a "me" lookup against the web service, this
|
31 |
+
* will be the externally routable IP address for the system the code is
|
32 |
+
* running on. If the system is behind a NAT, this may differ from the IP
|
33 |
+
* address locally assigned to it. This attribute is returned by all end
|
34 |
+
* points.
|
35 |
+
* @property-read bool $isAnonymous This is true if the IP address belongs to
|
36 |
+
* any sort of anonymous network. This property is only available from GeoIP2
|
37 |
+
* Precision Insights.
|
38 |
+
* @property-read bool $isAnonymousProxy *Deprecated.* Please see our
|
39 |
+
* {@link * https://www.maxmind.com/en/geoip2-anonymous-ip-database GeoIP2
|
40 |
+
* Anonymous IP database} to determine whether the IP address is used by an
|
41 |
+
* anonymizing service.
|
42 |
+
* @property-read bool $isAnonymousVpn This is true if the IP address belongs to
|
43 |
+
* an anonymous VPN system. This property is only available from GeoIP2
|
44 |
+
* Precision Insights.
|
45 |
+
* @property-read bool $isHostingProvider This is true if the IP address belongs
|
46 |
+
* to a hosting provider. This property is only available from GeoIP2
|
47 |
+
* Precision Insights.
|
48 |
+
* @property-read bool $isLegitimateProxy This attribute is true if MaxMind
|
49 |
+
* believes this IP address to be a legitimate proxy, such as an internal
|
50 |
+
* VPN used by a corporation. This attribute is only available in the GeoIP2
|
51 |
+
* Enterprise database.
|
52 |
+
* @property-read bool $isPublicProxy This is true if the IP address belongs to
|
53 |
+
* a public proxy. This property is only available from GeoIP2 Precision
|
54 |
+
* Insights.
|
55 |
+
* @property-read bool $isSatelliteProvider *Deprecated.* Due to the
|
56 |
+
* increased coverage by mobile carriers, very few satellite providers now
|
57 |
+
* serve multiple countries. As a result, the output does not provide
|
58 |
+
* sufficiently relevant data for us to maintain it.
|
59 |
+
* @property-read bool $isTorExitNode This is true if the IP address is a Tor
|
60 |
+
* exit node. This property is only available from GeoIP2 Precision Insights.
|
61 |
+
* @property-read string|null $isp The name of the ISP associated with the IP
|
62 |
+
* address. This attribute is only available from the City and Insights web
|
63 |
+
* services and the GeoIP2 Enterprise database.
|
64 |
+
* @property-read string|null $organization The name of the organization associated
|
65 |
+
* with the IP address. This attribute is only available from the City and
|
66 |
+
* Insights web services and the GeoIP2 Enterprise database.
|
67 |
+
* @property-read string|null $userType <p>The user type associated with the IP
|
68 |
+
* address. This can be one of the following values:</p>
|
69 |
+
* <ul>
|
70 |
+
* <li>business
|
71 |
+
* <li>cafe
|
72 |
+
* <li>cellular
|
73 |
+
* <li>college
|
74 |
+
* <li>content_delivery_network
|
75 |
+
* <li>dialup
|
76 |
+
* <li>government
|
77 |
+
* <li>hosting
|
78 |
+
* <li>library
|
79 |
+
* <li>military
|
80 |
+
* <li>residential
|
81 |
+
* <li>router
|
82 |
+
* <li>school
|
83 |
+
* <li>search_engine_spider
|
84 |
+
* <li>traveler
|
85 |
+
* </ul>
|
86 |
+
* <p>
|
87 |
+
* This attribute is only available from the Insights web service and the
|
88 |
+
* GeoIP2 Enterprise database.
|
89 |
+
* </p>
|
90 |
+
*/
|
91 |
+
class Traits extends AbstractRecord
|
92 |
+
{
|
93 |
+
/**
|
94 |
+
* @ignore
|
95 |
+
*/
|
96 |
+
protected $validAttributes = [
|
97 |
+
'autonomousSystemNumber',
|
98 |
+
'autonomousSystemOrganization',
|
99 |
+
'connectionType',
|
100 |
+
'domain',
|
101 |
+
'ipAddress',
|
102 |
+
'isAnonymous',
|
103 |
+
'isAnonymousProxy',
|
104 |
+
'isAnonymousVpn',
|
105 |
+
'isHostingProvider',
|
106 |
+
'isLegitimateProxy',
|
107 |
+
'isp',
|
108 |
+
'isPublicProxy',
|
109 |
+
'isSatelliteProvider',
|
110 |
+
'isTorExitNode',
|
111 |
+
'organization',
|
112 |
+
'userType',
|
113 |
+
];
|
114 |
+
}
|
includes/vendor/geoip2/geoip2/src/WebService/Client.php
CHANGED
@@ -1,239 +1,239 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace GeoIp2\WebService;
|
4 |
-
|
5 |
-
use GeoIp2\Exception\AddressNotFoundException;
|
6 |
-
use GeoIp2\Exception\AuthenticationException;
|
7 |
-
use GeoIp2\Exception\GeoIp2Exception;
|
8 |
-
use GeoIp2\Exception\HttpException;
|
9 |
-
use GeoIp2\Exception\InvalidRequestException;
|
10 |
-
use GeoIp2\Exception\OutOfQueriesException;
|
11 |
-
use GeoIp2\ProviderInterface;
|
12 |
-
use MaxMind\WebService\Client as WsClient;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* This class provides a client API for all the GeoIP2 Precision web services.
|
16 |
-
* The services are Country, City, and Insights. Each service returns a
|
17 |
-
* different set of data about an IP address, with Country returning the
|
18 |
-
* least data and Insights the most.
|
19 |
-
*
|
20 |
-
* Each web service is represented by a different model class, and these model
|
21 |
-
* classes in turn contain multiple record classes. The record classes have
|
22 |
-
* attributes which contain data about the IP address.
|
23 |
-
*
|
24 |
-
* If the web service does not return a particular piece of data for an IP
|
25 |
-
* address, the associated attribute is not populated.
|
26 |
-
*
|
27 |
-
* The web service may not return any information for an entire record, in
|
28 |
-
* which case all of the attributes for that record class will be empty.
|
29 |
-
*
|
30 |
-
* ## Usage ##
|
31 |
-
*
|
32 |
-
* The basic API for this class is the same for all of the web service end
|
33 |
-
* points. First you create a web service object with your MaxMind `$accountId`
|
34 |
-
* and `$licenseKey`, then you call the method corresponding to a specific end
|
35 |
-
* point, passing it the IP address you want to look up.
|
36 |
-
*
|
37 |
-
* If the request succeeds, the method call will return a model class for
|
38 |
-
* the service you called. This model in turn contains multiple record
|
39 |
-
* classes, each of which represents part of the data returned by the web
|
40 |
-
* service.
|
41 |
-
*
|
42 |
-
* If the request fails, the client class throws an exception.
|
43 |
-
*/
|
44 |
-
class Client implements ProviderInterface
|
45 |
-
{
|
46 |
-
private $locales;
|
47 |
-
private $client;
|
48 |
-
private static $basePath = '/geoip/v2.1';
|
49 |
-
|
50 |
-
const VERSION = 'v2.9.0';
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Constructor.
|
54 |
-
*
|
55 |
-
* @param int $accountId your MaxMind account ID
|
56 |
-
* @param string $licenseKey your MaxMind license key
|
57 |
-
* @param array $locales list of locale codes to use in name property
|
58 |
-
* from most preferred to least preferred
|
59 |
-
* @param array $options array of options. Valid options include:
|
60 |
-
* * `host` - The host to use when querying the web service.
|
61 |
-
* * `timeout` - Timeout in seconds.
|
62 |
-
* * `connectTimeout` - Initial connection timeout in seconds.
|
63 |
-
* * `proxy` - The HTTP proxy to use. May include a schema, port,
|
64 |
-
* username, and password, e.g.,
|
65 |
-
* `http://username:password@127.0.0.1:10`.
|
66 |
-
*/
|
67 |
-
public function __construct(
|
68 |
-
$accountId,
|
69 |
-
$licenseKey,
|
70 |
-
$locales = ['en'],
|
71 |
-
$options = []
|
72 |
-
) {
|
73 |
-
$this->locales = $locales;
|
74 |
-
|
75 |
-
// This is for backwards compatibility. Do not remove except for a
|
76 |
-
// major version bump.
|
77 |
-
if (is_string($options)) {
|
78 |
-
$options = ['host' => $options];
|
79 |
-
}
|
80 |
-
|
81 |
-
if (!isset($options['host'])) {
|
82 |
-
$options['host'] = 'geoip.maxmind.com';
|
83 |
-
}
|
84 |
-
|
85 |
-
$options['userAgent'] = $this->userAgent();
|
86 |
-
|
87 |
-
$this->client = new WsClient($accountId, $licenseKey, $options);
|
88 |
-
}
|
89 |
-
|
90 |
-
private function userAgent()
|
91 |
-
{
|
92 |
-
return 'GeoIP2-API/' . self::VERSION;
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* This method calls the GeoIP2 Precision: City service.
|
97 |
-
*
|
98 |
-
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
99 |
-
* address is provided, the address that the web service is called
|
100 |
-
* from will be used.
|
101 |
-
*
|
102 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
|
103 |
-
* provided is not in our database (e.g., a private address).
|
104 |
-
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
105 |
-
* with the account ID or license key that you provided
|
106 |
-
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
|
107 |
-
* of queries
|
108 |
-
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
109 |
-
* invalid for some other reason. This may indicate an issue
|
110 |
-
* with this API. Please report the error to MaxMind.
|
111 |
-
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
|
112 |
-
* This could indicate a problem with the connection between
|
113 |
-
* your server and the web service or that the web service
|
114 |
-
* returned an invalid document or 500 error code.
|
115 |
-
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
|
116 |
-
* class to the above exceptions. It will be thrown directly
|
117 |
-
* if a 200 status code is returned but the body is invalid.
|
118 |
-
*
|
119 |
-
* @return \GeoIp2\Model\City
|
120 |
-
*/
|
121 |
-
public function city($ipAddress = 'me')
|
122 |
-
{
|
123 |
-
return $this->responseFor('city', 'City', $ipAddress);
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* This method calls the GeoIP2 Precision: Country service.
|
128 |
-
*
|
129 |
-
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
130 |
-
* address is provided, the address that the web service is called
|
131 |
-
* from will be used.
|
132 |
-
*
|
133 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g.,
|
134 |
-
* a private address).
|
135 |
-
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
136 |
-
* with the account ID or license key that you provided
|
137 |
-
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out of queries
|
138 |
-
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
139 |
-
* invalid for some other reason. This may indicate an
|
140 |
-
* issue with this API. Please report the error to MaxMind.
|
141 |
-
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error
|
142 |
-
* code or message was returned. This could indicate a problem
|
143 |
-
* with the connection between your server and the web service
|
144 |
-
* or that the web service returned an invalid document or 500
|
145 |
-
* error code.
|
146 |
-
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent class to the above exceptions. It
|
147 |
-
* will be thrown directly if a 200 status code is returned but
|
148 |
-
* the body is invalid.
|
149 |
-
*
|
150 |
-
* @return \GeoIp2\Model\Country
|
151 |
-
*/
|
152 |
-
public function country($ipAddress = 'me')
|
153 |
-
{
|
154 |
-
return $this->responseFor('country', 'Country', $ipAddress);
|
155 |
-
}
|
156 |
-
|
157 |
-
/**
|
158 |
-
* This method calls the GeoIP2 Precision: Insights service.
|
159 |
-
*
|
160 |
-
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
161 |
-
* address is provided, the address that the web service is called
|
162 |
-
* from will be used.
|
163 |
-
*
|
164 |
-
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
|
165 |
-
* provided is not in our database (e.g., a private address).
|
166 |
-
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
167 |
-
* with the account ID or license key that you provided
|
168 |
-
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
|
169 |
-
* of queries
|
170 |
-
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
171 |
-
* invalid for some other reason. This may indicate an
|
172 |
-
* issue with this API. Please report the error to MaxMind.
|
173 |
-
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
|
174 |
-
* This could indicate a problem with the connection between
|
175 |
-
* your server and the web service or that the web service
|
176 |
-
* returned an invalid document or 500 error code.
|
177 |
-
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
|
178 |
-
* class to the above exceptions. It will be thrown directly
|
179 |
-
* if a 200 status code is returned but the body is invalid.
|
180 |
-
*
|
181 |
-
* @return \GeoIp2\Model\Insights
|
182 |
-
*/
|
183 |
-
public function insights($ipAddress = 'me')
|
184 |
-
{
|
185 |
-
return $this->responseFor('insights', 'Insights', $ipAddress);
|
186 |
-
}
|
187 |
-
|
188 |
-
private function responseFor($endpoint, $class, $ipAddress)
|
189 |
-
{
|
190 |
-
$path = implode('/', [self::$basePath, $endpoint, $ipAddress]);
|
191 |
-
|
192 |
-
try {
|
193 |
-
$body = $this->client->get('GeoIP2 ' . $class, $path);
|
194 |
-
} catch (\MaxMind\Exception\IpAddressNotFoundException $ex) {
|
195 |
-
throw new AddressNotFoundException(
|
196 |
-
$ex->getMessage(),
|
197 |
-
$ex->getStatusCode(),
|
198 |
-
$ex
|
199 |
-
);
|
200 |
-
} catch (\MaxMind\Exception\AuthenticationException $ex) {
|
201 |
-
throw new AuthenticationException(
|
202 |
-
$ex->getMessage(),
|
203 |
-
$ex->getStatusCode(),
|
204 |
-
$ex
|
205 |
-
);
|
206 |
-
} catch (\MaxMind\Exception\InsufficientFundsException $ex) {
|
207 |
-
throw new OutOfQueriesException(
|
208 |
-
$ex->getMessage(),
|
209 |
-
$ex->getStatusCode(),
|
210 |
-
$ex
|
211 |
-
);
|
212 |
-
} catch (\MaxMind\Exception\InvalidRequestException $ex) {
|
213 |
-
throw new InvalidRequestException(
|
214 |
-
$ex->getMessage(),
|
215 |
-
$ex->getErrorCode(),
|
216 |
-
$ex->getStatusCode(),
|
217 |
-
$ex->getUri(),
|
218 |
-
$ex
|
219 |
-
);
|
220 |
-
} catch (\MaxMind\Exception\HttpException $ex) {
|
221 |
-
throw new HttpException(
|
222 |
-
$ex->getMessage(),
|
223 |
-
$ex->getStatusCode(),
|
224 |
-
$ex->getUri(),
|
225 |
-
$ex
|
226 |
-
);
|
227 |
-
} catch (\MaxMind\Exception\WebServiceException $ex) {
|
228 |
-
throw new GeoIp2Exception(
|
229 |
-
$ex->getMessage(),
|
230 |
-
$ex->getCode(),
|
231 |
-
$ex
|
232 |
-
);
|
233 |
-
}
|
234 |
-
|
235 |
-
$class = 'GeoIp2\\Model\\' . $class;
|
236 |
-
|
237 |
-
return new $class($body, $this->locales);
|
238 |
-
}
|
239 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace GeoIp2\WebService;
|
4 |
+
|
5 |
+
use GeoIp2\Exception\AddressNotFoundException;
|
6 |
+
use GeoIp2\Exception\AuthenticationException;
|
7 |
+
use GeoIp2\Exception\GeoIp2Exception;
|
8 |
+
use GeoIp2\Exception\HttpException;
|
9 |
+
use GeoIp2\Exception\InvalidRequestException;
|
10 |
+
use GeoIp2\Exception\OutOfQueriesException;
|
11 |
+
use GeoIp2\ProviderInterface;
|
12 |
+
use MaxMind\WebService\Client as WsClient;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* This class provides a client API for all the GeoIP2 Precision web services.
|
16 |
+
* The services are Country, City, and Insights. Each service returns a
|
17 |
+
* different set of data about an IP address, with Country returning the
|
18 |
+
* least data and Insights the most.
|
19 |
+
*
|
20 |
+
* Each web service is represented by a different model class, and these model
|
21 |
+
* classes in turn contain multiple record classes. The record classes have
|
22 |
+
* attributes which contain data about the IP address.
|
23 |
+
*
|
24 |
+
* If the web service does not return a particular piece of data for an IP
|
25 |
+
* address, the associated attribute is not populated.
|
26 |
+
*
|
27 |
+
* The web service may not return any information for an entire record, in
|
28 |
+
* which case all of the attributes for that record class will be empty.
|
29 |
+
*
|
30 |
+
* ## Usage ##
|
31 |
+
*
|
32 |
+
* The basic API for this class is the same for all of the web service end
|
33 |
+
* points. First you create a web service object with your MaxMind `$accountId`
|
34 |
+
* and `$licenseKey`, then you call the method corresponding to a specific end
|
35 |
+
* point, passing it the IP address you want to look up.
|
36 |
+
*
|
37 |
+
* If the request succeeds, the method call will return a model class for
|
38 |
+
* the service you called. This model in turn contains multiple record
|
39 |
+
* classes, each of which represents part of the data returned by the web
|
40 |
+
* service.
|
41 |
+
*
|
42 |
+
* If the request fails, the client class throws an exception.
|
43 |
+
*/
|
44 |
+
class Client implements ProviderInterface
|
45 |
+
{
|
46 |
+
private $locales;
|
47 |
+
private $client;
|
48 |
+
private static $basePath = '/geoip/v2.1';
|
49 |
+
|
50 |
+
const VERSION = 'v2.9.0';
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Constructor.
|
54 |
+
*
|
55 |
+
* @param int $accountId your MaxMind account ID
|
56 |
+
* @param string $licenseKey your MaxMind license key
|
57 |
+
* @param array $locales list of locale codes to use in name property
|
58 |
+
* from most preferred to least preferred
|
59 |
+
* @param array $options array of options. Valid options include:
|
60 |
+
* * `host` - The host to use when querying the web service.
|
61 |
+
* * `timeout` - Timeout in seconds.
|
62 |
+
* * `connectTimeout` - Initial connection timeout in seconds.
|
63 |
+
* * `proxy` - The HTTP proxy to use. May include a schema, port,
|
64 |
+
* username, and password, e.g.,
|
65 |
+
* `http://username:password@127.0.0.1:10`.
|
66 |
+
*/
|
67 |
+
public function __construct(
|
68 |
+
$accountId,
|
69 |
+
$licenseKey,
|
70 |
+
$locales = ['en'],
|
71 |
+
$options = []
|
72 |
+
) {
|
73 |
+
$this->locales = $locales;
|
74 |
+
|
75 |
+
// This is for backwards compatibility. Do not remove except for a
|
76 |
+
// major version bump.
|
77 |
+
if (is_string($options)) {
|
78 |
+
$options = ['host' => $options];
|
79 |
+
}
|
80 |
+
|
81 |
+
if (!isset($options['host'])) {
|
82 |
+
$options['host'] = 'geoip.maxmind.com';
|
83 |
+
}
|
84 |
+
|
85 |
+
$options['userAgent'] = $this->userAgent();
|
86 |
+
|
87 |
+
$this->client = new WsClient($accountId, $licenseKey, $options);
|
88 |
+
}
|
89 |
+
|
90 |
+
private function userAgent()
|
91 |
+
{
|
92 |
+
return 'GeoIP2-API/' . self::VERSION;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* This method calls the GeoIP2 Precision: City service.
|
97 |
+
*
|
98 |
+
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
99 |
+
* address is provided, the address that the web service is called
|
100 |
+
* from will be used.
|
101 |
+
*
|
102 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
|
103 |
+
* provided is not in our database (e.g., a private address).
|
104 |
+
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
105 |
+
* with the account ID or license key that you provided
|
106 |
+
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
|
107 |
+
* of queries
|
108 |
+
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
109 |
+
* invalid for some other reason. This may indicate an issue
|
110 |
+
* with this API. Please report the error to MaxMind.
|
111 |
+
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
|
112 |
+
* This could indicate a problem with the connection between
|
113 |
+
* your server and the web service or that the web service
|
114 |
+
* returned an invalid document or 500 error code.
|
115 |
+
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
|
116 |
+
* class to the above exceptions. It will be thrown directly
|
117 |
+
* if a 200 status code is returned but the body is invalid.
|
118 |
+
*
|
119 |
+
* @return \GeoIp2\Model\City
|
120 |
+
*/
|
121 |
+
public function city($ipAddress = 'me')
|
122 |
+
{
|
123 |
+
return $this->responseFor('city', 'City', $ipAddress);
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* This method calls the GeoIP2 Precision: Country service.
|
128 |
+
*
|
129 |
+
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
130 |
+
* address is provided, the address that the web service is called
|
131 |
+
* from will be used.
|
132 |
+
*
|
133 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g.,
|
134 |
+
* a private address).
|
135 |
+
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
136 |
+
* with the account ID or license key that you provided
|
137 |
+
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out of queries
|
138 |
+
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
139 |
+
* invalid for some other reason. This may indicate an
|
140 |
+
* issue with this API. Please report the error to MaxMind.
|
141 |
+
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error
|
142 |
+
* code or message was returned. This could indicate a problem
|
143 |
+
* with the connection between your server and the web service
|
144 |
+
* or that the web service returned an invalid document or 500
|
145 |
+
* error code.
|
146 |
+
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent class to the above exceptions. It
|
147 |
+
* will be thrown directly if a 200 status code is returned but
|
148 |
+
* the body is invalid.
|
149 |
+
*
|
150 |
+
* @return \GeoIp2\Model\Country
|
151 |
+
*/
|
152 |
+
public function country($ipAddress = 'me')
|
153 |
+
{
|
154 |
+
return $this->responseFor('country', 'Country', $ipAddress);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* This method calls the GeoIP2 Precision: Insights service.
|
159 |
+
*
|
160 |
+
* @param string $ipAddress IPv4 or IPv6 address as a string. If no
|
161 |
+
* address is provided, the address that the web service is called
|
162 |
+
* from will be used.
|
163 |
+
*
|
164 |
+
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
|
165 |
+
* provided is not in our database (e.g., a private address).
|
166 |
+
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
|
167 |
+
* with the account ID or license key that you provided
|
168 |
+
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
|
169 |
+
* of queries
|
170 |
+
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
|
171 |
+
* invalid for some other reason. This may indicate an
|
172 |
+
* issue with this API. Please report the error to MaxMind.
|
173 |
+
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
|
174 |
+
* This could indicate a problem with the connection between
|
175 |
+
* your server and the web service or that the web service
|
176 |
+
* returned an invalid document or 500 error code.
|
177 |
+
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
|
178 |
+
* class to the above exceptions. It will be thrown directly
|
179 |
+
* if a 200 status code is returned but the body is invalid.
|
180 |
+
*
|
181 |
+
* @return \GeoIp2\Model\Insights
|
182 |
+
*/
|
183 |
+
public function insights($ipAddress = 'me')
|
184 |
+
{
|
185 |
+
return $this->responseFor('insights', 'Insights', $ipAddress);
|
186 |
+
}
|
187 |
+
|
188 |
+
private function responseFor($endpoint, $class, $ipAddress)
|
189 |
+
{
|
190 |
+
$path = implode('/', [self::$basePath, $endpoint, $ipAddress]);
|
191 |
+
|
192 |
+
try {
|
193 |
+
$body = $this->client->get('GeoIP2 ' . $class, $path);
|
194 |
+
} catch (\MaxMind\Exception\IpAddressNotFoundException $ex) {
|
195 |
+
throw new AddressNotFoundException(
|
196 |
+
$ex->getMessage(),
|
197 |
+
$ex->getStatusCode(),
|
198 |
+
$ex
|
199 |
+
);
|
200 |
+
} catch (\MaxMind\Exception\AuthenticationException $ex) {
|
201 |
+
throw new AuthenticationException(
|
202 |
+
$ex->getMessage(),
|
203 |
+
$ex->getStatusCode(),
|
204 |
+
$ex
|
205 |
+
);
|
206 |
+
} catch (\MaxMind\Exception\InsufficientFundsException $ex) {
|
207 |
+
throw new OutOfQueriesException(
|
208 |
+
$ex->getMessage(),
|
209 |
+
$ex->getStatusCode(),
|
210 |
+
$ex
|
211 |
+
);
|
212 |
+
} catch (\MaxMind\Exception\InvalidRequestException $ex) {
|
213 |
+
throw new InvalidRequestException(
|
214 |
+
$ex->getMessage(),
|
215 |
+
$ex->getErrorCode(),
|
216 |
+
$ex->getStatusCode(),
|
217 |
+
$ex->getUri(),
|
218 |
+
$ex
|
219 |
+
);
|
220 |
+
} catch (\MaxMind\Exception\HttpException $ex) {
|
221 |
+
throw new HttpException(
|
222 |
+
$ex->getMessage(),
|
223 |
+
$ex->getStatusCode(),
|
224 |
+
$ex->getUri(),
|
225 |
+
$ex
|
226 |
+
);
|
227 |
+
} catch (\MaxMind\Exception\WebServiceException $ex) {
|
228 |
+
throw new GeoIp2Exception(
|
229 |
+
$ex->getMessage(),
|
230 |
+
$ex->getCode(),
|
231 |
+
$ex
|
232 |
+
);
|
233 |
+
}
|
234 |
+
|
235 |
+
$class = 'GeoIp2\\Model\\' . $class;
|
236 |
+
|
237 |
+
return new $class($body, $this->locales);
|
238 |
+
}
|
239 |
+
}
|
includes/vendor/maxmind-db/reader/CHANGELOG.md
CHANGED
@@ -1,121 +1,121 @@
|
|
1 |
-
CHANGELOG
|
2 |
-
=========
|
3 |
-
|
4 |
-
1.3.0 (2018-02-21)
|
5 |
-
------------------
|
6 |
-
|
7 |
-
* IMPORTANT: The `maxminddb` extension now obeys `open_basedir`. If
|
8 |
-
`open_basedir` is set, you _must_ store the database within the
|
9 |
-
specified directory. Placing the file outside of this directory
|
10 |
-
will result in an exception. Please test your integration before
|
11 |
-
upgrading the extension. This does not affect the pure PHP
|
12 |
-
implementation, which has always had this restriction. Reported
|
13 |
-
by Benoît Burnichon. GitHub #61.
|
14 |
-
* A custom `autoload.php` file is provided for installations without
|
15 |
-
Composer. GitHub #56.
|
16 |
-
|
17 |
-
1.2.0 (2017-10-27)
|
18 |
-
------------------
|
19 |
-
|
20 |
-
* PHP 5.4 or greater is now required.
|
21 |
-
* The `Reader` class for the `maxminddb` extension is no longer final.
|
22 |
-
This was change to match the behavior of the pure PHP class.
|
23 |
-
Reported and fixed by venyii. GitHub #52 & #54.
|
24 |
-
|
25 |
-
1.1.3 (2017-01-19)
|
26 |
-
------------------
|
27 |
-
|
28 |
-
* Fix incorrect version in `ext/php_maxminddb.h`. GitHub #48.
|
29 |
-
|
30 |
-
1.1.2 (2016-11-22)
|
31 |
-
------------------
|
32 |
-
|
33 |
-
* Searching for database metadata only occurs within the last 128KB
|
34 |
-
(128 * 1024 bytes) of the file, speeding detection of corrupt
|
35 |
-
datafiles. Reported by Eric Teubert. GitHub #42.
|
36 |
-
* Suggest relevant extensions when installing with Composer. GitHub #37.
|
37 |
-
|
38 |
-
1.1.1 (2016-09-15)
|
39 |
-
------------------
|
40 |
-
|
41 |
-
* Development files were added to the `.gitattributes` as `export-ignore` so
|
42 |
-
that they are not part of the Composer release. Pull request by Michele
|
43 |
-
Locati. GitHub #39.
|
44 |
-
|
45 |
-
1.1.0 (2016-01-04)
|
46 |
-
------------------
|
47 |
-
|
48 |
-
* The MaxMind DB extension now supports PHP 7. Pull request by John Boehr.
|
49 |
-
GitHub #27.
|
50 |
-
|
51 |
-
1.0.3 (2015-03-13)
|
52 |
-
------------------
|
53 |
-
|
54 |
-
* All uses of `strlen` were removed. This should prevent issues in situations
|
55 |
-
where the function is overloaded or otherwise broken.
|
56 |
-
|
57 |
-
1.0.2 (2015-01-19)
|
58 |
-
------------------
|
59 |
-
|
60 |
-
* Previously the MaxMind DB extension would cause a segfault if the Reader
|
61 |
-
object's destructor was called without first having called the constructor.
|
62 |
-
(Reported by Matthias Saou & Juan Peri. GitHub #20.)
|
63 |
-
|
64 |
-
1.0.1 (2015-01-12)
|
65 |
-
------------------
|
66 |
-
|
67 |
-
* In the last several releases, the version number in the extension was
|
68 |
-
incorrect. This release is being done to correct it. No other code changes
|
69 |
-
are included.
|
70 |
-
|
71 |
-
1.0.0 (2014-09-22)
|
72 |
-
------------------
|
73 |
-
|
74 |
-
* First production release.
|
75 |
-
* In the pure PHP reader, a string length test after `fread()` was replaced
|
76 |
-
with the difference between the start pointer and the end pointer. This
|
77 |
-
provided a 15% speed increase.
|
78 |
-
|
79 |
-
0.3.3 (2014-09-15)
|
80 |
-
------------------
|
81 |
-
|
82 |
-
* Clarified behavior of 128-bit type in documentation.
|
83 |
-
* Updated phpunit and fixed some test breakage from the newer version.
|
84 |
-
|
85 |
-
0.3.2 (2014-09-10)
|
86 |
-
------------------
|
87 |
-
|
88 |
-
* Fixed invalid reference to global class RuntimeException from namespaced
|
89 |
-
code. Fixed by Steven Don. GitHub issue #15.
|
90 |
-
* Additional documentation of `Metadata` class as well as misc. documentation
|
91 |
-
cleanup.
|
92 |
-
|
93 |
-
0.3.1 (2014-05-01)
|
94 |
-
------------------
|
95 |
-
|
96 |
-
* The API now works when `mbstring.func_overload` is set.
|
97 |
-
* BCMath is no longer required. If the decoder encounters a big integer,
|
98 |
-
it will try to use GMP and then BCMath. If both of those fail, it will
|
99 |
-
throw an exception. No databases released by MaxMind currently use big
|
100 |
-
integers.
|
101 |
-
* The API now officially supports HHVM when using the pure PHP reader.
|
102 |
-
|
103 |
-
0.3.0 (2014-02-19)
|
104 |
-
------------------
|
105 |
-
|
106 |
-
* This API is now licensed under the Apache License, Version 2.0.
|
107 |
-
* The code for the C extension was cleaned up, fixing several potential
|
108 |
-
issues.
|
109 |
-
|
110 |
-
0.2.0 (2013-10-21)
|
111 |
-
------------------
|
112 |
-
|
113 |
-
* Added optional C extension for using libmaxminddb in place of the pure PHP
|
114 |
-
reader.
|
115 |
-
* Significantly improved error handling in pure PHP reader.
|
116 |
-
* Improved performance for IPv4 lookups in an IPv6 database.
|
117 |
-
|
118 |
-
0.1.0 (2013-07-16)
|
119 |
-
------------------
|
120 |
-
|
121 |
-
* Initial release
|
1 |
+
CHANGELOG
|
2 |
+
=========
|
3 |
+
|
4 |
+
1.3.0 (2018-02-21)
|
5 |
+
------------------
|
6 |
+
|
7 |
+
* IMPORTANT: The `maxminddb` extension now obeys `open_basedir`. If
|
8 |
+
`open_basedir` is set, you _must_ store the database within the
|
9 |
+
specified directory. Placing the file outside of this directory
|
10 |
+
will result in an exception. Please test your integration before
|
11 |
+
upgrading the extension. This does not affect the pure PHP
|
12 |
+
implementation, which has always had this restriction. Reported
|
13 |
+
by Benoît Burnichon. GitHub #61.
|
14 |
+
* A custom `autoload.php` file is provided for installations without
|
15 |
+
Composer. GitHub #56.
|
16 |
+
|
17 |
+
1.2.0 (2017-10-27)
|
18 |
+
------------------
|
19 |
+
|
20 |
+
* PHP 5.4 or greater is now required.
|
21 |
+
* The `Reader` class for the `maxminddb` extension is no longer final.
|
22 |
+
This was change to match the behavior of the pure PHP class.
|
23 |
+
Reported and fixed by venyii. GitHub #52 & #54.
|
24 |
+
|
25 |
+
1.1.3 (2017-01-19)
|
26 |
+
------------------
|
27 |
+
|
28 |
+
* Fix incorrect version in `ext/php_maxminddb.h`. GitHub #48.
|
29 |
+
|
30 |
+
1.1.2 (2016-11-22)
|
31 |
+
------------------
|
32 |
+
|
33 |
+
* Searching for database metadata only occurs within the last 128KB
|
34 |
+
(128 * 1024 bytes) of the file, speeding detection of corrupt
|
35 |
+
datafiles. Reported by Eric Teubert. GitHub #42.
|
36 |
+
* Suggest relevant extensions when installing with Composer. GitHub #37.
|
37 |
+
|
38 |
+
1.1.1 (2016-09-15)
|
39 |
+
------------------
|
40 |
+
|
41 |
+
* Development files were added to the `.gitattributes` as `export-ignore` so
|
42 |
+
that they are not part of the Composer release. Pull request by Michele
|
43 |
+
Locati. GitHub #39.
|
44 |
+
|
45 |
+
1.1.0 (2016-01-04)
|
46 |
+
------------------
|
47 |
+
|
48 |
+
* The MaxMind DB extension now supports PHP 7. Pull request by John Boehr.
|
49 |
+
GitHub #27.
|
50 |
+
|
51 |
+
1.0.3 (2015-03-13)
|
52 |
+
------------------
|
53 |
+
|
54 |
+
* All uses of `strlen` were removed. This should prevent issues in situations
|
55 |
+
where the function is overloaded or otherwise broken.
|
56 |
+
|
57 |
+
1.0.2 (2015-01-19)
|
58 |
+
------------------
|
59 |
+
|
60 |
+
* Previously the MaxMind DB extension would cause a segfault if the Reader
|
61 |
+
object's destructor was called without first having called the constructor.
|
62 |
+
(Reported by Matthias Saou & Juan Peri. GitHub #20.)
|
63 |
+
|
64 |
+
1.0.1 (2015-01-12)
|
65 |
+
------------------
|
66 |
+
|
67 |
+
* In the last several releases, the version number in the extension was
|
68 |
+
incorrect. This release is being done to correct it. No other code changes
|
69 |
+
are included.
|
70 |
+
|
71 |
+
1.0.0 (2014-09-22)
|
72 |
+
------------------
|
73 |
+
|
74 |
+
* First production release.
|
75 |
+
* In the pure PHP reader, a string length test after `fread()` was replaced
|
76 |
+
with the difference between the start pointer and the end pointer. This
|
77 |
+
provided a 15% speed increase.
|
78 |
+
|
79 |
+
0.3.3 (2014-09-15)
|
80 |
+
------------------
|
81 |
+
|
82 |
+
* Clarified behavior of 128-bit type in documentation.
|
83 |
+
* Updated phpunit and fixed some test breakage from the newer version.
|
84 |
+
|
85 |
+
0.3.2 (2014-09-10)
|
86 |
+
------------------
|
87 |
+
|
88 |
+
* Fixed invalid reference to global class RuntimeException from namespaced
|
89 |
+
code. Fixed by Steven Don. GitHub issue #15.
|
90 |
+
* Additional documentation of `Metadata` class as well as misc. documentation
|
91 |
+
cleanup.
|
92 |
+
|
93 |
+
0.3.1 (2014-05-01)
|
94 |
+
------------------
|
95 |
+
|
96 |
+
* The API now works when `mbstring.func_overload` is set.
|
97 |
+
* BCMath is no longer required. If the decoder encounters a big integer,
|
98 |
+
it will try to use GMP and then BCMath. If both of those fail, it will
|
99 |
+
throw an exception. No databases released by MaxMind currently use big
|
100 |
+
integers.
|
101 |
+
* The API now officially supports HHVM when using the pure PHP reader.
|
102 |
+
|
103 |
+
0.3.0 (2014-02-19)
|
104 |
+
------------------
|
105 |
+
|
106 |
+
* This API is now licensed under the Apache License, Version 2.0.
|
107 |
+
* The code for the C extension was cleaned up, fixing several potential
|
108 |
+
issues.
|
109 |
+
|
110 |
+
0.2.0 (2013-10-21)
|
111 |
+
------------------
|
112 |
+
|
113 |
+
* Added optional C extension for using libmaxminddb in place of the pure PHP
|
114 |
+
reader.
|
115 |
+
* Significantly improved error handling in pure PHP reader.
|
116 |
+
* Improved performance for IPv4 lookups in an IPv6 database.
|
117 |
+
|
118 |
+
0.1.0 (2013-07-16)
|
119 |
+
------------------
|
120 |
+
|
121 |
+
* Initial release
|
includes/vendor/maxmind-db/reader/LICENSE
CHANGED
@@ -1,202 +1,202 @@
|
|
1 |
-
|
2 |
-
Apache License
|
3 |
-
Version 2.0, January 2004
|
4 |
-
http://www.apache.org/licenses/
|
5 |
-
|
6 |
-
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
7 |
-
|
8 |
-
1. Definitions.
|
9 |
-
|
10 |
-
"License" shall mean the terms and conditions for use, reproduction,
|
11 |
-
and distribution as defined by Sections 1 through 9 of this document.
|
12 |
-
|
13 |
-
"Licensor" shall mean the copyright owner or entity authorized by
|
14 |
-
the copyright owner that is granting the License.
|
15 |
-
|
16 |
-
"Legal Entity" shall mean the union of the acting entity and all
|
17 |
-
other entities that control, are controlled by, or are under common
|
18 |
-
control with that entity. For the purposes of this definition,
|
19 |
-
"control" means (i) the power, direct or indirect, to cause the
|
20 |
-
direction or management of such entity, whether by contract or
|
21 |
-
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
22 |
-
outstanding shares, or (iii) beneficial ownership of such entity.
|
23 |
-
|
24 |
-
"You" (or "Your") shall mean an individual or Legal Entity
|
25 |
-
exercising permissions granted by this License.
|
26 |
-
|
27 |
-
"Source" form shall mean the preferred form for making modifications,
|
28 |
-
including but not limited to software source code, documentation
|
29 |
-
source, and configuration files.
|
30 |
-
|
31 |
-
"Object" form shall mean any form resulting from mechanical
|
32 |
-
transformation or translation of a Source form, including but
|
33 |
-
not limited to compiled object code, generated documentation,
|
34 |
-
and conversions to other media types.
|
35 |
-
|
36 |
-
"Work" shall mean the work of authorship, whether in Source or
|
37 |
-
Object form, made available under the License, as indicated by a
|
38 |
-
copyright notice that is included in or attached to the work
|
39 |
-
(an example is provided in the Appendix below).
|
40 |
-
|
41 |
-
"Derivative Works" shall mean any work, whether in Source or Object
|
42 |
-
form, that is based on (or derived from) the Work and for which the
|
43 |
-
editorial revisions, annotations, elaborations, or other modifications
|
44 |
-
represent, as a whole, an original work of authorship. For the purposes
|
45 |
-
of this License, Derivative Works shall not include works that remain
|
46 |
-
separable from, or merely link (or bind by name) to the interfaces of,
|
47 |
-
the Work and Derivative Works thereof.
|
48 |
-
|
49 |
-
"Contribution" shall mean any work of authorship, including
|
50 |
-
the original version of the Work and any modifications or additions
|
51 |
-
to that Work or Derivative Works thereof, that is intentionally
|
52 |
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
53 |
-
or by an individual or Legal Entity authorized to submit on behalf of
|
54 |
-
the copyright owner. For the purposes of this definition, "submitted"
|
55 |
-
means any form of electronic, verbal, or written communication sent
|
56 |
-
to the Licensor or its representatives, including but not limited to
|
57 |
-
communication on electronic mailing lists, source code control systems,
|
58 |
-
and issue tracking systems that are managed by, or on behalf of, the
|
59 |
-
Licensor for the purpose of discussing and improving the Work, but
|
60 |
-
excluding communication that is conspicuously marked or otherwise
|
61 |
-
designated in writing by the copyright owner as "Not a Contribution."
|
62 |
-
|
63 |
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
64 |
-
on behalf of whom a Contribution has been received by Licensor and
|
65 |
-
subsequently incorporated within the Work.
|
66 |
-
|
67 |
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
68 |
-
this License, each Contributor hereby grants to You a perpetual,
|
69 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
70 |
-
copyright license to reproduce, prepare Derivative Works of,
|
71 |
-
publicly display, publicly perform, sublicense, and distribute the
|
72 |
-
Work and such Derivative Works in Source or Object form.
|
73 |
-
|
74 |
-
3. Grant of Patent License. Subject to the terms and conditions of
|
75 |
-
this License, each Contributor hereby grants to You a perpetual,
|
76 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
77 |
-
(except as stated in this section) patent license to make, have made,
|
78 |
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
79 |
-
where such license applies only to those patent claims licensable
|
80 |
-
by such Contributor that are necessarily infringed by their
|
81 |
-
Contribution(s) alone or by combination of their Contribution(s)
|
82 |
-
with the Work to which such Contribution(s) was submitted. If You
|
83 |
-
institute patent litigation against any entity (including a
|
84 |
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
85 |
-
or a Contribution incorporated within the Work constitutes direct
|
86 |
-
or contributory patent infringement, then any patent licenses
|
87 |
-
granted to You under this License for that Work shall terminate
|
88 |
-
as of the date such litigation is filed.
|
89 |
-
|
90 |
-
4. Redistribution. You may reproduce and distribute copies of the
|
91 |
-
Work or Derivative Works thereof in any medium, with or without
|
92 |
-
modifications, and in Source or Object form, provided that You
|
93 |
-
meet the following conditions:
|
94 |
-
|
95 |
-
(a) You must give any other recipients of the Work or
|
96 |
-
Derivative Works a copy of this License; and
|
97 |
-
|
98 |
-
(b) You must cause any modified files to carry prominent notices
|
99 |
-
stating that You changed the files; and
|
100 |
-
|
101 |
-
(c) You must retain, in the Source form of any Derivative Works
|
102 |
-
that You distribute, all copyright, patent, trademark, and
|
103 |
-
attribution notices from the Source form of the Work,
|
104 |
-
excluding those notices that do not pertain to any part of
|
105 |
-
the Derivative Works; and
|
106 |
-
|
107 |
-
(d) If the Work includes a "NOTICE" text file as part of its
|
108 |
-
distribution, then any Derivative Works that You distribute must
|
109 |
-
include a readable copy of the attribution notices contained
|
110 |
-
within such NOTICE file, excluding those notices that do not
|
111 |
-
pertain to any part of the Derivative Works, in at least one
|
112 |
-
of the following places: within a NOTICE text file distributed
|
113 |
-
as part of the Derivative Works; within the Source form or
|
114 |
-
documentation, if provided along with the Derivative Works; or,
|
115 |
-
within a display generated by the Derivative Works, if and
|
116 |
-
wherever such third-party notices normally appear. The contents
|
117 |
-
of the NOTICE file are for informational purposes only and
|
118 |
-
do not modify the License. You may add Your own attribution
|
119 |
-
notices within Derivative Works that You distribute, alongside
|
120 |
-
or as an addendum to the NOTICE text from the Work, provided
|
121 |
-
that such additional attribution notices cannot be construed
|
122 |
-
as modifying the License.
|
123 |
-
|
124 |
-
You may add Your own copyright statement to Your modifications and
|
125 |
-
may provide additional or different license terms and conditions
|
126 |
-
for use, reproduction, or distribution of Your modifications, or
|
127 |
-
for any such Derivative Works as a whole, provided Your use,
|
128 |
-
reproduction, and distribution of the Work otherwise complies with
|
129 |
-
the conditions stated in this License.
|
130 |
-
|
131 |
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
132 |
-
any Contribution intentionally submitted for inclusion in the Work
|
133 |
-
by You to the Licensor shall be under the terms and conditions of
|
134 |
-
this License, without any additional terms or conditions.
|
135 |
-
Notwithstanding the above, nothing herein shall supersede or modify
|
136 |
-
the terms of any separate license agreement you may have executed
|
137 |
-
with Licensor regarding such Contributions.
|
138 |
-
|
139 |
-
6. Trademarks. This License does not grant permission to use the trade
|
140 |
-
names, trademarks, service marks, or product names of the Licensor,
|
141 |
-
except as required for reasonable and customary use in describing the
|
142 |
-
origin of the Work and reproducing the content of the NOTICE file.
|
143 |
-
|
144 |
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
145 |
-
agreed to in writing, Licensor provides the Work (and each
|
146 |
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
147 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
148 |
-
implied, including, without limitation, any warranties or conditions
|
149 |
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
150 |
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
151 |
-
appropriateness of using or redistributing the Work and assume any
|
152 |
-
risks associated with Your exercise of permissions under this License.
|
153 |
-
|
154 |
-
8. Limitation of Liability. In no event and under no legal theory,
|
155 |
-
whether in tort (including negligence), contract, or otherwise,
|
156 |
-
unless required by applicable law (such as deliberate and grossly
|
157 |
-
negligent acts) or agreed to in writing, shall any Contributor be
|
158 |
-
liable to You for damages, including any direct, indirect, special,
|
159 |
-
incidental, or consequential damages of any character arising as a
|
160 |
-
result of this License or out of the use or inability to use the
|
161 |
-
Work (including but not limited to damages for loss of goodwill,
|
162 |
-
work stoppage, computer failure or malfunction, or any and all
|
163 |
-
other commercial damages or losses), even if such Contributor
|
164 |
-
has been advised of the possibility of such damages.
|
165 |
-
|
166 |
-
9. Accepting Warranty or Additional Liability. While redistributing
|
167 |
-
the Work or Derivative Works thereof, You may choose to offer,
|
168 |
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
169 |
-
or other liability obligations and/or rights consistent with this
|
170 |
-
License. However, in accepting such obligations, You may act only
|
171 |
-
on Your own behalf and on Your sole responsibility, not on behalf
|
172 |
-
of any other Contributor, and only if You agree to indemnify,
|
173 |
-
defend, and hold each Contributor harmless for any liability
|
174 |
-
incurred by, or claims asserted against, such Contributor by reason
|
175 |
-
of your accepting any such warranty or additional liability.
|
176 |
-
|
177 |
-
END OF TERMS AND CONDITIONS
|
178 |
-
|
179 |
-
APPENDIX: How to apply the Apache License to your work.
|
180 |
-
|
181 |
-
To apply the Apache License to your work, attach the following
|
182 |
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
183 |
-
replaced with your own identifying information. (Don't include
|
184 |
-
the brackets!) The text should be enclosed in the appropriate
|
185 |
-
comment syntax for the file format. We also recommend that a
|
186 |
-
file or class name and description of purpose be included on the
|
187 |
-
same "printed page" as the copyright notice for easier
|
188 |
-
identification within third-party archives.
|
189 |
-
|
190 |
-
Copyright [yyyy] [name of copyright owner]
|
191 |
-
|
192 |
-
Licensed under the Apache License, Version 2.0 (the "License");
|
193 |
-
you may not use this file except in compliance with the License.
|
194 |
-
You may obtain a copy of the License at
|
195 |
-
|
196 |
-
http://www.apache.org/licenses/LICENSE-2.0
|
197 |
-
|
198 |
-
Unless required by applicable law or agreed to in writing, software
|
199 |
-
distributed under the License is distributed on an "AS IS" BASIS,
|
200 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
201 |
-
See the License for the specific language governing permissions and
|
202 |
-
limitations under the License.
|
1 |
+
|
2 |
+
Apache License
|
3 |
+
Version 2.0, January 2004
|
4 |
+
http://www.apache.org/licenses/
|
5 |
+
|
6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
7 |
+
|
8 |
+
1. Definitions.
|
9 |
+
|
10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
12 |
+
|
13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
14 |
+
the copyright owner that is granting the License.
|
15 |
+
|
16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
17 |
+
other entities that control, are controlled by, or are under common
|
18 |
+
control with that entity. For the purposes of this definition,
|
19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
20 |
+
direction or management of such entity, whether by contract or
|
21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
23 |
+
|
24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
25 |
+
exercising permissions granted by this License.
|
26 |
+
|
27 |
+
"Source" form shall mean the preferred form for making modifications,
|
28 |
+
including but not limited to software source code, documentation
|
29 |
+
source, and configuration files.
|
30 |
+
|
31 |
+
"Object" form shall mean any form resulting from mechanical
|
32 |
+
transformation or translation of a Source form, including but
|
33 |
+
not limited to compiled object code, generated documentation,
|
34 |
+
and conversions to other media types.
|
35 |
+
|
36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
37 |
+
Object form, made available under the License, as indicated by a
|
38 |
+
copyright notice that is included in or attached to the work
|
39 |
+
(an example is provided in the Appendix below).
|
40 |
+
|
41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
42 |
+
form, that is based on (or derived from) the Work and for which the
|
43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
45 |
+
of this License, Derivative Works shall not include works that remain
|
46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
47 |
+
the Work and Derivative Works thereof.
|
48 |
+
|
49 |
+
"Contribution" shall mean any work of authorship, including
|
50 |
+
the original version of the Work and any modifications or additions
|
51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
55 |
+
means any form of electronic, verbal, or written communication sent
|
56 |
+
to the Licensor or its representatives, including but not limited to
|
57 |
+
communication on electronic mailing lists, source code control systems,
|
58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
60 |
+
excluding communication that is conspicuously marked or otherwise
|
61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
62 |
+
|
63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
65 |
+
subsequently incorporated within the Work.
|
66 |
+
|
67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
72 |
+
Work and such Derivative Works in Source or Object form.
|
73 |
+
|
74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
77 |
+
(except as stated in this section) patent license to make, have made,
|
78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
79 |
+
where such license applies only to those patent claims licensable
|
80 |
+
by such Contributor that are necessarily infringed by their
|
81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
83 |
+
institute patent litigation against any entity (including a
|
84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
85 |
+
or a Contribution incorporated within the Work constitutes direct
|
86 |
+
or contributory patent infringement, then any patent licenses
|
87 |
+
granted to You under this License for that Work shall terminate
|
88 |
+
as of the date such litigation is filed.
|
89 |
+
|
90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
91 |
+
Work or Derivative Works thereof in any medium, with or without
|
92 |
+
modifications, and in Source or Object form, provided that You
|
93 |
+
meet the following conditions:
|
94 |
+
|
95 |
+
(a) You must give any other recipients of the Work or
|
96 |
+
Derivative Works a copy of this License; and
|
97 |
+
|
98 |
+
(b) You must cause any modified files to carry prominent notices
|
99 |
+
stating that You changed the files; and
|
100 |
+
|
101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
102 |
+
that You distribute, all copyright, patent, trademark, and
|
103 |
+
attribution notices from the Source form of the Work,
|
104 |
+
excluding those notices that do not pertain to any part of
|
105 |
+
the Derivative Works; and
|
106 |
+
|
107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
108 |
+
distribution, then any Derivative Works that You distribute must
|
109 |
+
include a readable copy of the attribution notices contained
|
110 |
+
within such NOTICE file, excluding those notices that do not
|
111 |
+
pertain to any part of the Derivative Works, in at least one
|
112 |
+
of the following places: within a NOTICE text file distributed
|
113 |
+
as part of the Derivative Works; within the Source form or
|
114 |
+
documentation, if provided along with the Derivative Works; or,
|
115 |
+
within a display generated by the Derivative Works, if and
|
116 |
+
wherever such third-party notices normally appear. The contents
|
117 |
+
of the NOTICE file are for informational purposes only and
|
118 |
+
do not modify the License. You may add Your own attribution
|
119 |
+
notices within Derivative Works that You distribute, alongside
|
120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
121 |
+
that such additional attribution notices cannot be construed
|
122 |
+
as modifying the License.
|
123 |
+
|
124 |
+
You may add Your own copyright statement to Your modifications and
|
125 |
+
may provide additional or different license terms and conditions
|
126 |
+
for use, reproduction, or distribution of Your modifications, or
|
127 |
+
for any such Derivative Works as a whole, provided Your use,
|
128 |
+
reproduction, and distribution of the Work otherwise complies with
|
129 |
+
the conditions stated in this License.
|
130 |
+
|
131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
133 |
+
by You to the Licensor shall be under the terms and conditions of
|
134 |
+
this License, without any additional terms or conditions.
|
135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
136 |
+
the terms of any separate license agreement you may have executed
|
137 |
+
with Licensor regarding such Contributions.
|
138 |
+
|
139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
141 |
+
except as required for reasonable and customary use in describing the
|
142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
143 |
+
|
144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
145 |
+
agreed to in writing, Licensor provides the Work (and each
|
146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
148 |
+
implied, including, without limitation, any warranties or conditions
|
149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
151 |
+
appropriateness of using or redistributing the Work and assume any
|
152 |
+
risks associated with Your exercise of permissions under this License.
|
153 |
+
|
154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
155 |
+
whether in tort (including negligence), contract, or otherwise,
|
156 |
+
unless required by applicable law (such as deliberate and grossly
|
157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
158 |
+
liable to You for damages, including any direct, indirect, special,
|
159 |
+
incidental, or consequential damages of any character arising as a
|
160 |
+
result of this License or out of the use or inability to use the
|
161 |
+
Work (including but not limited to damages for loss of goodwill,
|
162 |
+
work stoppage, computer failure or malfunction, or any and all
|
163 |
+
other commercial damages or losses), even if such Contributor
|
164 |
+
has been advised of the possibility of such damages.
|
165 |
+
|
166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
169 |
+
or other liability obligations and/or rights consistent with this
|
170 |
+
License. However, in accepting such obligations, You may act only
|
171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
172 |
+
of any other Contributor, and only if You agree to indemnify,
|
173 |
+
defend, and hold each Contributor harmless for any liability
|
174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
175 |
+
of your accepting any such warranty or additional liability.
|
176 |
+
|
177 |
+
END OF TERMS AND CONDITIONS
|
178 |
+
|
179 |
+
APPENDIX: How to apply the Apache License to your work.
|
180 |
+
|
181 |
+
To apply the Apache License to your work, attach the following
|
182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
183 |
+
replaced with your own identifying information. (Don't include
|
184 |
+
the brackets!) The text should be enclosed in the appropriate
|
185 |
+
comment syntax for the file format. We also recommend that a
|
186 |
+
file or class name and description of purpose be included on the
|
187 |
+
same "printed page" as the copyright notice for easier
|
188 |
+
identification within third-party archives.
|
189 |
+
|
190 |
+
Copyright [yyyy] [name of copyright owner]
|
191 |
+
|
192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
193 |
+
you may not use this file except in compliance with the License.
|
194 |
+
You may obtain a copy of the License at
|
195 |
+
|
196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
197 |
+
|
198 |
+
Unless required by applicable law or agreed to in writing, software
|
199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
201 |
+
See the License for the specific language governing permissions and
|
202 |
+
limitations under the License.
|
includes/vendor/maxmind-db/reader/README.md
CHANGED
@@ -1,156 +1,156 @@
|
|
1 |
-
# MaxMind DB Reader PHP API #
|
2 |
-
|
3 |
-
## Description ##
|
4 |
-
|
5 |
-
This is the PHP API for reading MaxMind DB files. MaxMind DB is a binary file
|
6 |
-
format that stores data indexed by IP address subnets (IPv4 or IPv6).
|
7 |
-
|
8 |
-
## Installation (Composer) ##
|
9 |
-
|
10 |
-
We recommend installing this package with [Composer](http://getcomposer.org/).
|
11 |
-
|
12 |
-
### Download Composer ###
|
13 |
-
|
14 |
-
To download Composer, run in the root directory of your project:
|
15 |
-
|
16 |
-
```bash
|
17 |
-
curl -sS https://getcomposer.org/installer | php
|
18 |
-
```
|
19 |
-
|
20 |
-
You should now have the file `composer.phar` in your project directory.
|
21 |
-
|
22 |
-
### Install Dependencies ###
|
23 |
-
|
24 |
-
Run in your project root:
|
25 |
-
|
26 |
-
```
|
27 |
-
php composer.phar require maxmind-db/reader:~1.0
|
28 |
-
```
|
29 |
-
|
30 |
-
You should now have the files `composer.json` and `composer.lock` as well as
|
31 |
-
the directory `vendor` in your project directory. If you use a version control
|
32 |
-
system, `composer.json` should be added to it.
|
33 |
-
|
34 |
-
### Require Autoloader ###
|
35 |
-
|
36 |
-
After installing the dependencies, you need to require the Composer autoloader
|
37 |
-
from your code:
|
38 |
-
|
39 |
-
```php
|
40 |
-
require 'vendor/autoload.php';
|
41 |
-
```
|
42 |
-
|
43 |
-
## Installation (Standalone) ##
|
44 |
-
|
45 |
-
If you don't want to use Composer for some reason, a custom
|
46 |
-
`autoload.php` is provided for you in the project root. To use the
|
47 |
-
library, simply include that file,
|
48 |
-
|
49 |
-
```php
|
50 |
-
require('/path/to/MaxMind-DB-Reader-php/autoload.php');
|
51 |
-
```
|
52 |
-
|
53 |
-
and then instantiate the reader class normally:
|
54 |
-
|
55 |
-
```php
|
56 |
-
use MaxMind\Db\Reader;
|
57 |
-
$reader = new Reader('example.mmdb');
|
58 |
-
```
|
59 |
-
|
60 |
-
## Usage ##
|
61 |
-
|
62 |
-
## Example ##
|
63 |
-
|
64 |
-
```php
|
65 |
-
<?php
|
66 |
-
require_once 'vendor/autoload.php';
|
67 |
-
|
68 |
-
use MaxMind\Db\Reader;
|
69 |
-
|
70 |
-
$ipAddress = '24.24.24.24';
|
71 |
-
$databaseFile = 'GeoIP2-City.mmdb';
|
72 |
-
|
73 |
-
$reader = new Reader($databaseFile);
|
74 |
-
|
75 |
-
print_r($reader->get($ipAddress));
|
76 |
-
|
77 |
-
$reader->close();
|
78 |
-
```
|
79 |
-
|
80 |
-
## Optional PHP C Extension ##
|
81 |
-
|
82 |
-
MaxMind provides an optional C extension that is a drop-in replacement for
|
83 |
-
`MaxMind\Db\Reader`. In order to use this extension, you must install the
|
84 |
-
Reader API as described above and install the extension as described below. If
|
85 |
-
you are using an autoloader, no changes to your code should be necessary.
|
86 |
-
|
87 |
-
### Installing Extension ###
|
88 |
-
|
89 |
-
First install [libmaxminddb](https://github.com/maxmind/libmaxminddb) as
|
90 |
-
described in its [README.md
|
91 |
-
file](https://github.com/maxmind/libmaxminddb/blob/master/README.md#installing-from-a-tarball).
|
92 |
-
After successfully installing libmaxmindb, run the following commands from the
|
93 |
-
top-level directory of this distribution:
|
94 |
-
|
95 |
-
```
|
96 |
-
cd ext
|
97 |
-
phpize
|
98 |
-
./configure
|
99 |
-
make
|
100 |
-
make test
|
101 |
-
sudo make install
|
102 |
-
```
|
103 |
-
|
104 |
-
You then must load your extension. The recommend method is to add the
|
105 |
-
following to your `php.ini` file:
|
106 |
-
|
107 |
-
```
|
108 |
-
extension=maxminddb.so
|
109 |
-
```
|
110 |
-
|
111 |
-
Note: You may need to install the PHP development package on your OS such as
|
112 |
-
php5-dev for Debian-based systems or php-devel for RedHat/Fedora-based ones.
|
113 |
-
|
114 |
-
## 128-bit Integer Support ##
|
115 |
-
|
116 |
-
The MaxMind DB format includes 128-bit unsigned integer as a type. Although
|
117 |
-
no MaxMind-distributed database currently makes use of this type, both the
|
118 |
-
pure PHP reader and the C extension support this type. The pure PHP reader
|
119 |
-
requires gmp or bcmath to read databases with 128-bit unsigned integers.
|
120 |
-
|
121 |
-
The integer is currently returned as a hexadecimal string (prefixed with "0x")
|
122 |
-
by the C extension and a decimal string (no prefix) by the pure PHP reader.
|
123 |
-
Any change to make the reader implementations always return either a
|
124 |
-
hexadecimal or decimal representation of the integer will NOT be considered a
|
125 |
-
breaking change.
|
126 |
-
|
127 |
-
## Support ##
|
128 |
-
|
129 |
-
Please report all issues with this code using the [GitHub issue tracker]
|
130 |
-
(https://github.com/maxmind/MaxMind-DB-Reader-php/issues).
|
131 |
-
|
132 |
-
If you are having an issue with a MaxMind service that is not specific to the
|
133 |
-
client API, please see [our support page](http://www.maxmind.com/en/support).
|
134 |
-
|
135 |
-
## Requirements ##
|
136 |
-
|
137 |
-
This library requires PHP 5.4 or greater. The pure PHP reader included with
|
138 |
-
this library works and is tested with HHVM.
|
139 |
-
|
140 |
-
The GMP or BCMath extension may be required to read some databases
|
141 |
-
using the pure PHP API.
|
142 |
-
|
143 |
-
## Contributing ##
|
144 |
-
|
145 |
-
Patches and pull requests are encouraged. All code should follow the PSR-1 and
|
146 |
-
PSR-2 style guidelines. Please include unit tests whenever possible.
|
147 |
-
|
148 |
-
## Versioning ##
|
149 |
-
|
150 |
-
The MaxMind DB Reader PHP API uses [Semantic Versioning](http://semver.org/).
|
151 |
-
|
152 |
-
## Copyright and License ##
|
153 |
-
|
154 |
-
This software is Copyright (c) 2014-2017 by MaxMind, Inc.
|
155 |
-
|
156 |
-
This is free software, licensed under the Apache License, Version 2.0.
|
1 |
+
# MaxMind DB Reader PHP API #
|
2 |
+
|
3 |
+
## Description ##
|
4 |
+
|
5 |
+
This is the PHP API for reading MaxMind DB files. MaxMind DB is a binary file
|
6 |
+
format that stores data indexed by IP address subnets (IPv4 or IPv6).
|
7 |
+
|
8 |
+
## Installation (Composer) ##
|
9 |
+
|
10 |
+
We recommend installing this package with [Composer](http://getcomposer.org/).
|
11 |
+
|
12 |
+
### Download Composer ###
|
13 |
+
|
14 |
+
To download Composer, run in the root directory of your project:
|
15 |
+
|
16 |
+
```bash
|
17 |
+
curl -sS https://getcomposer.org/installer | php
|
18 |
+
```
|
19 |
+
|
20 |
+
You should now have the file `composer.phar` in your project directory.
|
21 |
+
|
22 |
+
### Install Dependencies ###
|
23 |
+
|
24 |
+
Run in your project root:
|
25 |
+
|
26 |
+
```
|
27 |
+
php composer.phar require maxmind-db/reader:~1.0
|
28 |
+
```
|
29 |
+
|
30 |
+
You should now have the files `composer.json` and `composer.lock` as well as
|
31 |
+
the directory `vendor` in your project directory. If you use a version control
|
32 |
+
system, `composer.json` should be added to it.
|
33 |
+
|
34 |
+
### Require Autoloader ###
|
35 |
+
|
36 |
+
After installing the dependencies, you need to require the Composer autoloader
|
37 |
+
from your code:
|
38 |
+
|
39 |
+
```php
|
40 |
+
require 'vendor/autoload.php';
|
41 |
+
```
|
42 |
+
|
43 |
+
## Installation (Standalone) ##
|
44 |
+
|
45 |
+
If you don't want to use Composer for some reason, a custom
|
46 |
+
`autoload.php` is provided for you in the project root. To use the
|
47 |
+
library, simply include that file,
|
48 |
+
|
49 |
+
```php
|
50 |
+
require('/path/to/MaxMind-DB-Reader-php/autoload.php');
|
51 |
+
```
|
52 |
+
|
53 |
+
and then instantiate the reader class normally:
|
54 |
+
|
55 |
+
```php
|
56 |
+
use MaxMind\Db\Reader;
|
57 |
+
$reader = new Reader('example.mmdb');
|
58 |
+
```
|
59 |
+
|
60 |
+
## Usage ##
|
61 |
+
|
62 |
+
## Example ##
|
63 |
+
|
64 |
+
```php
|
65 |
+
<?php
|
66 |
+
require_once 'vendor/autoload.php';
|
67 |
+
|
68 |
+
use MaxMind\Db\Reader;
|
69 |
+
|
70 |
+
$ipAddress = '24.24.24.24';
|
71 |
+
$databaseFile = 'GeoIP2-City.mmdb';
|
72 |
+
|
73 |
+
$reader = new Reader($databaseFile);
|
74 |
+
|
75 |
+
print_r($reader->get($ipAddress));
|
76 |
+
|
77 |
+
$reader->close();
|
78 |
+
```
|
79 |
+
|
80 |
+
## Optional PHP C Extension ##
|
81 |
+
|
82 |
+
MaxMind provides an optional C extension that is a drop-in replacement for
|
83 |
+
`MaxMind\Db\Reader`. In order to use this extension, you must install the
|
84 |
+
Reader API as described above and install the extension as described below. If
|
85 |
+
you are using an autoloader, no changes to your code should be necessary.
|
86 |
+
|
87 |
+
### Installing Extension ###
|
88 |
+
|
89 |
+
First install [libmaxminddb](https://github.com/maxmind/libmaxminddb) as
|
90 |
+
described in its [README.md
|
91 |
+
file](https://github.com/maxmind/libmaxminddb/blob/master/README.md#installing-from-a-tarball).
|
92 |
+
After successfully installing libmaxmindb, run the following commands from the
|
93 |
+
top-level directory of this distribution:
|
94 |
+
|
95 |
+
```
|
96 |
+
cd ext
|
97 |
+
phpize
|
98 |
+
./configure
|
99 |
+
make
|
100 |
+
make test
|
101 |
+
sudo make install
|
102 |
+
```
|
103 |
+
|
104 |
+
You then must load your extension. The recommend method is to add the
|
105 |
+
following to your `php.ini` file:
|
106 |
+
|
107 |
+
```
|
108 |
+
extension=maxminddb.so
|
109 |
+
```
|
110 |
+
|
111 |
+
Note: You may need to install the PHP development package on your OS such as
|
112 |
+
php5-dev for Debian-based systems or php-devel for RedHat/Fedora-based ones.
|
113 |
+
|
114 |
+
## 128-bit Integer Support ##
|
115 |
+
|
116 |
+
The MaxMind DB format includes 128-bit unsigned integer as a type. Although
|
117 |
+
no MaxMind-distributed database currently makes use of this type, both the
|
118 |
+
pure PHP reader and the C extension support this type. The pure PHP reader
|
119 |
+
requires gmp or bcmath to read databases with 128-bit unsigned integers.
|
120 |
+
|
121 |
+
The integer is currently returned as a hexadecimal string (prefixed with "0x")
|
122 |
+
by the C extension and a decimal string (no prefix) by the pure PHP reader.
|
123 |
+
Any change to make the reader implementations always return either a
|
124 |
+
hexadecimal or decimal representation of the integer will NOT be considered a
|
125 |
+
breaking change.
|
126 |
+
|
127 |
+
## Support ##
|
128 |
+
|
129 |
+
Please report all issues with this code using the [GitHub issue tracker]
|
130 |
+
(https://github.com/maxmind/MaxMind-DB-Reader-php/issues).
|
131 |
+
|
132 |
+
If you are having an issue with a MaxMind service that is not specific to the
|
133 |
+
client API, please see [our support page](http://www.maxmind.com/en/support).
|
134 |
+
|
135 |
+
## Requirements ##
|
136 |
+
|
137 |
+
This library requires PHP 5.4 or greater. The pure PHP reader included with
|
138 |
+
this library works and is tested with HHVM.
|
139 |
+
|
140 |
+
The GMP or BCMath extension may be required to read some databases
|
141 |
+
using the pure PHP API.
|
142 |
+
|
143 |
+
## Contributing ##
|
144 |
+
|
145 |
+
Patches and pull requests are encouraged. All code should follow the PSR-1 and
|
146 |
+
PSR-2 style guidelines. Please include unit tests whenever possible.
|
147 |
+
|
148 |
+
## Versioning ##
|
149 |
+
|
150 |
+
The MaxMind DB Reader PHP API uses [Semantic Versioning](http://semver.org/).
|
151 |
+
|
152 |
+
## Copyright and License ##
|
153 |
+
|
154 |
+
This software is Copyright (c) 2014-2017 by MaxMind, Inc.
|
155 |
+
|
156 |
+
This is free software, licensed under the Apache License, Version 2.0.
|
includes/vendor/maxmind-db/reader/autoload.php
CHANGED
@@ -1,44 +1,44 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* PSR-4 autoloader implementation for the MaxMind\DB namespace.
|
5 |
-
* First we define the 'mmdb_autoload' function, and then we register
|
6 |
-
* it with 'spl_autoload_register' so that PHP knows to use it.
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Automatically include the file that defines <code>class</code>.
|
11 |
-
*
|
12 |
-
* @param string $class
|
13 |
-
* the name of the class to load
|
14 |
-
*
|
15 |
-
* @return void
|
16 |
-
*/
|
17 |
-
function mmdb_autoload($class)
|
18 |
-
{
|
19 |
-
/*
|
20 |
-
* A project-specific mapping between the namespaces and where
|
21 |
-
* they're located. By convention, we include the trailing
|
22 |
-
* slashes. The one-element array here simply makes things easy
|
23 |
-
* to extend in the future if (for example) the test classes
|
24 |
-
* begin to use one another.
|
25 |
-
*/
|
26 |
-
$namespace_map = array('MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/');
|
27 |
-
|
28 |
-
foreach ($namespace_map as $prefix => $dir)
|
29 |
-
{
|
30 |
-
/* First swap out the namespace prefix with a directory... */
|
31 |
-
$path = str_replace($prefix, $dir, $class);
|
32 |
-
|
33 |
-
/* replace the namespace separator with a directory separator... */
|
34 |
-
$path = str_replace('\\', '/', $path);
|
35 |
-
|
36 |
-
/* and finally, add the PHP file extension to the result. */
|
37 |
-
$path = $path . '.php';
|
38 |
-
|
39 |
-
/* $path should now contain the path to a PHP file defining $class */
|
40 |
-
@include $path;
|
41 |
-
}
|
42 |
-
}
|
43 |
-
|
44 |
-
spl_autoload_register('mmdb_autoload');
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* PSR-4 autoloader implementation for the MaxMind\DB namespace.
|
5 |
+
* First we define the 'mmdb_autoload' function, and then we register
|
6 |
+
* it with 'spl_autoload_register' so that PHP knows to use it.
|
7 |
+
*/
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Automatically include the file that defines <code>class</code>.
|
11 |
+
*
|
12 |
+
* @param string $class
|
13 |
+
* the name of the class to load
|
14 |
+
*
|
15 |
+
* @return void
|
16 |
+
*/
|
17 |
+
function mmdb_autoload($class)
|
18 |
+
{
|
19 |
+
/*
|
20 |
+
* A project-specific mapping between the namespaces and where
|
21 |
+
* they're located. By convention, we include the trailing
|
22 |
+
* slashes. The one-element array here simply makes things easy
|
23 |
+
* to extend in the future if (for example) the test classes
|
24 |
+
* begin to use one another.
|
25 |
+
*/
|
26 |
+
$namespace_map = array('MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/');
|
27 |
+
|
28 |
+
foreach ($namespace_map as $prefix => $dir)
|
29 |
+
{
|
30 |
+
/* First swap out the namespace prefix with a directory... */
|
31 |
+
$path = str_replace($prefix, $dir, $class);
|
32 |
+
|
33 |
+
/* replace the namespace separator with a directory separator... */
|
34 |
+
$path = str_replace('\\', '/', $path);
|
35 |
+
|
36 |
+
/* and finally, add the PHP file extension to the result. */
|
37 |
+
$path = $path . '.php';
|
38 |
+
|
39 |
+
/* $path should now contain the path to a PHP file defining $class */
|
40 |
+
@include $path;
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
spl_autoload_register('mmdb_autoload');
|
includes/vendor/maxmind-db/reader/composer.json
CHANGED
@@ -1,34 +1,34 @@
|
|
1 |
-
{
|
2 |
-
"name": "maxmind-db/reader",
|
3 |
-
"description": "MaxMind DB Reader API",
|
4 |
-
"keywords": ["database", "geoip", "geoip2", "geolocation", "maxmind"],
|
5 |
-
"homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
|
6 |
-
"type": "library",
|
7 |
-
"license": "Apache-2.0",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "Gregory J. Oschwald",
|
11 |
-
"email": "goschwald@maxmind.com",
|
12 |
-
"homepage": "http://www.maxmind.com/"
|
13 |
-
}
|
14 |
-
],
|
15 |
-
"require": {
|
16 |
-
"php": ">=5.4"
|
17 |
-
},
|
18 |
-
"suggest": {
|
19 |
-
"ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
20 |
-
"ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
21 |
-
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
|
22 |
-
},
|
23 |
-
"require-dev": {
|
24 |
-
"friendsofphp/php-cs-fixer": "2.*",
|
25 |
-
"phpunit/phpunit": "4.* || 5.*",
|
26 |
-
"satooshi/php-coveralls": "1.0.*",
|
27 |
-
"squizlabs/php_codesniffer": "3.*"
|
28 |
-
},
|
29 |
-
"autoload": {
|
30 |
-
"psr-4": {
|
31 |
-
"MaxMind\\Db\\": "src/MaxMind/Db"
|
32 |
-
}
|
33 |
-
}
|
34 |
-
}
|
1 |
+
{
|
2 |
+
"name": "maxmind-db/reader",
|
3 |
+
"description": "MaxMind DB Reader API",
|
4 |
+
"keywords": ["database", "geoip", "geoip2", "geolocation", "maxmind"],
|
5 |
+
"homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
|
6 |
+
"type": "library",
|
7 |
+
"license": "Apache-2.0",
|
8 |
+
"authors": [
|
9 |
+
{
|
10 |
+
"name": "Gregory J. Oschwald",
|
11 |
+
"email": "goschwald@maxmind.com",
|
12 |
+
"homepage": "http://www.maxmind.com/"
|
13 |
+
}
|
14 |
+
],
|
15 |
+
"require": {
|
16 |
+
"php": ">=5.4"
|
17 |
+
},
|
18 |
+
"suggest": {
|
19 |
+
"ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
20 |
+
"ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
|
21 |
+
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
|
22 |
+
},
|
23 |
+
"require-dev": {
|
24 |
+
"friendsofphp/php-cs-fixer": "2.*",
|
25 |
+
"phpunit/phpunit": "4.* || 5.*",
|
26 |
+
"satooshi/php-coveralls": "1.0.*",
|
27 |
+
"squizlabs/php_codesniffer": "3.*"
|
28 |
+
},
|
29 |
+
"autoload": {
|
30 |
+
"psr-4": {
|
31 |
+
"MaxMind\\Db\\": "src/MaxMind/Db"
|
32 |
+
}
|
33 |
+
}
|
34 |
+
}
|
includes/vendor/maxmind-db/reader/ext/config.m4
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
PHP_ARG_WITH(maxminddb,
|
2 |
-
[Whether to enable the MaxMind DB Reader extension],
|
3 |
-
[ --with-maxminddb Enable MaxMind DB Reader extension support])
|
4 |
-
|
5 |
-
PHP_ARG_ENABLE(maxminddb-debug, for MaxMind DB debug support,
|
6 |
-
[ --enable-maxminddb-debug Enable enable MaxMind DB deubg support], no, no)
|
7 |
-
|
8 |
-
if test $PHP_MAXMINDDB != "no"; then
|
9 |
-
PHP_CHECK_LIBRARY(maxminddb, MMDB_open)
|
10 |
-
|
11 |
-
if test $PHP_MAXMINDDB_DEBUG != "no"; then
|
12 |
-
CFLAGS="$CFLAGS -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Werror"
|
13 |
-
fi
|
14 |
-
|
15 |
-
PHP_ADD_LIBRARY(maxminddb, 1, MAXMINDDB_SHARED_LIBADD)
|
16 |
-
PHP_SUBST(MAXMINDDB_SHARED_LIBADD)
|
17 |
-
|
18 |
-
PHP_NEW_EXTENSION(maxminddb, maxminddb.c, $ext_shared)
|
19 |
-
fi
|
1 |
+
PHP_ARG_WITH(maxminddb,
|
2 |
+
[Whether to enable the MaxMind DB Reader extension],
|
3 |
+
[ --with-maxminddb Enable MaxMind DB Reader extension support])
|
4 |
+
|
5 |
+
PHP_ARG_ENABLE(maxminddb-debug, for MaxMind DB debug support,
|
6 |
+
[ --enable-maxminddb-debug Enable enable MaxMind DB deubg support], no, no)
|
7 |
+
|
8 |
+
if test $PHP_MAXMINDDB != "no"; then
|
9 |
+
PHP_CHECK_LIBRARY(maxminddb, MMDB_open)
|
10 |
+
|
11 |
+
if test $PHP_MAXMINDDB_DEBUG != "no"; then
|
12 |
+
CFLAGS="$CFLAGS -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Werror"
|
13 |
+
fi
|
14 |
+
|
15 |
+
PHP_ADD_LIBRARY(maxminddb, 1, MAXMINDDB_SHARED_LIBADD)
|
16 |
+
PHP_SUBST(MAXMINDDB_SHARED_LIBADD)
|
17 |
+
|
18 |
+
PHP_NEW_EXTENSION(maxminddb, maxminddb.c, $ext_shared)
|
19 |
+
fi
|
includes/vendor/maxmind-db/reader/ext/maxminddb.c
CHANGED
@@ -1,564 +1,564 @@
|
|
1 |
-
/* MaxMind, Inc., licenses this file to you under the Apache License, Version
|
2 |
-
* 2.0 (the "License"); you may not use this file except in compliance with
|
3 |
-
* the License. You may obtain a copy of the License at
|
4 |
-
*
|
5 |
-
* http://www.apache.org/licenses/LICENSE-2.0
|
6 |
-
*
|
7 |
-
* Unless required by applicable law or agreed to in writing, software
|
8 |
-
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
9 |
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
10 |
-
* License for the specific language governing permissions and limitations
|
11 |
-
* under the License.
|
12 |
-
*/
|
13 |
-
|
14 |
-
#include "php_maxminddb.h"
|
15 |
-
|
16 |
-
#ifdef HAVE_CONFIG_H
|
17 |
-
#include "config.h"
|
18 |
-
#endif
|
19 |
-
|
20 |
-
#include <php.h>
|
21 |
-
#include <zend.h>
|
22 |
-
#include "Zend/zend_exceptions.h"
|
23 |
-
#include <maxminddb.h>
|
24 |
-
|
25 |
-
#ifdef ZTS
|
26 |
-
#include <TSRM.h>
|
27 |
-
#endif
|
28 |
-
|
29 |
-
#define __STDC_FORMAT_MACROS
|
30 |
-
#include <inttypes.h>
|
31 |
-
|
32 |
-
#define PHP_MAXMINDDB_NS ZEND_NS_NAME("MaxMind", "Db")
|
33 |
-
#define PHP_MAXMINDDB_READER_NS ZEND_NS_NAME(PHP_MAXMINDDB_NS, "Reader")
|
34 |
-
#define PHP_MAXMINDDB_READER_EX_NS \
|
35 |
-
ZEND_NS_NAME(PHP_MAXMINDDB_READER_NS, \
|
36 |
-
"InvalidDatabaseException")
|
37 |
-
|
38 |
-
#ifdef ZEND_ENGINE_3
|
39 |
-
#define Z_MAXMINDDB_P(zv) php_maxminddb_fetch_object(Z_OBJ_P(zv))
|
40 |
-
#define _ZVAL_STRING ZVAL_STRING
|
41 |
-
#define _ZVAL_STRINGL ZVAL_STRINGL
|
42 |
-
typedef size_t strsize_t;
|
43 |
-
typedef zend_object free_obj_t;
|
44 |
-
#else
|
45 |
-
#define Z_MAXMINDDB_P(zv) (maxminddb_obj *) zend_object_store_get_object(zv TSRMLS_CC)
|
46 |
-
#define _ZVAL_STRING(a, b) ZVAL_STRING(a, b, 1)
|
47 |
-
#define _ZVAL_STRINGL(a, b, c) ZVAL_STRINGL(a, b, c, 1)
|
48 |
-
typedef int strsize_t;
|
49 |
-
typedef void free_obj_t;
|
50 |
-
#endif
|
51 |
-
|
52 |
-
#ifdef ZEND_ENGINE_3
|
53 |
-
typedef struct _maxminddb_obj {
|
54 |
-
MMDB_s *mmdb;
|
55 |
-
zend_object std;
|
56 |
-
} maxminddb_obj;
|
57 |
-
#else
|
58 |
-
typedef struct _maxminddb_obj {
|
59 |
-
zend_object std;
|
60 |
-
MMDB_s *mmdb;
|
61 |
-
} maxminddb_obj;
|
62 |
-
#endif
|
63 |
-
|
64 |
-
PHP_FUNCTION(maxminddb);
|
65 |
-
|
66 |
-
static const MMDB_entry_data_list_s *handle_entry_data_list(
|
67 |
-
const MMDB_entry_data_list_s *entry_data_list,
|
68 |
-
zval *z_value
|
69 |
-
TSRMLS_DC);
|
70 |
-
static const MMDB_entry_data_list_s *handle_array(
|
71 |
-
const MMDB_entry_data_list_s *entry_data_list,
|
72 |
-
zval *z_value TSRMLS_DC);
|
73 |
-
static const MMDB_entry_data_list_s *handle_map(
|
74 |
-
const MMDB_entry_data_list_s *entry_data_list,
|
75 |
-
zval *z_value TSRMLS_DC);
|
76 |
-
static void handle_uint128(const MMDB_entry_data_list_s *entry_data_list,
|
77 |
-
zval *z_value TSRMLS_DC);
|
78 |
-
static void handle_uint64(const MMDB_entry_data_list_s *entry_data_list,
|
79 |
-
zval *z_value TSRMLS_DC);
|
80 |
-
static zend_class_entry * lookup_class(const char *name TSRMLS_DC);
|
81 |
-
|
82 |
-
#define CHECK_ALLOCATED(val) \
|
83 |
-
if (!val ) { \
|
84 |
-
zend_error(E_ERROR, "Out of memory"); \
|
85 |
-
return; \
|
86 |
-
} \
|
87 |
-
|
88 |
-
#define THROW_EXCEPTION(name, ... ) \
|
89 |
-
{ \
|
90 |
-
zend_class_entry *exception_ce = lookup_class(name TSRMLS_CC); \
|
91 |
-
zend_throw_exception_ex(exception_ce, 0 TSRMLS_CC, __VA_ARGS__); \
|
92 |
-
} \
|
93 |
-
|
94 |
-
|
95 |
-
#if PHP_VERSION_ID < 50399
|
96 |
-
#define object_properties_init(zo, class_type) \
|
97 |
-
{ \
|
98 |
-
zval *tmp; \
|
99 |
-
zend_hash_copy((*zo).properties, \
|
100 |
-
&class_type->default_properties, \
|
101 |
-
(copy_ctor_func_t)zval_add_ref, \
|
102 |
-
(void *)&tmp, \
|
103 |
-
sizeof(zval *)); \
|
104 |
-
}
|
105 |
-
#endif
|
106 |
-
|
107 |
-
static zend_object_handlers maxminddb_obj_handlers;
|
108 |
-
static zend_class_entry *maxminddb_ce;
|
109 |
-
|
110 |
-
static inline maxminddb_obj *php_maxminddb_fetch_object(zend_object *obj TSRMLS_DC){
|
111 |
-
#ifdef ZEND_ENGINE_3
|
112 |
-
return (maxminddb_obj *)((char*)(obj) - XtOffsetOf(maxminddb_obj, std));
|
113 |
-
#else
|
114 |
-
return (maxminddb_obj *)obj;
|
115 |
-
#endif
|
116 |
-
}
|
117 |
-
|
118 |
-
PHP_METHOD(MaxMind_Db_Reader, __construct){
|
119 |
-
char *db_file = NULL;
|
120 |
-
strsize_t name_len;
|
121 |
-
zval * _this_zval = NULL;
|
122 |
-
|
123 |
-
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
|
124 |
-
&_this_zval, maxminddb_ce, &db_file, &name_len) == FAILURE) {
|
125 |
-
THROW_EXCEPTION("InvalidArgumentException",
|
126 |
-
"The constructor takes exactly one argument.");
|
127 |
-
return;
|
128 |
-
}
|
129 |
-
|
130 |
-
if (0 != php_check_open_basedir(db_file TSRMLS_CC) || 0 != access(db_file, R_OK)) {
|
131 |
-
THROW_EXCEPTION("InvalidArgumentException",
|
132 |
-
"The file \"%s\" does not exist or is not readable.",
|
133 |
-
db_file);
|
134 |
-
return;
|
135 |
-
}
|
136 |
-
|
137 |
-
MMDB_s *mmdb = (MMDB_s *)emalloc(sizeof(MMDB_s));
|
138 |
-
uint16_t status = MMDB_open(db_file, MMDB_MODE_MMAP, mmdb);
|
139 |
-
|
140 |
-
if (MMDB_SUCCESS != status) {
|
141 |
-
THROW_EXCEPTION(
|
142 |
-
PHP_MAXMINDDB_READER_EX_NS,
|
143 |
-
"Error opening database file (%s). Is this a valid MaxMind DB file?",
|
144 |
-
db_file);
|
145 |
-
efree(mmdb);
|
146 |
-
return;
|
147 |
-
}
|
148 |
-
|
149 |
-
maxminddb_obj *mmdb_obj = Z_MAXMINDDB_P(getThis());
|
150 |
-
mmdb_obj->mmdb = mmdb;
|
151 |
-
}
|
152 |
-
|
153 |
-
PHP_METHOD(MaxMind_Db_Reader, get){
|
154 |
-
char *ip_address = NULL;
|
155 |
-
strsize_t name_len;
|
156 |
-
zval * _this_zval = NULL;
|
157 |
-
|
158 |
-
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
|
159 |
-
&_this_zval, maxminddb_ce, &ip_address, &name_len) == FAILURE) {
|
160 |
-
THROW_EXCEPTION("InvalidArgumentException",
|
161 |
-
"Method takes exactly one argument.");
|
162 |
-
return;
|
163 |
-
}
|
164 |
-
|
165 |
-
const maxminddb_obj *mmdb_obj =
|
166 |
-
(maxminddb_obj *)Z_MAXMINDDB_P(getThis());
|
167 |
-
|
168 |
-
MMDB_s *mmdb = mmdb_obj->mmdb;
|
169 |
-
|
170 |
-
if (NULL == mmdb) {
|
171 |
-
THROW_EXCEPTION("BadMethodCallException",
|
172 |
-
"Attempt to read from a closed MaxMind DB.");
|
173 |
-
return;
|
174 |
-
}
|
175 |
-
|
176 |
-
int gai_error = 0;
|
177 |
-
int mmdb_error = MMDB_SUCCESS;
|
178 |
-
MMDB_lookup_result_s result =
|
179 |
-
MMDB_lookup_string(mmdb, ip_address, &gai_error,
|
180 |
-
&mmdb_error);
|
181 |
-
|
182 |
-
if (MMDB_SUCCESS != gai_error) {
|
183 |
-
THROW_EXCEPTION("InvalidArgumentException",
|
184 |
-
"The value \"%s\" is not a valid IP address.",
|
185 |
-
ip_address);
|
186 |
-
return;
|
187 |
-
}
|
188 |
-
|
189 |
-
if (MMDB_SUCCESS != mmdb_error) {
|
190 |
-
char *exception_name;
|
191 |
-
if (MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR == mmdb_error) {
|
192 |
-
exception_name = "InvalidArgumentException";
|
193 |
-
} else {
|
194 |
-
exception_name = PHP_MAXMINDDB_READER_EX_NS;
|
195 |
-
}
|
196 |
-
THROW_EXCEPTION(exception_name,
|
197 |
-
"Error looking up %s. %s",
|
198 |
-
ip_address, MMDB_strerror(mmdb_error));
|
199 |
-
return;
|
200 |
-
}
|
201 |
-
|
202 |
-
MMDB_entry_data_list_s *entry_data_list = NULL;
|
203 |
-
|
204 |
-
if (!result.found_entry) {
|
205 |
-
RETURN_NULL();
|
206 |
-
}
|
207 |
-
|
208 |
-
int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
|
209 |
-
|
210 |
-
if (MMDB_SUCCESS != status) {
|
211 |
-
THROW_EXCEPTION(PHP_MAXMINDDB_READER_EX_NS,
|
212 |
-
"Error while looking up data for %s. %s",
|
213 |
-
ip_address, MMDB_strerror(status));
|
214 |
-
MMDB_free_entry_data_list(entry_data_list);
|
215 |
-
return;
|
216 |
-
} else if (NULL == entry_data_list) {
|
217 |
-
THROW_EXCEPTION(
|
218 |
-
PHP_MAXMINDDB_READER_EX_NS,
|
219 |
-
"Error while looking up data for %s. Your database may be corrupt or you have found a bug in libmaxminddb.",
|
220 |
-
ip_address);
|
221 |
-
return;
|
222 |
-
}
|
223 |
-
|
224 |
-
handle_entry_data_list(entry_data_list, return_value TSRMLS_CC);
|
225 |
-
MMDB_free_entry_data_list(entry_data_list);
|
226 |
-
}
|
227 |
-
|
228 |
-
PHP_METHOD(MaxMind_Db_Reader, metadata){
|
229 |
-
if (ZEND_NUM_ARGS() != 0) {
|
230 |
-
THROW_EXCEPTION("InvalidArgumentException",
|
231 |
-
"Method takes no arguments.");
|
232 |
-
return;
|
233 |
-
}
|
234 |
-
|
235 |
-
const maxminddb_obj *const mmdb_obj =
|
236 |
-
(maxminddb_obj *)Z_MAXMINDDB_P(getThis());
|
237 |
-
|
238 |
-
if (NULL == mmdb_obj->mmdb) {
|
239 |
-
THROW_EXCEPTION("BadMethodCallException",
|
240 |
-
"Attempt to read from a closed MaxMind DB.");
|
241 |
-
return;
|
242 |
-
}
|
243 |
-
|
244 |
-
const char *const name = ZEND_NS_NAME(PHP_MAXMINDDB_READER_NS, "Metadata");
|
245 |
-
zend_class_entry *metadata_ce = lookup_class(name TSRMLS_CC);
|
246 |
-
|
247 |
-
object_init_ex(return_value, metadata_ce);
|
248 |
-
|
249 |
-
#ifdef ZEND_ENGINE_3
|
250 |
-
zval _metadata_array;
|
251 |
-
zval *metadata_array = &_metadata_array;
|
252 |
-
ZVAL_NULL(metadata_array);
|
253 |
-
#else
|
254 |
-
zval *metadata_array;
|
255 |
-
ALLOC_INIT_ZVAL(metadata_array);
|
256 |
-
#endif
|
257 |
-
|
258 |
-
MMDB_entry_data_list_s *entry_data_list;
|
259 |
-
MMDB_get_metadata_as_entry_data_list(mmdb_obj->mmdb, &entry_data_list);
|
260 |
-
|
261 |
-
handle_entry_data_list(entry_data_list, metadata_array TSRMLS_CC);
|
262 |
-
MMDB_free_entry_data_list(entry_data_list);
|
263 |
-
#ifdef ZEND_ENGINE_3
|
264 |
-
zend_call_method_with_1_params(return_value, metadata_ce,
|
265 |
-
&metadata_ce->constructor,
|
266 |
-
ZEND_CONSTRUCTOR_FUNC_NAME,
|
267 |
-
NULL,
|
268 |
-
metadata_array);
|
269 |
-
zval_ptr_dtor(metadata_array);
|
270 |
-
#else
|
271 |
-
zend_call_method_with_1_params(&return_value, metadata_ce,
|
272 |
-
&metadata_ce->constructor,
|
273 |
-
ZEND_CONSTRUCTOR_FUNC_NAME,
|
274 |
-
NULL,
|
275 |
-
metadata_array);
|
276 |
-
zval_ptr_dtor(&metadata_array);
|
277 |
-
#endif
|
278 |
-
}
|
279 |
-
|
280 |
-
PHP_METHOD(MaxMind_Db_Reader, close){
|
281 |
-
if (ZEND_NUM_ARGS() != 0) {
|
282 |
-
THROW_EXCEPTION("InvalidArgumentException",
|
283 |
-
"Method takes no arguments.");
|
284 |
-
return;
|
285 |
-
}
|
286 |
-
|
287 |
-
maxminddb_obj *mmdb_obj =
|
288 |
-
(maxminddb_obj *)Z_MAXMINDDB_P(getThis());
|
289 |
-
|
290 |
-
if (NULL == mmdb_obj->mmdb) {
|
291 |
-
THROW_EXCEPTION("BadMethodCallException",
|
292 |
-
"Attempt to close a closed MaxMind DB.");
|
293 |
-
return;
|
294 |
-
}
|
295 |
-
MMDB_close(mmdb_obj->mmdb);
|
296 |
-
efree(mmdb_obj->mmdb);
|
297 |
-
mmdb_obj->mmdb = NULL;
|
298 |
-
}
|
299 |
-
|
300 |
-
static const MMDB_entry_data_list_s *handle_entry_data_list(
|
301 |
-
const MMDB_entry_data_list_s *entry_data_list,
|
302 |
-
zval *z_value
|
303 |
-
TSRMLS_DC)
|
304 |
-
{
|
305 |
-
switch (entry_data_list->entry_data.type) {
|
306 |
-
case MMDB_DATA_TYPE_MAP:
|
307 |
-
return handle_map(entry_data_list, z_value TSRMLS_CC);
|
308 |
-
case MMDB_DATA_TYPE_ARRAY:
|
309 |
-
return handle_array(entry_data_list, z_value TSRMLS_CC);
|
310 |
-
case MMDB_DATA_TYPE_UTF8_STRING:
|
311 |
-
_ZVAL_STRINGL(z_value,
|
312 |
-
(char *)entry_data_list->entry_data.utf8_string,
|
313 |
-
entry_data_list->entry_data.data_size);
|
314 |
-
break;
|
315 |
-
case MMDB_DATA_TYPE_BYTES:
|
316 |
-
_ZVAL_STRINGL(z_value, (char *)entry_data_list->entry_data.bytes,
|
317 |
-
entry_data_list->entry_data.data_size);
|
318 |
-
break;
|
319 |
-
case MMDB_DATA_TYPE_DOUBLE:
|
320 |
-
ZVAL_DOUBLE(z_value, entry_data_list->entry_data.double_value);
|
321 |
-
break;
|
322 |
-
case MMDB_DATA_TYPE_FLOAT:
|
323 |
-
ZVAL_DOUBLE(z_value, entry_data_list->entry_data.float_value);
|
324 |
-
break;
|
325 |
-
case MMDB_DATA_TYPE_UINT16:
|
326 |
-
ZVAL_LONG(z_value, entry_data_list->entry_data.uint16);
|
327 |
-
break;
|
328 |
-
case MMDB_DATA_TYPE_UINT32:
|
329 |
-
ZVAL_LONG(z_value, entry_data_list->entry_data.uint32);
|
330 |
-
break;
|
331 |
-
case MMDB_DATA_TYPE_BOOLEAN:
|
332 |
-
ZVAL_BOOL(z_value, entry_data_list->entry_data.boolean);
|
333 |
-
break;
|
334 |
-
case MMDB_DATA_TYPE_UINT64:
|
335 |
-
handle_uint64(entry_data_list, z_value TSRMLS_CC);
|
336 |
-
break;
|
337 |
-
case MMDB_DATA_TYPE_UINT128:
|
338 |
-
handle_uint128(entry_data_list, z_value TSRMLS_CC);
|
339 |
-
break;
|
340 |
-
case MMDB_DATA_TYPE_INT32:
|
341 |
-
ZVAL_LONG(z_value, entry_data_list->entry_data.int32);
|
342 |
-
break;
|
343 |
-
default:
|
344 |
-
THROW_EXCEPTION(PHP_MAXMINDDB_READER_EX_NS,
|
345 |
-
"Invalid data type arguments: %d",
|
346 |
-
entry_data_list->entry_data.type);
|
347 |
-
return NULL;
|
348 |
-
}
|
349 |
-
return entry_data_list;
|
350 |
-
}
|
351 |
-
|
352 |
-
static const MMDB_entry_data_list_s *handle_map(
|
353 |
-
const MMDB_entry_data_list_s *entry_data_list,
|
354 |
-
zval *z_value TSRMLS_DC)
|
355 |
-
{
|
356 |
-
array_init(z_value);
|
357 |
-
const uint32_t map_size = entry_data_list->entry_data.data_size;
|
358 |
-
|
359 |
-
uint i;
|
360 |
-
for (i = 0; i < map_size && entry_data_list; i++ ) {
|
361 |
-
entry_data_list = entry_data_list->next;
|
362 |
-
|
363 |
-
char *key =
|
364 |
-
estrndup((char *)entry_data_list->entry_data.utf8_string,
|
365 |
-
entry_data_list->entry_data.data_size);
|
366 |
-
if (NULL == key) {
|
367 |
-
THROW_EXCEPTION(PHP_MAXMINDDB_READER_EX_NS,
|
368 |
-
"Invalid data type arguments");
|
369 |
-
return NULL;
|
370 |
-
}
|
371 |
-
|
372 |
-
entry_data_list = entry_data_list->next;
|
373 |
-
#ifdef ZEND_ENGINE_3
|
374 |
-
zval _new_value;
|
375 |
-
zval * new_value = &_new_value;
|
376 |
-
ZVAL_NULL(new_value);
|
377 |
-
#else
|
378 |
-
zval *new_value;
|
379 |
-
ALLOC_INIT_ZVAL(new_value);
|
380 |
-
#endif
|
381 |
-
entry_data_list = handle_entry_data_list(entry_data_list,
|
382 |
-
new_value TSRMLS_CC);
|
383 |
-
add_assoc_zval(z_value, key, new_value);
|
384 |
-
efree(key);
|
385 |
-
}
|
386 |
-
return entry_data_list;
|
387 |
-
}
|
388 |
-
|
389 |
-
static const MMDB_entry_data_list_s *handle_array(
|
390 |
-
const MMDB_entry_data_list_s *entry_data_list,
|
391 |
-
zval *z_value TSRMLS_DC)
|
392 |
-
{
|
393 |
-
const uint32_t size = entry_data_list->entry_data.data_size;
|
394 |
-
|
395 |
-
array_init(z_value);
|
396 |
-
|
397 |
-
uint i;
|
398 |
-
for (i = 0; i < size && entry_data_list; i++) {
|
399 |
-
entry_data_list = entry_data_list->next;
|
400 |
-
#ifdef ZEND_ENGINE_3
|
401 |
-
zval _new_value;
|
402 |
-
zval * new_value = &_new_value;
|
403 |
-
ZVAL_NULL(new_value);
|
404 |
-
#else
|
405 |
-
zval *new_value;
|
406 |
-
ALLOC_INIT_ZVAL(new_value);
|
407 |
-
#endif
|
408 |
-
entry_data_list = handle_entry_data_list(entry_data_list,
|
409 |
-
new_value TSRMLS_CC);
|
410 |
-
add_next_index_zval(z_value, new_value);
|
411 |
-
}
|
412 |
-
return entry_data_list;
|
413 |
-
}
|
414 |
-
|
415 |
-
static void handle_uint128(const MMDB_entry_data_list_s *entry_data_list,
|
416 |
-
zval *z_value TSRMLS_DC)
|
417 |
-
{
|
418 |
-
uint64_t high = 0;
|
419 |
-
uint64_t low = 0;
|
420 |
-
#if MMDB_UINT128_IS_BYTE_ARRAY
|
421 |
-
int i;
|
422 |
-
for (i = 0; i < 8; i++) {
|
423 |
-
high = (high << 8) | entry_data_list->entry_data.uint128[i];
|
424 |
-
}
|
425 |
-
|
426 |
-
for (i = 8; i < 16; i++) {
|
427 |
-
low = (low << 8) | entry_data_list->entry_data.uint128[i];
|
428 |
-
}
|
429 |
-
#else
|
430 |
-
high = entry_data_list->entry_data.uint128 >> 64;
|
431 |
-
low = (uint64_t)entry_data_list->entry_data.uint128;
|
432 |
-
#endif
|
433 |
-
|
434 |
-
char *num_str;
|
435 |
-
spprintf(&num_str, 0, "0x%016" PRIX64 "%016" PRIX64, high, low);
|
436 |
-
CHECK_ALLOCATED(num_str);
|
437 |
-
|
438 |
-
_ZVAL_STRING(z_value, num_str);
|
439 |
-
efree(num_str);
|
440 |
-
}
|
441 |
-
|
442 |
-
static void handle_uint64(const MMDB_entry_data_list_s *entry_data_list,
|
443 |
-
zval *z_value TSRMLS_DC)
|
444 |
-
{
|
445 |
-
// We return it as a string because PHP uses signed longs
|
446 |
-
char *int_str;
|
447 |
-
spprintf(&int_str, 0, "%" PRIu64,
|
448 |
-
entry_data_list->entry_data.uint64);
|
449 |
-
CHECK_ALLOCATED(int_str);
|
450 |
-
|
451 |
-
_ZVAL_STRING(z_value, int_str);
|
452 |
-
efree(int_str);
|
453 |
-
}
|
454 |
-
|
455 |
-
static zend_class_entry *lookup_class(const char *name TSRMLS_DC)
|
456 |
-
{
|
457 |
-
#ifdef ZEND_ENGINE_3
|
458 |
-
zend_string *n = zend_string_init(name, strlen(name), 0);
|
459 |
-
zend_class_entry *ce = zend_lookup_class(n);
|
460 |
-
zend_string_release(n);
|
461 |
-
if( NULL == ce ) {
|
462 |
-
zend_error(E_ERROR, "Class %s not found", name);
|
463 |
-
}
|
464 |
-
return ce;
|
465 |
-
#else
|
466 |
-
zend_class_entry **ce;
|
467 |
-
if (FAILURE ==
|
468 |
-
zend_lookup_class(name, strlen(name),
|
469 |
-
&ce TSRMLS_CC)) {
|
470 |
-
zend_error(E_ERROR, "Class %s not found", name);
|
471 |
-
}
|
472 |
-
return *ce;
|
473 |
-
#endif
|
474 |
-
}
|
475 |
-
|
476 |
-
static void maxminddb_free_storage(free_obj_t *object TSRMLS_DC)
|
477 |
-
{
|
478 |
-
maxminddb_obj *obj = php_maxminddb_fetch_object((zend_object *)object TSRMLS_CC);
|
479 |
-
if (obj->mmdb != NULL) {
|
480 |
-
MMDB_close(obj->mmdb);
|
481 |
-
efree(obj->mmdb);
|
482 |
-
}
|
483 |
-
|
484 |
-
zend_object_std_dtor(&obj->std TSRMLS_CC);
|
485 |
-
#ifndef ZEND_ENGINE_3
|
486 |
-
efree(object);
|
487 |
-
#endif
|
488 |
-
}
|
489 |
-
|
490 |
-
#ifdef ZEND_ENGINE_3
|
491 |
-
static zend_object *maxminddb_create_handler(
|
492 |
-
zend_class_entry *type TSRMLS_DC)
|
493 |
-
{
|
494 |
-
maxminddb_obj *obj = (maxminddb_obj *)ecalloc(1, sizeof(maxminddb_obj));
|
495 |
-
zend_object_std_init(&obj->std, type TSRMLS_CC);
|
496 |
-
object_properties_init(&(obj->std), type);
|
497 |
-
|
498 |
-
obj->std.handlers = &maxminddb_obj_handlers;
|
499 |
-
|
500 |
-
return &obj->std;
|
501 |
-
}
|
502 |
-
#else
|
503 |
-
static zend_object_value maxminddb_create_handler(
|
504 |
-
zend_class_entry *type TSRMLS_DC)
|
505 |
-
{
|
506 |
-
zend_object_value retval;
|
507 |
-
|
508 |
-
maxminddb_obj *obj = (maxminddb_obj *)ecalloc(1, sizeof(maxminddb_obj));
|
509 |
-
zend_object_std_init(&obj->std, type TSRMLS_CC);
|
510 |
-
object_properties_init(&(obj->std), type);
|
511 |
-
|
512 |
-
retval.handle = zend_objects_store_put(obj, NULL,
|
513 |
-
maxminddb_free_storage,
|
514 |
-
NULL TSRMLS_CC);
|
515 |
-
retval.handlers = &maxminddb_obj_handlers;
|
516 |
-
|
517 |
-
return retval;
|
518 |
-
}
|
519 |
-
#endif
|
520 |
-
|
521 |
-
/* *INDENT-OFF* */
|
522 |
-
static zend_function_entry maxminddb_methods[] = {
|
523 |
-
PHP_ME(MaxMind_Db_Reader, __construct, NULL,
|
524 |
-
ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
|
525 |
-
PHP_ME(MaxMind_Db_Reader, close, NULL, ZEND_ACC_PUBLIC)
|
526 |
-
PHP_ME(MaxMind_Db_Reader, get, NULL, ZEND_ACC_PUBLIC)
|
527 |
-
PHP_ME(MaxMind_Db_Reader, metadata, NULL, ZEND_ACC_PUBLIC)
|
528 |
-
{ NULL, NULL, NULL }
|
529 |
-
};
|
530 |
-
/* *INDENT-ON* */
|
531 |
-
|
532 |
-
PHP_MINIT_FUNCTION(maxminddb){
|
533 |
-
zend_class_entry ce;
|
534 |
-
|
535 |
-
INIT_CLASS_ENTRY(ce, PHP_MAXMINDDB_READER_NS, maxminddb_methods);
|
536 |
-
maxminddb_ce = zend_register_internal_class(&ce TSRMLS_CC);
|
537 |
-
maxminddb_ce->create_object = maxminddb_create_handler;
|
538 |
-
memcpy(&maxminddb_obj_handlers,
|
539 |
-
zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
540 |
-
maxminddb_obj_handlers.clone_obj = NULL;
|
541 |
-
#ifdef ZEND_ENGINE_3
|
542 |
-
maxminddb_obj_handlers.offset = XtOffsetOf(maxminddb_obj, std);
|
543 |
-
maxminddb_obj_handlers.free_obj = maxminddb_free_storage;
|
544 |
-
#endif
|
545 |
-
|
546 |
-
return SUCCESS;
|
547 |
-
}
|
548 |
-
|
549 |
-
zend_module_entry maxminddb_module_entry = {
|
550 |
-
STANDARD_MODULE_HEADER,
|
551 |
-
PHP_MAXMINDDB_EXTNAME,
|
552 |
-
NULL,
|
553 |
-
PHP_MINIT(maxminddb),
|
554 |
-
NULL,
|
555 |
-
NULL,
|
556 |
-
NULL,
|
557 |
-
NULL,
|
558 |
-
PHP_MAXMINDDB_VERSION,
|
559 |
-
STANDARD_MODULE_PROPERTIES
|
560 |
-
};
|
561 |
-
|
562 |
-
#ifdef COMPILE_DL_MAXMINDDB
|
563 |
-
ZEND_GET_MODULE(maxminddb)
|
564 |
-
#endif
|
1 |
+
/* MaxMind, Inc., licenses this file to you under the Apache License, Version
|
2 |
+
* 2.0 (the "License"); you may not use this file except in compliance with
|
3 |
+
* the License. You may obtain a copy of the License at
|
4 |
+
*
|
5 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
6 |
+
*
|
7 |
+
* Unless required by applicable law or agreed to in writing, software
|
8 |
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
9 |
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
10 |
+
* License for the specific language governing permissions and limitations
|
11 |
+
* under the License.
|
12 |
+
*/
|
13 |
+
|
14 |
+
#include "php_maxminddb.h"
|
15 |
+
|
16 |
+
#ifdef HAVE_CONFIG_H
|
17 |
+
#include "config.h"
|
18 |
+
#endif
|
19 |
+
|
20 |
+
#include <php.h>
|
21 |
+
#include <zend.h>
|
22 |
+
#include "Zend/zend_exceptions.h"
|
23 |
+
#include <maxminddb.h>
|
24 |
+
|
25 |
+
#ifdef ZTS
|
26 |
+
#include <TSRM.h>
|
27 |
+
#endif
|
28 |
+
|
29 |
+
#define __STDC_FORMAT_MACROS
|
30 |
+
#include <inttypes.h>
|
31 |
+
|
32 |
+
#define PHP_MAXMINDDB_NS ZEND_NS_NAME("MaxMind", "Db")
|
33 |
+
#define PHP_MAXMINDDB_READER_NS ZEND_NS_NAME(PHP_MAXMINDDB_NS, "Reader")
|
34 |
+
#define PHP_MAXMINDDB_READER_EX_NS \
|
35 |
+
ZEND_NS_NAME(PHP_MAXMINDDB_READER_NS, \
|
36 |
+
"InvalidDatabaseException")
|
37 |
+
|
38 |
+
#ifdef ZEND_ENGINE_3
|
39 |
+
#define Z_MAXMINDDB_P(zv) php_maxminddb_fetch_object(Z_OBJ_P(zv))
|
40 |
+
#define _ZVAL_STRING ZVAL_STRING
|
41 |
+
#define _ZVAL_STRINGL ZVAL_STRINGL
|
42 |
+
typedef size_t strsize_t;
|
43 |
+
typedef zend_object free_obj_t;
|
44 |
+
#else
|
45 |
+
#define Z_MAXMINDDB_P(zv) (maxminddb_obj *) zend_object_store_get_object(zv TSRMLS_CC)
|
46 |
+
#define _ZVAL_STRING(a, b) ZVAL_STRING(a, b, 1)
|
47 |
+
#define _ZVAL_STRINGL(a, b, c) ZVAL_STRINGL(a, b, c, 1)
|
48 |
+
typedef int strsize_t;
|
49 |
+
typedef void free_obj_t;
|
50 |
+
#endif
|
51 |
+
|
52 |
+
#ifdef ZEND_ENGINE_3
|
53 |
+
typedef struct _maxminddb_obj {
|
54 |
+
MMDB_s *mmdb;
|
55 |
+
zend_object std;
|
56 |
+
} maxminddb_obj;
|
57 |
+
#else
|
58 |
+
typedef struct _maxminddb_obj {
|
59 |
+
zend_object std;
|
60 |
+
MMDB_s *mmdb;
|
61 |
+
} maxminddb_obj;
|
62 |
+
#endif
|
63 |
+
|
64 |
+
PHP_FUNCTION(maxminddb);
|
65 |
+
|
66 |
+
static const MMDB_entry_data_list_s *handle_entry_data_list(
|
67 |
+
const MMDB_entry_data_list_s *entry_data_list,
|
68 |
+
zval *z_value
|
69 |
+
TSRMLS_DC);
|
70 |
+
static const MMDB_entry_data_list_s *handle_array(
|
71 |
+
const MMDB_entry_data_list_s *entry_data_list,
|
72 |
+
zval *z_value TSRMLS_DC);
|
73 |
+
static const MMDB_entry_data_list_s *handle_map(
|
74 |
+
const MMDB_entry_data_list_s *entry_data_list,
|
75 |
+
zval *z_value TSRMLS_DC);
|
76 |
+
static void handle_uint128(const MMDB_entry_data_list_s *entry_data_list,
|
77 |
+
zval *z_value TSRMLS_DC);
|
78 |
+
static void handle_uint64(const MMDB_entry_data_list_s *entry_data_list,
|
79 |
+
zval *z_value TSRMLS_DC);
|
80 |
+
static zend_class_entry * lookup_class(const char *name TSRMLS_DC);
|
81 |
+
|
82 |
+
#define CHECK_ALLOCATED(val) \
|
83 |
+
if (!val ) { \
|
84 |
+
zend_error(E_ERROR, "Out of memory"); \
|
85 |
+
return; \
|
86 |
+
} \
|
87 |
+
|
88 |
+
#define THROW_EXCEPTION(name, ... ) \
|
89 |
+
{ \
|
90 |
+
zend_class_entry *exception_ce = lookup_class(name TSRMLS_CC); \
|
91 |
+
zend_throw_exception_ex(exception_ce, 0 TSRMLS_CC, __VA_ARGS__); \
|
92 |
+
} \
|
93 |
+
|
94 |
+
|
95 |
+
#if PHP_VERSION_ID < 50399
|
96 |
+
#define object_properties_init(zo, class_type) \
|
97 |
+
{ \
|
98 |
+
zval *tmp; \
|
99 |
+
zend_hash_copy((*zo).properties, \
|
100 |
+
&class_type->default_properties, \
|
101 |
+
(copy_ctor_func_t)zval_add_ref, \
|
102 |
+
(void *)&tmp, \
|
103 |
+
sizeof(zval *)); \
|
104 |
+
}
|
105 |
+
#endif
|
106 |
+
|
107 |
+
static zend_object_handlers maxminddb_obj_handlers;
|
108 |
+
static zend_class_entry *maxminddb_ce;
|
109 |
+
|
110 |
+
static inline maxminddb_obj *php_maxminddb_fetch_object(zend_object *obj TSRMLS_DC){
|
111 |
+
#ifdef ZEND_ENGINE_3
|
112 |
+
return (maxminddb_obj *)((char*)(obj) - XtOffsetOf(maxminddb_obj, std));
|
113 |
+
#else
|
114 |
+
return (maxminddb_obj *)obj;
|
115 |
+
#endif
|
116 |
+
}
|
117 |
+
|
118 |
+
PHP_METHOD(MaxMind_Db_Reader, __construct){
|
119 |
+
char *db_file = NULL;
|
120 |
+
strsize_t name_len;
|
121 |
+
zval * _this_zval = NULL;
|
122 |
+
|
123 |
+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
|
124 |
+
&_this_zval, maxminddb_ce, &db_file, &name_len) == FAILURE) {
|
125 |
+
THROW_EXCEPTION("InvalidArgumentException",
|
126 |
+
"The constructor takes exactly one argument.");
|
127 |
+
return;
|
128 |
+
}
|
129 |
+
|
130 |
+
if (0 != php_check_open_basedir(db_file TSRMLS_CC) || 0 != access(db_file, R_OK)) {
|
131 |
+
THROW_EXCEPTION("InvalidArgumentException",
|
132 |
+
"The file \"%s\" does not exist or is not readable.",
|
133 |
+
db_file);
|
134 |
+
return;
|
135 |
+
}
|
136 |
+
|
137 |
+
MMDB_s *mmdb = (MMDB_s *)emalloc(sizeof(MMDB_s));
|
138 |
+
uint16_t status = MMDB_open(db_file, MMDB_MODE_MMAP, mmdb);
|
139 |
+
|
140 |
+
if (MMDB_SUCCESS != status) {
|
141 |
+
THROW_EXCEPTION(
|
142 |
+
PHP_MAXMINDDB_READER_EX_NS,
|
143 |
+
"Error opening database file (%s). Is this a valid MaxMind DB file?",
|
144 |
+
db_file);
|
145 |
+
efree(mmdb);
|
146 |
+
return;
|
147 |
+
}
|
148 |
+
|
149 |
+
maxminddb_obj *mmdb_obj = Z_MAXMINDDB_P(getThis());
|
150 |
+
mmdb_obj->mmdb = mmdb;
|
151 |
+
}
|
152 |
+
|
153 |
+
PHP_METHOD(MaxMind_Db_Reader, get){
|
154 |
+
char *ip_address = NULL;
|
155 |
+
strsize_t name_len;
|
156 |
+
zval * _this_zval = NULL;
|
157 |
+
|
158 |
+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
|
159 |
+
&_this_zval, maxminddb_ce, &ip_address, &name_len) == FAILURE) {
|
160 |
+
THROW_EXCEPTION("InvalidArgumentException",
|
161 |
+
"Method takes exactly one argument.");
|
162 |
+
return;
|
163 |
+
}
|
164 |
+
|
165 |
+
const maxminddb_obj *mmdb_obj =
|
166 |
+
(maxminddb_obj *)Z_MAXMINDDB_P(getThis());
|
167 |
+
|
168 |
+
MMDB_s *mmdb = mmdb_obj->mmdb;
|
169 |
+
|
170 |
+
if (NULL == mmdb) {
|
171 |
+
THROW_EXCEPTION("BadMethodCallException",
|
172 |
+
"Attempt to read from a closed MaxMind DB.");
|
173 |
+
return;
|
174 |
+
}
|
175 |
+
|
176 |
+
int gai_error = 0;
|
177 |
+
int mmdb_error = MMDB_SUCCESS;
|
178 |
+
MMDB_lookup_result_s result =
|
179 |
+
MMDB_lookup_string(mmdb, ip_address, &gai_error,
|
180 |
+
&mmdb_error);
|
181 |
+
|
182 |
+
if (MMDB_SUCCESS != gai_error) {
|
183 |
+
THROW_EXCEPTION("InvalidArgumentException",
|
184 |
+
"The value \"%s\" is not a valid IP address.",
|
185 |
+
ip_address);
|
186 |
+
return;
|
187 |
+
}
|
188 |
+
|
189 |
+
if (MMDB_SUCCESS != mmdb_error) {
|
190 |
+
char *exception_name;
|
191 |
+
if (MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR == mmdb_error) {
|
192 |
+
exception_name = "InvalidArgumentException";
|
193 |
+
} else {
|
194 |
+
exception_name = PHP_MAXMINDDB_READER_EX_NS;
|
195 |
+
}
|
196 |
+
THROW_EXCEPTION(exception_name,
|
197 |
+
"Error looking up %s. %s",
|
198 |
+
ip_address, MMDB_strerror(mmdb_error));
|
199 |
+
return;
|
200 |
+
}
|
201 |
+
|
202 |
+
MMDB_entry_data_list_s *entry_data_list = NULL;
|
203 |
+
|
204 |
+
if (!result.found_entry) {
|
205 |
+
RETURN_NULL();
|
206 |
+
}
|
207 |
+
|
208 |
+
int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
|
209 |
+
|
210 |
+
if (MMDB_SUCCESS != status) {
|
211 |
+
THROW_EXCEPTION(PHP_MAXMINDDB_READER_EX_NS,
|
212 |
+
"Error while looking up data for %s. %s",
|
213 |
+
ip_address, MMDB_strerror(status));
|
214 |
+
MMDB_free_entry_data_list(entry_data_list);
|
215 |
+
return;
|
216 |
+
} else if (NULL == entry_data_list) {
|
217 |
+
THROW_EXCEPTION(
|
218 |
+
PHP_MAXMINDDB_READER_EX_NS,
|
219 |
+
"Error while looking up data for %s. Your database may be corrupt or you have found a bug in libmaxminddb.",
|
220 |
+
ip_address);
|
221 |
+
return;
|
222 |
+
}
|
223 |
+
|
224 |
+
handle_entry_data_list(entry_data_list, return_value TSRMLS_CC);
|
225 |
+
MMDB_free_entry_data_list(entry_data_list);
|
226 |
+
}
|
227 |
+
|
228 |
+
PHP_METHOD(MaxMind_Db_Reader, metadata){
|
229 |
+
if (ZEND_NUM_ARGS() != 0) {
|
230 |
+
THROW_EXCEPTION("InvalidArgumentException",
|
231 |
+
"Method takes no arguments.");
|
232 |
+
return;
|
233 |
+
}
|
234 |
+
|
235 |
+
const maxminddb_obj *const mmdb_obj =
|
236 |
+
(maxminddb_obj *)Z_MAXMINDDB_P(getThis());
|
237 |
+
|
238 |
+
if (NULL == mmdb_obj->mmdb) {
|
239 |
+
THROW_EXCEPTION("BadMethodCallException",
|
240 |
+
"Attempt to read from a closed MaxMind DB.");
|
241 |
+
return;
|
242 |
+
}
|
243 |
+
|
244 |
+
const char *const name = ZEND_NS_NAME(PHP_MAXMINDDB_READER_NS, "Metadata");
|
245 |
+
zend_class_entry *metadata_ce = lookup_class(name TSRMLS_CC);
|
246 |
+
|
247 |
+
object_init_ex(return_value, metadata_ce);
|
248 |
+
|
249 |
+
#ifdef ZEND_ENGINE_3
|
250 |
+
zval _metadata_array;
|
251 |
+
zval *metadata_array = &_metadata_array;
|
252 |
+
ZVAL_NULL(metadata_array);
|
253 |
+
#else
|
254 |
+
zval *metadata_array;
|
255 |
+
ALLOC_INIT_ZVAL(metadata_array);
|
256 |
+
#endif
|
257 |
+
|
258 |
+
MMDB_entry_data_list_s *entry_data_list;
|
259 |
+
MMDB_get_metadata_as_entry_data_list(mmdb_obj->mmdb, &entry_data_list);
|
260 |
+
|
261 |
+
handle_entry_data_list(entry_data_list, metadata_array TSRMLS_CC);
|
262 |
+
MMDB_free_entry_data_list(entry_data_list);
|
263 |
+
#ifdef ZEND_ENGINE_3
|
264 |
+
zend_call_method_with_1_params(return_value, metadata_ce,
|
265 |
+
&metadata_ce->constructor,
|
266 |
+
ZEND_CONSTRUCTOR_FUNC_NAME,
|
267 |
+
NULL,
|
268 |
+
metadata_array);
|
269 |
+
zval_ptr_dtor(metadata_array);
|
270 |
+
#else
|
271 |
+
zend_call_method_with_1_params(&return_value, metadata_ce,
|
272 |
+
&metadata_ce->constructor,
|
273 |
+
ZEND_CONSTRUCTOR_FUNC_NAME,
|
274 |
+
NULL,
|
275 |
+
metadata_array);
|
276 |
+
zval_ptr_dtor(&metadata_array);
|
277 |
+
#endif
|
278 |
+
}
|
279 |
+
|
280 |
+
PHP_METHOD(MaxMind_Db_Reader, close){
|
281 |
+
if (ZEND_NUM_ARGS() != 0) {
|
282 |
+
THROW_EXCEPTION("InvalidArgumentException",
|
283 |
+
"Method takes no arguments.");
|
284 |
+
return;
|
285 |
+
}
|
286 |
+
|
287 |
+
maxminddb_obj *mmdb_obj =
|
288 |
+
(maxminddb_obj *)Z_MAXMINDDB_P(getThis());
|
289 |
+
|
290 |
+
if (NULL == mmdb_obj->mmdb) {
|
291 |
+
THROW_EXCEPTION("BadMethodCallException",
|
292 |
+
"Attempt to close a closed MaxMind DB.");
|
293 |
+
return;
|
294 |
+
}
|
295 |
+
MMDB_close(mmdb_obj->mmdb);
|
296 |
+
efree(mmdb_obj->mmdb);
|
297 |
+
mmdb_obj->mmdb = NULL;
|
298 |
+
}
|
299 |
+
|
300 |
+
static const MMDB_entry_data_list_s *handle_entry_data_list(
|
301 |
+
const MMDB_entry_data_list_s *entry_data_list,
|
302 |
+
zval *z_value
|
303 |
+
TSRMLS_DC)
|
304 |
+
{
|
305 |
+
switch (entry_data_list->entry_data.type) {
|
306 |
+
case MMDB_DATA_TYPE_MAP:
|
307 |
+
return handle_map(entry_data_list, z_value TSRMLS_CC);
|
308 |
+
case MMDB_DATA_TYPE_ARRAY:
|
309 |
+
return handle_array(entry_data_list, z_value TSRMLS_CC);
|
310 |
+
case MMDB_DATA_TYPE_UTF8_STRING:
|
311 |
+
_ZVAL_STRINGL(z_value,
|
312 |
+
(char *)entry_data_list->entry_data.utf8_string,
|
313 |
+
entry_data_list->entry_data.data_size);
|
314 |
+
break;
|
315 |
+
case MMDB_DATA_TYPE_BYTES:
|
316 |
+
_ZVAL_STRINGL(z_value, (char *)entry_data_list->entry_data.bytes,
|
317 |
+
entry_data_list->entry_data.data_size);
|
318 |
+
break;
|
319 |
+
case MMDB_DATA_TYPE_DOUBLE:
|
320 |
+
ZVAL_DOUBLE(z_value, entry_data_list->entry_data.double_value);
|
321 |
+
break;
|
322 |
+
case MMDB_DATA_TYPE_FLOAT:
|
323 |
+
ZVAL_DOUBLE(z_value, entry_data_list->entry_data.float_value);
|
324 |
+
break;
|
325 |
+
case MMDB_DATA_TYPE_UINT16:
|
326 |
+
ZVAL_LONG(z_value, entry_data_list->entry_data.uint16);
|
327 |
+
break;
|
328 |
+
case MMDB_DATA_TYPE_UINT32:
|
329 |
+
ZVAL_LONG(z_value, entry_data_list->entry_data.uint32);
|
330 |
+
break;
|
331 |
+
case MMDB_DATA_TYPE_BOOLEAN:
|
332 |
+
ZVAL_BOOL(z_value, entry_data_list->entry_data.boolean);
|
333 |
+
break;
|
334 |
+
case MMDB_DATA_TYPE_UINT64:
|
335 |
+
handle_uint64(entry_data_list, z_value TSRMLS_CC);
|
336 |
+
break;
|
337 |
+
case MMDB_DATA_TYPE_UINT128:
|
338 |
+
handle_uint128(entry_data_list, z_value TSRMLS_CC);
|
339 |
+
break;
|
340 |
+
case MMDB_DATA_TYPE_INT32:
|
341 |
+
ZVAL_LONG(z_value, entry_data_list->entry_data.int32);
|
342 |
+
break;
|
343 |
+
default:
|
344 |
+
THROW_EXCEPTION(PHP_MAXMINDDB_READER_EX_NS,
|
345 |
+
"Invalid data type arguments: %d",
|
346 |
+
entry_data_list->entry_data.type);
|
347 |
+
return NULL;
|
348 |
+
}
|
349 |
+
return entry_data_list;
|
350 |
+
}
|
351 |
+
|
352 |
+
static const MMDB_entry_data_list_s *handle_map(
|
353 |
+
const MMDB_entry_data_list_s *entry_data_list,
|
354 |
+
zval *z_value TSRMLS_DC)
|
355 |
+
{
|
356 |
+
array_init(z_value);
|
357 |
+
const uint32_t map_size = entry_data_list->entry_data.data_size;
|
358 |
+
|
359 |
+
uint i;
|
360 |
+
for (i = 0; i < map_size && entry_data_list; i++ ) {
|
361 |
+
entry_data_list = entry_data_list->next;
|
362 |
+
|
363 |
+
char *key =
|
364 |
+
estrndup((char *)entry_data_list->entry_data.utf8_string,
|
365 |
+
entry_data_list->entry_data.data_size);
|
366 |
+
if (NULL == key) {
|
367 |
+
THROW_EXCEPTION(PHP_MAXMINDDB_READER_EX_NS,
|
368 |
+
"Invalid data type arguments");
|
369 |
+
return NULL;
|
370 |
+
}
|
371 |
+
|
372 |
+
entry_data_list = entry_data_list->next;
|
373 |
+
#ifdef ZEND_ENGINE_3
|
374 |
+
zval _new_value;
|
375 |
+
zval * new_value = &_new_value;
|
376 |
+
ZVAL_NULL(new_value);
|
377 |
+
#else
|
378 |
+
zval *new_value;
|
379 |
+
ALLOC_INIT_ZVAL(new_value);
|
380 |
+
#endif
|
381 |
+
entry_data_list = handle_entry_data_list(entry_data_list,
|
382 |
+
new_value TSRMLS_CC);
|
383 |
+
add_assoc_zval(z_value, key, new_value);
|
384 |
+
efree(key);
|
385 |
+
}
|
386 |
+
return entry_data_list;
|
387 |
+
}
|
388 |
+
|
389 |
+
static const MMDB_entry_data_list_s *handle_array(
|
390 |
+
const MMDB_entry_data_list_s *entry_data_list,
|
391 |
+
zval *z_value TSRMLS_DC)
|
392 |
+
{
|
393 |
+
const uint32_t size = entry_data_list->entry_data.data_size;
|
394 |
+
|
395 |
+
array_init(z_value);
|
396 |
+
|
397 |
+
uint i;
|
398 |
+
for (i = 0; i < size && entry_data_list; i++) {
|
399 |
+
entry_data_list = entry_data_list->next;
|
400 |
+
#ifdef ZEND_ENGINE_3
|
401 |
+
zval _new_value;
|
402 |
+
zval * new_value = &_new_value;
|
403 |
+
ZVAL_NULL(new_value);
|
404 |
+
#else
|
405 |
+
zval *new_value;
|
406 |
+
ALLOC_INIT_ZVAL(new_value);
|
407 |
+
#endif
|
408 |
+
entry_data_list = handle_entry_data_list(entry_data_list,
|
409 |
+
new_value TSRMLS_CC);
|
410 |
+
add_next_index_zval(z_value, new_value);
|
411 |
+
}
|
412 |
+
return entry_data_list;
|
413 |
+
}
|
414 |
+
|
415 |
+
static void handle_uint128(const MMDB_entry_data_list_s *entry_data_list,
|
416 |
+
zval *z_value TSRMLS_DC)
|
417 |
+
{
|
418 |
+
uint64_t high = 0;
|
419 |
+
uint64_t low = 0;
|
420 |
+
#if MMDB_UINT128_IS_BYTE_ARRAY
|
421 |
+
int i;
|
422 |
+
for (i = 0; i < 8; i++) {
|
423 |
+
high = (high << 8) | entry_data_list->entry_data.uint128[i];
|
424 |
+
}
|
425 |
+
|
426 |
+
for (i = 8; i < 16; i++) {
|
427 |
+
low = (low << 8) | entry_data_list->entry_data.uint128[i];
|
428 |
+
}
|
429 |
+
#else
|
430 |
+
high = entry_data_list->entry_data.uint128 >> 64;
|
431 |
+
low = (uint64_t)entry_data_list->entry_data.uint128;
|
432 |
+
#endif
|
433 |
+
|
434 |
+
char *num_str;
|
435 |
+
spprintf(&num_str, 0, "0x%016" PRIX64 "%016" PRIX64, high, low);
|
436 |
+
CHECK_ALLOCATED(num_str);
|
437 |
+
|
438 |
+
_ZVAL_STRING(z_value, num_str);
|
439 |
+
efree(num_str);
|
440 |
+
}
|
441 |
+
|
442 |
+
static void handle_uint64(const MMDB_entry_data_list_s *entry_data_list,
|
443 |
+
zval *z_value TSRMLS_DC)
|
444 |
+
{
|
445 |
+
// We return it as a string because PHP uses signed longs
|
446 |
+
char *int_str;
|
447 |
+
spprintf(&int_str, 0, "%" PRIu64,
|
448 |
+
entry_data_list->entry_data.uint64);
|
449 |
+
CHECK_ALLOCATED(int_str);
|
450 |
+
|
451 |
+
_ZVAL_STRING(z_value, int_str);
|
452 |
+
efree(int_str);
|
453 |
+
}
|
454 |
+
|
455 |
+
static zend_class_entry *lookup_class(const char *name TSRMLS_DC)
|
456 |
+
{
|
457 |
+
#ifdef ZEND_ENGINE_3
|
458 |
+
zend_string *n = zend_string_init(name, strlen(name), 0);
|
459 |
+
zend_class_entry *ce = zend_lookup_class(n);
|
460 |
+
zend_string_release(n);
|
461 |
+
if( NULL == ce ) {
|
462 |
+
zend_error(E_ERROR, "Class %s not found", name);
|
463 |
+
}
|
464 |
+
return ce;
|
465 |
+
#else
|
466 |
+
zend_class_entry **ce;
|
467 |
+
if (FAILURE ==
|
468 |
+
zend_lookup_class(name, strlen(name),
|
469 |
+
&ce TSRMLS_CC)) {
|
470 |
+
zend_error(E_ERROR, "Class %s not found", name);
|
471 |
+
}
|
472 |
+
return *ce;
|
473 |
+
#endif
|
474 |
+
}
|
475 |
+
|
476 |
+
static void maxminddb_free_storage(free_obj_t *object TSRMLS_DC)
|
477 |
+
{
|
478 |
+
maxminddb_obj *obj = php_maxminddb_fetch_object((zend_object *)object TSRMLS_CC);
|
479 |
+
if (obj->mmdb != NULL) {
|
480 |
+
MMDB_close(obj->mmdb);
|
481 |
+
efree(obj->mmdb);
|
482 |
+
}
|
483 |
+
|
484 |
+
zend_object_std_dtor(&obj->std TSRMLS_CC);
|
485 |
+
#ifndef ZEND_ENGINE_3
|
486 |
+
efree(object);
|
487 |
+
#endif
|
488 |
+
}
|
489 |
+
|
490 |
+
#ifdef ZEND_ENGINE_3
|
491 |
+
static zend_object *maxminddb_create_handler(
|
492 |
+
zend_class_entry *type TSRMLS_DC)
|
493 |
+
{
|
494 |
+
maxminddb_obj *obj = (maxminddb_obj *)ecalloc(1, sizeof(maxminddb_obj));
|
495 |
+
zend_object_std_init(&obj->std, type TSRMLS_CC);
|
496 |
+
object_properties_init(&(obj->std), type);
|
497 |
+
|
498 |
+
obj->std.handlers = &maxminddb_obj_handlers;
|
499 |
+
|
500 |
+
return &obj->std;
|
501 |
+
}
|
502 |
+
#else
|
503 |
+
static zend_object_value maxminddb_create_handler(
|
504 |
+
zend_class_entry *type TSRMLS_DC)
|
505 |
+
{
|
506 |
+
zend_object_value retval;
|
507 |
+
|
508 |
+
maxminddb_obj *obj = (maxminddb_obj *)ecalloc(1, sizeof(maxminddb_obj));
|
509 |
+
zend_object_std_init(&obj->std, type TSRMLS_CC);
|
510 |
+
object_properties_init(&(obj->std), type);
|
511 |
+
|
512 |
+
retval.handle = zend_objects_store_put(obj, NULL,
|
513 |
+
maxminddb_free_storage,
|
514 |
+
NULL TSRMLS_CC);
|
515 |
+
retval.handlers = &maxminddb_obj_handlers;
|
516 |
+
|
517 |
+
return retval;
|
518 |
+
}
|
519 |
+
#endif
|
520 |
+
|
521 |
+
/* *INDENT-OFF* */
|
522 |
+
static zend_function_entry maxminddb_methods[] = {
|
523 |
+
PHP_ME(MaxMind_Db_Reader, __construct, NULL,
|
524 |
+
ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
|
525 |
+
PHP_ME(MaxMind_Db_Reader, close, NULL, ZEND_ACC_PUBLIC)
|
526 |
+
PHP_ME(MaxMind_Db_Reader, get, NULL, ZEND_ACC_PUBLIC)
|
527 |
+
PHP_ME(MaxMind_Db_Reader, metadata, NULL, ZEND_ACC_PUBLIC)
|
528 |
+
{ NULL, NULL, NULL }
|
529 |
+
};
|
530 |
+
/* *INDENT-ON* */
|
531 |
+
|
532 |
+
PHP_MINIT_FUNCTION(maxminddb){
|
533 |
+
zend_class_entry ce;
|
534 |
+
|
535 |
+
INIT_CLASS_ENTRY(ce, PHP_MAXMINDDB_READER_NS, maxminddb_methods);
|
536 |
+
maxminddb_ce = zend_register_internal_class(&ce TSRMLS_CC);
|
537 |
+
maxminddb_ce->create_object = maxminddb_create_handler;
|
538 |
+
memcpy(&maxminddb_obj_handlers,
|
539 |
+
zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
540 |
+
maxminddb_obj_handlers.clone_obj = NULL;
|
541 |
+
#ifdef ZEND_ENGINE_3
|
542 |
+
maxminddb_obj_handlers.offset = XtOffsetOf(maxminddb_obj, std);
|
543 |
+
maxminddb_obj_handlers.free_obj = maxminddb_free_storage;
|
544 |
+
#endif
|
545 |
+
|
546 |
+
return SUCCESS;
|
547 |
+
}
|
548 |
+
|
549 |
+
zend_module_entry maxminddb_module_entry = {
|
550 |
+
STANDARD_MODULE_HEADER,
|
551 |
+
PHP_MAXMINDDB_EXTNAME,
|
552 |
+
NULL,
|
553 |
+
PHP_MINIT(maxminddb),
|
554 |
+
NULL,
|
555 |
+
NULL,
|
556 |
+
NULL,
|
557 |
+
NULL,
|
558 |
+
PHP_MAXMINDDB_VERSION,
|
559 |
+
STANDARD_MODULE_PROPERTIES
|
560 |
+
};
|
561 |
+
|
562 |
+
#ifdef COMPILE_DL_MAXMINDDB
|
563 |
+
ZEND_GET_MODULE(maxminddb)
|
564 |
+
#endif
|
includes/vendor/maxmind-db/reader/ext/php_maxminddb.h
CHANGED
@@ -1,24 +1,24 @@
|
|
1 |
-
/* MaxMind, Inc., licenses this file to you under the Apache License, Version
|
2 |
-
* 2.0 (the "License"); you may not use this file except in compliance with
|
3 |
-
* the License. You may obtain a copy of the License at
|
4 |
-
*
|
5 |
-
* http://www.apache.org/licenses/LICENSE-2.0
|
6 |
-
*
|
7 |
-
* Unless required by applicable law or agreed to in writing, software
|
8 |
-
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
9 |
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
10 |
-
* License for the specific language governing permissions and limitations
|
11 |
-
* under the License.
|
12 |
-
*/
|
13 |
-
|
14 |
-
#include <zend_interfaces.h>
|
15 |
-
|
16 |
-
#ifndef PHP_MAXMINDDB_H
|
17 |
-
#define PHP_MAXMINDDB_H 1
|
18 |
-
#define PHP_MAXMINDDB_VERSION "1.3.0"
|
19 |
-
#define PHP_MAXMINDDB_EXTNAME "maxminddb"
|
20 |
-
|
21 |
-
extern zend_module_entry maxminddb_module_entry;
|
22 |
-
#define phpext_maxminddb_ptr &maxminddb_module_entry
|
23 |
-
|
24 |
-
#endif
|
1 |
+
/* MaxMind, Inc., licenses this file to you under the Apache License, Version
|
2 |
+
* 2.0 (the "License"); you may not use this file except in compliance with
|
3 |
+
* the License. You may obtain a copy of the License at
|
4 |
+
*
|
5 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
6 |
+
*
|
7 |
+
* Unless required by applicable law or agreed to in writing, software
|
8 |
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
9 |
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
10 |
+
* License for the specific language governing permissions and limitations
|
11 |
+
* under the License.
|
12 |
+
*/
|
13 |
+
|
14 |
+
#include <zend_interfaces.h>
|
15 |
+
|
16 |
+
#ifndef PHP_MAXMINDDB_H
|
17 |
+
#define PHP_MAXMINDDB_H 1
|
18 |
+
#define PHP_MAXMINDDB_VERSION "1.3.0"
|
19 |
+
#define PHP_MAXMINDDB_EXTNAME "maxminddb"
|
20 |
+
|
21 |
+
extern zend_module_entry maxminddb_module_entry;
|
22 |
+
#define phpext_maxminddb_ptr &maxminddb_module_entry
|
23 |
+
|
24 |
+
#endif
|
includes/vendor/maxmind-db/reader/ext/tests/001-load.phpt
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
-
--TEST--
|
2 |
-
Check for maxminddb presence
|
3 |
-
--SKIPIF--
|
4 |
-
<?php if (!extension_loaded('maxminddb')) {
|
5 |
-
echo 'skip';
|
6 |
-
} ?>
|
7 |
-
--FILE--
|
8 |
-
<?php
|
9 |
-
echo 'maxminddb extension is available';
|
10 |
-
?>
|
11 |
-
--EXPECT--
|
12 |
-
maxminddb extension is available
|
1 |
+
--TEST--
|
2 |
+
Check for maxminddb presence
|
3 |
+
--SKIPIF--
|
4 |
+
<?php if (!extension_loaded('maxminddb')) {
|
5 |
+
echo 'skip';
|
6 |
+
} ?>
|
7 |
+
--FILE--
|
8 |
+
<?php
|
9 |
+
echo 'maxminddb extension is available';
|
10 |
+
?>
|
11 |
+
--EXPECT--
|
12 |
+
maxminddb extension is available
|
includes/vendor/maxmind-db/reader/ext/tests/002-final.phpt
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
-
--TEST--
|
2 |
-
Check that Reader class is not final
|
3 |
-
--SKIPIF--
|
4 |
-
<?php if (!extension_loaded('maxminddb')) {
|
5 |
-
echo 'skip';
|
6 |
-
} ?>
|
7 |
-
--FILE--
|
8 |
-
<?php
|
9 |
-
$reflectionClass = new \ReflectionClass('MaxMind\Db\Reader');
|
10 |
-
var_dump($reflectionClass->isFinal());
|
11 |
-
?>
|
12 |
-
--EXPECT--
|
13 |
-
bool(false)
|
1 |
+
--TEST--
|
2 |
+
Check that Reader class is not final
|
3 |
+
--SKIPIF--
|
4 |
+
<?php if (!extension_loaded('maxminddb')) {
|
5 |
+
echo 'skip';
|
6 |
+
} ?>
|
7 |
+
--FILE--
|
8 |
+
<?php
|
9 |
+
$reflectionClass = new \ReflectionClass('MaxMind\Db\Reader');
|
10 |
+
var_dump($reflectionClass->isFinal());
|
11 |
+
?>
|
12 |
+
--EXPECT--
|
13 |
+
bool(false)
|
includes/vendor/maxmind-db/reader/ext/tests/003-open-basedir.phpt
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
-
--TEST--
|
2 |
-
openbase_dir is followed
|
3 |
-
--INI--
|
4 |
-
open_basedir=/--dne--
|
5 |
-
--FILE--
|
6 |
-
<?php
|
7 |
-
use MaxMind\Db\Reader;
|
8 |
-
|
9 |
-
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-City.mmdb');
|
10 |
-
?>
|
11 |
-
--EXPECTREGEX--
|
12 |
-
.*open_basedir restriction in effect.*
|
1 |
+
--TEST--
|
2 |
+
openbase_dir is followed
|
3 |
+
--INI--
|
4 |
+
open_basedir=/--dne--
|
5 |
+
--FILE--
|
6 |
+
<?php
|
7 |
+
use MaxMind\Db\Reader;
|
8 |
+
|
9 |
+
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-City.mmdb');
|
10 |
+
?>
|
11 |
+
--EXPECTREGEX--
|
12 |
+
.*open_basedir restriction in effect.*
|
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php
CHANGED
@@ -1,309 +1,309 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Db;
|
4 |
-
|
5 |
-
use MaxMind\Db\Reader\Decoder;
|
6 |
-
use MaxMind\Db\Reader\InvalidDatabaseException;
|
7 |
-
use MaxMind\Db\Reader\Metadata;
|
8 |
-
use MaxMind\Db\Reader\Util;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Instances of this class provide a reader for the MaxMind DB format. IP
|
12 |
-
* addresses can be looked up using the <code>get</code> method.
|
13 |
-
*/
|
14 |
-
class Reader
|
15 |
-
{
|
16 |
-
private static $DATA_SECTION_SEPARATOR_SIZE = 16;
|
17 |
-
private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com";
|
18 |
-
private static $METADATA_START_MARKER_LENGTH = 14;
|
19 |
-
private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KB
|
20 |
-
|
21 |
-
private $decoder;
|
22 |
-
private $fileHandle;
|
23 |
-
private $fileSize;
|
24 |
-
private $ipV4Start;
|
25 |
-
private $metadata;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Constructs a Reader for the MaxMind DB format. The file passed to it must
|
29 |
-
* be a valid MaxMind DB file such as a GeoIp2 database file.
|
30 |
-
*
|
31 |
-
* @param string $database
|
32 |
-
* the MaxMind DB file to use
|
33 |
-
*
|
34 |
-
* @throws \InvalidArgumentException for invalid database path or unknown arguments
|
35 |
-
* @throws \MaxMind\Db\Reader\InvalidDatabaseException
|
36 |
-
* if the database is invalid or there is an error reading
|
37 |
-
* from it
|
38 |
-
*/
|
39 |
-
public function __construct($database)
|
40 |
-
{
|
41 |
-
if (func_num_args() !== 1) {
|
42 |
-
throw new \InvalidArgumentException(
|
43 |
-
'The constructor takes exactly one argument.'
|
44 |
-
);
|
45 |
-
}
|
46 |
-
|
47 |
-
if (!is_readable($database)) {
|
48 |
-
throw new \InvalidArgumentException(
|
49 |
-
"The file \"$database\" does not exist or is not readable."
|
50 |
-
);
|
51 |
-
}
|
52 |
-
$this->fileHandle = @fopen($database, 'rb');
|
53 |
-
if ($this->fileHandle === false) {
|
54 |
-
throw new \InvalidArgumentException(
|
55 |
-
"Error opening \"$database\"."
|
56 |
-
);
|
57 |
-
}
|
58 |
-
$this->fileSize = @filesize($database);
|
59 |
-
if ($this->fileSize === false) {
|
60 |
-
throw new \UnexpectedValueException(
|
61 |
-
"Error determining the size of \"$database\"."
|
62 |
-
);
|
63 |
-
}
|
64 |
-
|
65 |
-
$start = $this->findMetadataStart($database);
|
66 |
-
$metadataDecoder = new Decoder($this->fileHandle, $start);
|
67 |
-
list($metadataArray) = $metadataDecoder->decode($start);
|
68 |
-
$this->metadata = new Metadata($metadataArray);
|
69 |
-
$this->decoder = new Decoder(
|
70 |
-
$this->fileHandle,
|
71 |
-
$this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
|
72 |
-
);
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Looks up the <code>address</code> in the MaxMind DB.
|
77 |
-
*
|
78 |
-
* @param string $ipAddress
|
79 |
-
* the IP address to look up
|
80 |
-
*
|
81 |
-
* @throws \BadMethodCallException if this method is called on a closed database
|
82 |
-
* @throws \InvalidArgumentException if something other than a single IP address is passed to the method
|
83 |
-
* @throws InvalidDatabaseException
|
84 |
-
* if the database is invalid or there is an error reading
|
85 |
-
* from it
|
86 |
-
*
|
87 |
-
* @return array the record for the IP address
|
88 |
-
*/
|
89 |
-
public function get($ipAddress)
|
90 |
-
{
|
91 |
-
if (func_num_args() !== 1) {
|
92 |
-
throw new \InvalidArgumentException(
|
93 |
-
'Method takes exactly one argument.'
|
94 |
-
);
|
95 |
-
}
|
96 |
-
|
97 |
-
if (!is_resource($this->fileHandle)) {
|
98 |
-
throw new \BadMethodCallException(
|
99 |
-
'Attempt to read from a closed MaxMind DB.'
|
100 |
-
);
|
101 |
-
}
|
102 |
-
|
103 |
-
if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
|
104 |
-
throw new \InvalidArgumentException(
|
105 |
-
"The value \"$ipAddress\" is not a valid IP address."
|
106 |
-
);
|
107 |
-
}
|
108 |
-
|
109 |
-
if ($this->metadata->ipVersion === 4 && strrpos($ipAddress, ':')) {
|
110 |
-
throw new \InvalidArgumentException(
|
111 |
-
"Error looking up $ipAddress. You attempted to look up an"
|
112 |
-
. ' IPv6 address in an IPv4-only database.'
|
113 |
-
);
|
114 |
-
}
|
115 |
-
$pointer = $this->findAddressInTree($ipAddress);
|
116 |
-
if ($pointer === 0) {
|
117 |
-
return null;
|
118 |
-
}
|
119 |
-
|
120 |
-
return $this->resolveDataPointer($pointer);
|
121 |
-
}
|
122 |
-
|
123 |
-
private function findAddressInTree($ipAddress)
|
124 |
-
{
|
125 |
-
// XXX - could simplify. Done as a byte array to ease porting
|
126 |
-
$rawAddress = array_merge(unpack('C*', inet_pton($ipAddress)));
|
127 |
-
|
128 |
-
$bitCount = count($rawAddress) * 8;
|
129 |
-
|
130 |
-
// The first node of the tree is always node 0, at the beginning of the
|
131 |
-
// value
|
132 |
-
$node = $this->startNode($bitCount);
|
133 |
-
|
134 |
-
for ($i = 0; $i < $bitCount; $i++) {
|
135 |
-
if ($node >= $this->metadata->nodeCount) {
|
136 |
-
break;
|
137 |
-
}
|
138 |
-
$tempBit = 0xFF & $rawAddress[$i >> 3];
|
139 |
-
$bit = 1 & ($tempBit >> 7 - ($i % 8));
|
140 |
-
|
141 |
-
$node = $this->readNode($node, $bit);
|
142 |
-
}
|
143 |
-
if ($node === $this->metadata->nodeCount) {
|
144 |
-
// Record is empty
|
145 |
-
return 0;
|
146 |
-
} elseif ($node > $this->metadata->nodeCount) {
|
147 |
-
// Record is a data pointer
|
148 |
-
return $node;
|
149 |
-
}
|
150 |
-
throw new InvalidDatabaseException('Something bad happened');
|
151 |
-
}
|
152 |
-
|
153 |
-
private function startNode($length)
|
154 |
-
{
|
155 |
-
// Check if we are looking up an IPv4 address in an IPv6 tree. If this
|
156 |
-
// is the case, we can skip over the first 96 nodes.
|
157 |
-
if ($this->metadata->ipVersion === 6 && $length === 32) {
|
158 |
-
return $this->ipV4StartNode();
|
159 |
-
}
|
160 |
-
// The first node of the tree is always node 0, at the beginning of the
|
161 |
-
// value
|
162 |
-
return 0;
|
163 |
-
}
|
164 |
-
|
165 |
-
private function ipV4StartNode()
|
166 |
-
{
|
167 |
-
// This is a defensive check. There is no reason to call this when you
|
168 |
-
// have an IPv4 tree.
|
169 |
-
if ($this->metadata->ipVersion === 4) {
|
170 |
-
return 0;
|
171 |
-
}
|
172 |
-
|
173 |
-
if ($this->ipV4Start) {
|
174 |
-
return $this->ipV4Start;
|
175 |
-
}
|
176 |
-
$node = 0;
|
177 |
-
|
178 |
-
for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; $i++) {
|
179 |
-
$node = $this->readNode($node, 0);
|
180 |
-
}
|
181 |
-
$this->ipV4Start = $node;
|
182 |
-
|
183 |
-
return $node;
|
184 |
-
}
|
185 |
-
|
186 |
-
private function readNode($nodeNumber, $index)
|
187 |
-
{
|
188 |
-
$baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
|
189 |
-
|
190 |
-
// XXX - probably could condense this.
|
191 |
-
switch ($this->metadata->recordSize) {
|
192 |
-
case 24:
|
193 |
-
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
|
194 |
-
list(, $node) = unpack('N', "\x00" . $bytes);
|
195 |
-
|
196 |
-
return $node;
|
197 |
-
case 28:
|
198 |
-
$middleByte = Util::read($this->fileHandle, $baseOffset + 3, 1);
|
199 |
-
list(, $middle) = unpack('C', $middleByte);
|
200 |
-
if ($index === 0) {
|
201 |
-
$middle = (0xF0 & $middle) >> 4;
|
202 |
-
} else {
|
203 |
-
$middle = 0x0F & $middle;
|
204 |
-
}
|
205 |
-
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 3);
|
206 |
-
list(, $node) = unpack('N', chr($middle) . $bytes);
|
207 |
-
|
208 |
-
return $node;
|
209 |
-
case 32:
|
210 |
-
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
|
211 |
-
list(, $node) = unpack('N', $bytes);
|
212 |
-
|
213 |
-
return $node;
|
214 |
-
default:
|
215 |
-
throw new InvalidDatabaseException(
|
216 |
-
'Unknown record size: '
|
217 |
-
. $this->metadata->recordSize
|
218 |
-
);
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
private function resolveDataPointer($pointer)
|
223 |
-
{
|
224 |
-
$resolved = $pointer - $this->metadata->nodeCount
|
225 |
-
+ $this->metadata->searchTreeSize;
|
226 |
-
if ($resolved > $this->fileSize) {
|
227 |
-
throw new InvalidDatabaseException(
|
228 |
-
"The MaxMind DB file's search tree is corrupt"
|
229 |
-
);
|
230 |
-
}
|
231 |
-
|
232 |
-
list($data) = $this->decoder->decode($resolved);
|
233 |
-
|
234 |
-
return $data;
|
235 |
-
}
|
236 |
-
|
237 |
-
/*
|
238 |
-
* This is an extremely naive but reasonably readable implementation. There
|
239 |
-
* are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
|
240 |
-
* an issue, but I suspect it won't be.
|
241 |
-
*/
|
242 |
-
private function findMetadataStart($filename)
|
243 |
-
{
|
244 |
-
$handle = $this->fileHandle;
|
245 |
-
$fstat = fstat($handle);
|
246 |
-
$fileSize = $fstat['size'];
|
247 |
-
$marker = self::$METADATA_START_MARKER;
|
248 |
-
$markerLength = self::$METADATA_START_MARKER_LENGTH;
|
249 |
-
$metadataMaxLengthExcludingMarker
|
250 |
-
= min(self::$METADATA_MAX_SIZE, $fileSize) - $markerLength;
|
251 |
-
|
252 |
-
for ($i = 0; $i <= $metadataMaxLengthExcludingMarker; $i++) {
|
253 |
-
for ($j = 0; $j < $markerLength; $j++) {
|
254 |
-
fseek($handle, $fileSize - $i - $j - 1);
|
255 |
-
$matchBit = fgetc($handle);
|
256 |
-
if ($matchBit !== $marker[$markerLength - $j - 1]) {
|
257 |
-
continue 2;
|
258 |
-
}
|
259 |
-
}
|
260 |
-
|
261 |
-
return $fileSize - $i;
|
262 |
-
}
|
263 |
-
throw new InvalidDatabaseException(
|
264 |
-
"Error opening database file ($filename). " .
|
265 |
-
'Is this a valid MaxMind DB file?'
|
266 |
-
);
|
267 |
-
}
|
268 |
-
|
269 |
-
/**
|
270 |
-
* @throws \InvalidArgumentException if arguments are passed to the method
|
271 |
-
* @throws \BadMethodCallException if the database has been closed
|
272 |
-
*
|
273 |
-
* @return Metadata object for the database
|
274 |
-
*/
|
275 |
-
public function metadata()
|
276 |
-
{
|
277 |
-
if (func_num_args()) {
|
278 |
-
throw new \InvalidArgumentException(
|
279 |
-
'Method takes no arguments.'
|
280 |
-
);
|
281 |
-
}
|
282 |
-
|
283 |
-
// Not technically required, but this makes it consistent with
|
284 |
-
// C extension and it allows us to change our implementation later.
|
285 |
-
if (!is_resource($this->fileHandle)) {
|
286 |
-
throw new \BadMethodCallException(
|
287 |
-
'Attempt to read from a closed MaxMind DB.'
|
288 |
-
);
|
289 |
-
}
|
290 |
-
|
291 |
-
return $this->metadata;
|
292 |
-
}
|
293 |
-
|
294 |
-
/**
|
295 |
-
* Closes the MaxMind DB and returns resources to the system.
|
296 |
-
*
|
297 |
-
* @throws \Exception
|
298 |
-
* if an I/O error occurs
|
299 |
-
*/
|
300 |
-
public function close()
|
301 |
-
{
|
302 |
-
if (!is_resource($this->fileHandle)) {
|
303 |
-
throw new \BadMethodCallException(
|
304 |
-
'Attempt to close a closed MaxMind DB.'
|
305 |
-
);
|
306 |
-
}
|
307 |
-
fclose($this->fileHandle);
|
308 |
-
}
|
309 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Db;
|
4 |
+
|
5 |
+
use MaxMind\Db\Reader\Decoder;
|
6 |
+
use MaxMind\Db\Reader\InvalidDatabaseException;
|
7 |
+
use MaxMind\Db\Reader\Metadata;
|
8 |
+
use MaxMind\Db\Reader\Util;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Instances of this class provide a reader for the MaxMind DB format. IP
|
12 |
+
* addresses can be looked up using the <code>get</code> method.
|
13 |
+
*/
|
14 |
+
class Reader
|
15 |
+
{
|
16 |
+
private static $DATA_SECTION_SEPARATOR_SIZE = 16;
|
17 |
+
private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com";
|
18 |
+
private static $METADATA_START_MARKER_LENGTH = 14;
|
19 |
+
private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KB
|
20 |
+
|
21 |
+
private $decoder;
|
22 |
+
private $fileHandle;
|
23 |
+
private $fileSize;
|
24 |
+
private $ipV4Start;
|
25 |
+
private $metadata;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Constructs a Reader for the MaxMind DB format. The file passed to it must
|
29 |
+
* be a valid MaxMind DB file such as a GeoIp2 database file.
|
30 |
+
*
|
31 |
+
* @param string $database
|
32 |
+
* the MaxMind DB file to use
|
33 |
+
*
|
34 |
+
* @throws \InvalidArgumentException for invalid database path or unknown arguments
|
35 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException
|
36 |
+
* if the database is invalid or there is an error reading
|
37 |
+
* from it
|
38 |
+
*/
|
39 |
+
public function __construct($database)
|
40 |
+
{
|
41 |
+
if (func_num_args() !== 1) {
|
42 |
+
throw new \InvalidArgumentException(
|
43 |
+
'The constructor takes exactly one argument.'
|
44 |
+
);
|
45 |
+
}
|
46 |
+
|
47 |
+
if (!is_readable($database)) {
|
48 |
+
throw new \InvalidArgumentException(
|
49 |
+
"The file \"$database\" does not exist or is not readable."
|
50 |
+
);
|
51 |
+
}
|
52 |
+
$this->fileHandle = @fopen($database, 'rb');
|
53 |
+
if ($this->fileHandle === false) {
|
54 |
+
throw new \InvalidArgumentException(
|
55 |
+
"Error opening \"$database\"."
|
56 |
+
);
|
57 |
+
}
|
58 |
+
$this->fileSize = @filesize($database);
|
59 |
+
if ($this->fileSize === false) {
|
60 |
+
throw new \UnexpectedValueException(
|
61 |
+
"Error determining the size of \"$database\"."
|
62 |
+
);
|
63 |
+
}
|
64 |
+
|
65 |
+
$start = $this->findMetadataStart($database);
|
66 |
+
$metadataDecoder = new Decoder($this->fileHandle, $start);
|
67 |
+
list($metadataArray) = $metadataDecoder->decode($start);
|
68 |
+
$this->metadata = new Metadata($metadataArray);
|
69 |
+
$this->decoder = new Decoder(
|
70 |
+
$this->fileHandle,
|
71 |
+
$this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
|
72 |
+
);
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Looks up the <code>address</code> in the MaxMind DB.
|
77 |
+
*
|
78 |
+
* @param string $ipAddress
|
79 |
+
* the IP address to look up
|
80 |
+
*
|
81 |
+
* @throws \BadMethodCallException if this method is called on a closed database
|
82 |
+
* @throws \InvalidArgumentException if something other than a single IP address is passed to the method
|
83 |
+
* @throws InvalidDatabaseException
|
84 |
+
* if the database is invalid or there is an error reading
|
85 |
+
* from it
|
86 |
+
*
|
87 |
+
* @return array the record for the IP address
|
88 |
+
*/
|
89 |
+
public function get($ipAddress)
|
90 |
+
{
|
91 |
+
if (func_num_args() !== 1) {
|
92 |
+
throw new \InvalidArgumentException(
|
93 |
+
'Method takes exactly one argument.'
|
94 |
+
);
|
95 |
+
}
|
96 |
+
|
97 |
+
if (!is_resource($this->fileHandle)) {
|
98 |
+
throw new \BadMethodCallException(
|
99 |
+
'Attempt to read from a closed MaxMind DB.'
|
100 |
+
);
|
101 |
+
}
|
102 |
+
|
103 |
+
if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
|
104 |
+
throw new \InvalidArgumentException(
|
105 |
+
"The value \"$ipAddress\" is not a valid IP address."
|
106 |
+
);
|
107 |
+
}
|
108 |
+
|
109 |
+
if ($this->metadata->ipVersion === 4 && strrpos($ipAddress, ':')) {
|
110 |
+
throw new \InvalidArgumentException(
|
111 |
+
"Error looking up $ipAddress. You attempted to look up an"
|
112 |
+
. ' IPv6 address in an IPv4-only database.'
|
113 |
+
);
|
114 |
+
}
|
115 |
+
$pointer = $this->findAddressInTree($ipAddress);
|
116 |
+
if ($pointer === 0) {
|
117 |
+
return null;
|
118 |
+
}
|
119 |
+
|
120 |
+
return $this->resolveDataPointer($pointer);
|
121 |
+
}
|
122 |
+
|
123 |
+
private function findAddressInTree($ipAddress)
|
124 |
+
{
|
125 |
+
// XXX - could simplify. Done as a byte array to ease porting
|
126 |
+
$rawAddress = array_merge(unpack('C*', inet_pton($ipAddress)));
|
127 |
+
|
128 |
+
$bitCount = count($rawAddress) * 8;
|
129 |
+
|
130 |
+
// The first node of the tree is always node 0, at the beginning of the
|
131 |
+
// value
|
132 |
+
$node = $this->startNode($bitCount);
|
133 |
+
|
134 |
+
for ($i = 0; $i < $bitCount; $i++) {
|
135 |
+
if ($node >= $this->metadata->nodeCount) {
|
136 |
+
break;
|
137 |
+
}
|
138 |
+
$tempBit = 0xFF & $rawAddress[$i >> 3];
|
139 |
+
$bit = 1 & ($tempBit >> 7 - ($i % 8));
|
140 |
+
|
141 |
+
$node = $this->readNode($node, $bit);
|
142 |
+
}
|
143 |
+
if ($node === $this->metadata->nodeCount) {
|
144 |
+
// Record is empty
|
145 |
+
return 0;
|
146 |
+
} elseif ($node > $this->metadata->nodeCount) {
|
147 |
+
// Record is a data pointer
|
148 |
+
return $node;
|
149 |
+
}
|
150 |
+
throw new InvalidDatabaseException('Something bad happened');
|
151 |
+
}
|
152 |
+
|
153 |
+
private function startNode($length)
|
154 |
+
{
|
155 |
+
// Check if we are looking up an IPv4 address in an IPv6 tree. If this
|
156 |
+
// is the case, we can skip over the first 96 nodes.
|
157 |
+
if ($this->metadata->ipVersion === 6 && $length === 32) {
|
158 |
+
return $this->ipV4StartNode();
|
159 |
+
}
|
160 |
+
// The first node of the tree is always node 0, at the beginning of the
|
161 |
+
// value
|
162 |
+
return 0;
|
163 |
+
}
|
164 |
+
|
165 |
+
private function ipV4StartNode()
|
166 |
+
{
|
167 |
+
// This is a defensive check. There is no reason to call this when you
|
168 |
+
// have an IPv4 tree.
|
169 |
+
if ($this->metadata->ipVersion === 4) {
|
170 |
+
return 0;
|
171 |
+
}
|
172 |
+
|
173 |
+
if ($this->ipV4Start) {
|
174 |
+
return $this->ipV4Start;
|
175 |
+
}
|
176 |
+
$node = 0;
|
177 |
+
|
178 |
+
for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; $i++) {
|
179 |
+
$node = $this->readNode($node, 0);
|
180 |
+
}
|
181 |
+
$this->ipV4Start = $node;
|
182 |
+
|
183 |
+
return $node;
|
184 |
+
}
|
185 |
+
|
186 |
+
private function readNode($nodeNumber, $index)
|
187 |
+
{
|
188 |
+
$baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
|
189 |
+
|
190 |
+
// XXX - probably could condense this.
|
191 |
+
switch ($this->metadata->recordSize) {
|
192 |
+
case 24:
|
193 |
+
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
|
194 |
+
list(, $node) = unpack('N', "\x00" . $bytes);
|
195 |
+
|
196 |
+
return $node;
|
197 |
+
case 28:
|
198 |
+
$middleByte = Util::read($this->fileHandle, $baseOffset + 3, 1);
|
199 |
+
list(, $middle) = unpack('C', $middleByte);
|
200 |
+
if ($index === 0) {
|
201 |
+
$middle = (0xF0 & $middle) >> 4;
|
202 |
+
} else {
|
203 |
+
$middle = 0x0F & $middle;
|
204 |
+
}
|
205 |
+
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 3);
|
206 |
+
list(, $node) = unpack('N', chr($middle) . $bytes);
|
207 |
+
|
208 |
+
return $node;
|
209 |
+
case 32:
|
210 |
+
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
|
211 |
+
list(, $node) = unpack('N', $bytes);
|
212 |
+
|
213 |
+
return $node;
|
214 |
+
default:
|
215 |
+
throw new InvalidDatabaseException(
|
216 |
+
'Unknown record size: '
|
217 |
+
. $this->metadata->recordSize
|
218 |
+
);
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
private function resolveDataPointer($pointer)
|
223 |
+
{
|
224 |
+
$resolved = $pointer - $this->metadata->nodeCount
|
225 |
+
+ $this->metadata->searchTreeSize;
|
226 |
+
if ($resolved > $this->fileSize) {
|
227 |
+
throw new InvalidDatabaseException(
|
228 |
+
"The MaxMind DB file's search tree is corrupt"
|
229 |
+
);
|
230 |
+
}
|
231 |
+
|
232 |
+
list($data) = $this->decoder->decode($resolved);
|
233 |
+
|
234 |
+
return $data;
|
235 |
+
}
|
236 |
+
|
237 |
+
/*
|
238 |
+
* This is an extremely naive but reasonably readable implementation. There
|
239 |
+
* are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
|
240 |
+
* an issue, but I suspect it won't be.
|
241 |
+
*/
|
242 |
+
private function findMetadataStart($filename)
|
243 |
+
{
|
244 |
+
$handle = $this->fileHandle;
|
245 |
+
$fstat = fstat($handle);
|
246 |
+
$fileSize = $fstat['size'];
|
247 |
+
$marker = self::$METADATA_START_MARKER;
|
248 |
+
$markerLength = self::$METADATA_START_MARKER_LENGTH;
|
249 |
+
$metadataMaxLengthExcludingMarker
|
250 |
+
= min(self::$METADATA_MAX_SIZE, $fileSize) - $markerLength;
|
251 |
+
|
252 |
+
for ($i = 0; $i <= $metadataMaxLengthExcludingMarker; $i++) {
|
253 |
+
for ($j = 0; $j < $markerLength; $j++) {
|
254 |
+
fseek($handle, $fileSize - $i - $j - 1);
|
255 |
+
$matchBit = fgetc($handle);
|
256 |
+
if ($matchBit !== $marker[$markerLength - $j - 1]) {
|
257 |
+
continue 2;
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
return $fileSize - $i;
|
262 |
+
}
|
263 |
+
throw new InvalidDatabaseException(
|
264 |
+
"Error opening database file ($filename). " .
|
265 |
+
'Is this a valid MaxMind DB file?'
|
266 |
+
);
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* @throws \InvalidArgumentException if arguments are passed to the method
|
271 |
+
* @throws \BadMethodCallException if the database has been closed
|
272 |
+
*
|
273 |
+
* @return Metadata object for the database
|
274 |
+
*/
|
275 |
+
public function metadata()
|
276 |
+
{
|
277 |
+
if (func_num_args()) {
|
278 |
+
throw new \InvalidArgumentException(
|
279 |
+
'Method takes no arguments.'
|
280 |
+
);
|
281 |
+
}
|
282 |
+
|
283 |
+
// Not technically required, but this makes it consistent with
|
284 |
+
// C extension and it allows us to change our implementation later.
|
285 |
+
if (!is_resource($this->fileHandle)) {
|
286 |
+
throw new \BadMethodCallException(
|
287 |
+
'Attempt to read from a closed MaxMind DB.'
|
288 |
+
);
|
289 |
+
}
|
290 |
+
|
291 |
+
return $this->metadata;
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* Closes the MaxMind DB and returns resources to the system.
|
296 |
+
*
|
297 |
+
* @throws \Exception
|
298 |
+
* if an I/O error occurs
|
299 |
+
*/
|
300 |
+
public function close()
|
301 |
+
{
|
302 |
+
if (!is_resource($this->fileHandle)) {
|
303 |
+
throw new \BadMethodCallException(
|
304 |
+
'Attempt to close a closed MaxMind DB.'
|
305 |
+
);
|
306 |
+
}
|
307 |
+
fclose($this->fileHandle);
|
308 |
+
}
|
309 |
+
}
|
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php
CHANGED
@@ -1,311 +1,311 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Db\Reader;
|
4 |
-
|
5 |
-
class Decoder
|
6 |
-
{
|
7 |
-
private $fileStream;
|
8 |
-
private $pointerBase;
|
9 |
-
// This is only used for unit testing
|
10 |
-
private $pointerTestHack;
|
11 |
-
private $switchByteOrder;
|
12 |
-
|
13 |
-
private $types = [
|
14 |
-
0 => 'extended',
|
15 |
-
1 => 'pointer',
|
16 |
-
2 => 'utf8_string',
|
17 |
-
3 => 'double',
|
18 |
-
4 => 'bytes',
|
19 |
-
5 => 'uint16',
|
20 |
-
6 => 'uint32',
|
21 |
-
7 => 'map',
|
22 |
-
8 => 'int32',
|
23 |
-
9 => 'uint64',
|
24 |
-
10 => 'uint128',
|
25 |
-
11 => 'array',
|
26 |
-
12 => 'container',
|
27 |
-
13 => 'end_marker',
|
28 |
-
14 => 'boolean',
|
29 |
-
15 => 'float',
|
30 |
-
];
|
31 |
-
|
32 |
-
public function __construct(
|
33 |
-
$fileStream,
|
34 |
-
$pointerBase = 0,
|
35 |
-
$pointerTestHack = false
|
36 |
-
) {
|
37 |
-
$this->fileStream = $fileStream;
|
38 |
-
$this->pointerBase = $pointerBase;
|
39 |
-
$this->pointerTestHack = $pointerTestHack;
|
40 |
-
|
41 |
-
$this->switchByteOrder = $this->isPlatformLittleEndian();
|
42 |
-
}
|
43 |
-
|
44 |
-
public function decode($offset)
|
45 |
-
{
|
46 |
-
list(, $ctrlByte) = unpack(
|
47 |
-
'C',
|
48 |
-
Util::read($this->fileStream, $offset, 1)
|
49 |
-
);
|
50 |
-
$offset++;
|
51 |
-
|
52 |
-
$type = $this->types[$ctrlByte >> 5];
|
53 |
-
|
54 |
-
// Pointers are a special case, we don't read the next $size bytes, we
|
55 |
-
// use the size to determine the length of the pointer and then follow
|
56 |
-
// it.
|
57 |
-
if ($type === 'pointer') {
|
58 |
-
list($pointer, $offset) = $this->decodePointer($ctrlByte, $offset);
|
59 |
-
|
60 |
-
// for unit testing
|
61 |
-
if ($this->pointerTestHack) {
|
62 |
-
return [$pointer];
|
63 |
-
}
|
64 |
-
|
65 |
-
list($result) = $this->decode($pointer);
|
66 |
-
|
67 |
-
return [$result, $offset];
|
68 |
-
}
|
69 |
-
|
70 |
-
if ($type === 'extended') {
|
71 |
-
list(, $nextByte) = unpack(
|
72 |
-
'C',
|
73 |
-
Util::read($this->fileStream, $offset, 1)
|
74 |
-
);
|
75 |
-
|
76 |
-
$typeNum = $nextByte + 7;
|
77 |
-
|
78 |
-
if ($typeNum < 8) {
|
79 |
-
throw new InvalidDatabaseException(
|
80 |
-
'Something went horribly wrong in the decoder. An extended type '
|
81 |
-
. 'resolved to a type number < 8 ('
|
82 |
-
. $this->types[$typeNum]
|
83 |
-
. ')'
|
84 |
-
);
|
85 |
-
}
|
86 |
-
|
87 |
-
$type = $this->types[$typeNum];
|
88 |
-
$offset++;
|
89 |
-
}
|
90 |
-
|
91 |
-
list($size, $offset) = $this->sizeFromCtrlByte($ctrlByte, $offset);
|
92 |
-
|
93 |
-
return $this->decodeByType($type, $offset, $size);
|
94 |
-
}
|
95 |
-
|
96 |
-
private function decodeByType($type, $offset, $size)
|
97 |
-
{
|
98 |
-
switch ($type) {
|
99 |
-
case 'map':
|
100 |
-
return $this->decodeMap($size, $offset);
|
101 |
-
case 'array':
|
102 |
-
return $this->decodeArray($size, $offset);
|
103 |
-
case 'boolean':
|
104 |
-
return [$this->decodeBoolean($size), $offset];
|
105 |
-
}
|
106 |
-
|
107 |
-
$newOffset = $offset + $size;
|
108 |
-
$bytes = Util::read($this->fileStream, $offset, $size);
|
109 |
-
switch ($type) {
|
110 |
-
case 'utf8_string':
|
111 |
-
return [$this->decodeString($bytes), $newOffset];
|
112 |
-
case 'double':
|
113 |
-
$this->verifySize(8, $size);
|
114 |
-
|
115 |
-
return [$this->decodeDouble($bytes), $newOffset];
|
116 |
-
case 'float':
|
117 |
-
$this->verifySize(4, $size);
|
118 |
-
|
119 |
-
return [$this->decodeFloat($bytes), $newOffset];
|
120 |
-
case 'bytes':
|
121 |
-
return [$bytes, $newOffset];
|
122 |
-
case 'uint16':
|
123 |
-
case 'uint32':
|
124 |
-
return [$this->decodeUint($bytes), $newOffset];
|
125 |
-
case 'int32':
|
126 |
-
return [$this->decodeInt32($bytes), $newOffset];
|
127 |
-
case 'uint64':
|
128 |
-
case 'uint128':
|
129 |
-
return [$this->decodeBigUint($bytes, $size), $newOffset];
|
130 |
-
default:
|
131 |
-
throw new InvalidDatabaseException(
|
132 |
-
'Unknown or unexpected type: ' . $type
|
133 |
-
);
|
134 |
-
}
|
135 |
-
}
|
136 |
-
|
137 |
-
private function verifySize($expected, $actual)
|
138 |
-
{
|
139 |
-
if ($expected !== $actual) {
|
140 |
-
throw new InvalidDatabaseException(
|
141 |
-
"The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
|
142 |
-
);
|
143 |
-
}
|
144 |
-
}
|
145 |
-
|
146 |
-
private function decodeArray($size, $offset)
|
147 |
-
{
|
148 |
-
$array = [];
|
149 |
-
|
150 |
-
for ($i = 0; $i < $size; $i++) {
|
151 |
-
list($value, $offset) = $this->decode($offset);
|
152 |
-
array_push($array, $value);
|
153 |
-
}
|
154 |
-
|
155 |
-
return [$array, $offset];
|
156 |
-
}
|
157 |
-
|
158 |
-
private function decodeBoolean($size)
|
159 |
-
{
|
160 |
-
return $size === 0 ? false : true;
|
161 |
-
}
|
162 |
-
|
163 |
-
private function decodeDouble($bits)
|
164 |
-
{
|
165 |
-
// XXX - Assumes IEEE 754 double on platform
|
166 |
-
list(, $double) = unpack('d', $this->maybeSwitchByteOrder($bits));
|
167 |
-
|
168 |
-
return $double;
|
169 |
-
}
|
170 |
-
|
171 |
-
private function decodeFloat($bits)
|
172 |
-
{
|
173 |
-
// XXX - Assumes IEEE 754 floats on platform
|
174 |
-
list(, $float) = unpack('f', $this->maybeSwitchByteOrder($bits));
|
175 |
-
|
176 |
-
return $float;
|
177 |
-
}
|
178 |
-
|
179 |
-
private function decodeInt32($bytes)
|
180 |
-
{
|
181 |
-
$bytes = $this->zeroPadLeft($bytes, 4);
|
182 |
-
list(, $int) = unpack('l', $this->maybeSwitchByteOrder($bytes));
|
183 |
-
|
184 |
-
return $int;
|
185 |
-
}
|
186 |
-
|
187 |
-
private function decodeMap($size, $offset)
|
188 |
-
{
|
189 |
-
$map = [];
|
190 |
-
|
191 |
-
for ($i = 0; $i < $size; $i++) {
|
192 |
-
list($key, $offset) = $this->decode($offset);
|
193 |
-
list($value, $offset) = $this->decode($offset);
|
194 |
-
$map[$key] = $value;
|
195 |
-
}
|
196 |
-
|
197 |
-
return [$map, $offset];
|
198 |
-
}
|
199 |
-
|
200 |
-
private $pointerValueOffset = [
|
201 |
-
1 => 0,
|
202 |
-
2 => 2048,
|
203 |
-
3 => 526336,
|
204 |
-
4 => 0,
|
205 |
-
];
|
206 |
-
|
207 |
-
private function decodePointer($ctrlByte, $offset)
|
208 |
-
{
|
209 |
-
$pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
|
210 |
-
|
211 |
-
$buffer = Util::read($this->fileStream, $offset, $pointerSize);
|
212 |
-
$offset = $offset + $pointerSize;
|
213 |
-
|
214 |
-
$packed = $pointerSize === 4
|
215 |
-
? $buffer
|
216 |
-
: (pack('C', $ctrlByte & 0x7)) . $buffer;
|
217 |
-
|
218 |
-
$unpacked = $this->decodeUint($packed);
|
219 |
-
$pointer = $unpacked + $this->pointerBase
|
220 |
-
+ $this->pointerValueOffset[$pointerSize];
|
221 |
-
|
222 |
-
return [$pointer, $offset];
|
223 |
-
}
|
224 |
-
|
225 |
-
private function decodeUint($bytes)
|
226 |
-
{
|
227 |
-
list(, $int) = unpack('N', $this->zeroPadLeft($bytes, 4));
|
228 |
-
|
229 |
-
return $int;
|
230 |
-
}
|
231 |
-
|
232 |
-
private function decodeBigUint($bytes, $byteLength)
|
233 |
-
{
|
234 |
-
$maxUintBytes = log(PHP_INT_MAX, 2) / 8;
|
235 |
-
|
236 |
-
if ($byteLength === 0) {
|
237 |
-
return 0;
|
238 |
-
}
|
239 |
-
|
240 |
-
$numberOfLongs = ceil($byteLength / 4);
|
241 |
-
$paddedLength = $numberOfLongs * 4;
|
242 |
-
$paddedBytes = $this->zeroPadLeft($bytes, $paddedLength);
|
243 |
-
$unpacked = array_merge(unpack("N$numberOfLongs", $paddedBytes));
|
244 |
-
|
245 |
-
$integer = 0;
|
246 |
-
|
247 |
-
// 2^32
|
248 |
-
$twoTo32 = '4294967296';
|
249 |
-
|
250 |
-
foreach ($unpacked as $part) {
|
251 |
-
// We only use gmp or bcmath if the final value is too big
|
252 |
-
if ($byteLength <= $maxUintBytes) {
|
253 |
-
$integer = ($integer << 32) + $part;
|
254 |
-
} elseif (extension_loaded('gmp')) {
|
255 |
-
$integer = gmp_strval(gmp_add(gmp_mul($integer, $twoTo32), $part));
|
256 |
-
} elseif (extension_loaded('bcmath')) {
|
257 |
-
$integer = bcadd(bcmul($integer, $twoTo32), $part);
|
258 |
-
} else {
|
259 |
-
throw new \RuntimeException(
|
260 |
-
'The gmp or bcmath extension must be installed to read this database.'
|
261 |
-
);
|
262 |
-
}
|
263 |
-
}
|
264 |
-
|
265 |
-
return $integer;
|
266 |
-
}
|
267 |
-
|
268 |
-
private function decodeString($bytes)
|
269 |
-
{
|
270 |
-
// XXX - NOOP. As far as I know, the end user has to explicitly set the
|
271 |
-
// encoding in PHP. Strings are just bytes.
|
272 |
-
return $bytes;
|
273 |
-
}
|
274 |
-
|
275 |
-
private function sizeFromCtrlByte($ctrlByte, $offset)
|
276 |
-
{
|
277 |
-
$size = $ctrlByte & 0x1f;
|
278 |
-
$bytesToRead = $size < 29 ? 0 : $size - 28;
|
279 |
-
$bytes = Util::read($this->fileStream, $offset, $bytesToRead);
|
280 |
-
$decoded = $this->decodeUint($bytes);
|
281 |
-
|
282 |
-
if ($size === 29) {
|
283 |
-
$size = 29 + $decoded;
|
284 |
-
} elseif ($size === 30) {
|
285 |
-
$size = 285 + $decoded;
|
286 |
-
} elseif ($size > 30) {
|
287 |
-
$size = ($decoded & (0x0FFFFFFF >> (32 - (8 * $bytesToRead))))
|
288 |
-
+ 65821;
|
289 |
-
}
|
290 |
-
|
291 |
-
return [$size, $offset + $bytesToRead];
|
292 |
-
}
|
293 |
-
|
294 |
-
private function zeroPadLeft($content, $desiredLength)
|
295 |
-
{
|
296 |
-
return str_pad($content, $desiredLength, "\x00", STR_PAD_LEFT);
|
297 |
-
}
|
298 |
-
|
299 |
-
private function maybeSwitchByteOrder($bytes)
|
300 |
-
{
|
301 |
-
return $this->switchByteOrder ? strrev($bytes) : $bytes;
|
302 |
-
}
|
303 |
-
|
304 |
-
private function isPlatformLittleEndian()
|
305 |
-
{
|
306 |
-
$testint = 0x00FF;
|
307 |
-
$packed = pack('S', $testint);
|
308 |
-
|
309 |
-
return $testint === current(unpack('v', $packed));
|
310 |
-
}
|
311 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Db\Reader;
|
4 |
+
|
5 |
+
class Decoder
|
6 |
+
{
|
7 |
+
private $fileStream;
|
8 |
+
private $pointerBase;
|
9 |
+
// This is only used for unit testing
|
10 |
+
private $pointerTestHack;
|
11 |
+
private $switchByteOrder;
|
12 |
+
|
13 |
+
private $types = [
|
14 |
+
0 => 'extended',
|
15 |
+
1 => 'pointer',
|
16 |
+
2 => 'utf8_string',
|
17 |
+
3 => 'double',
|
18 |
+
4 => 'bytes',
|
19 |
+
5 => 'uint16',
|
20 |
+
6 => 'uint32',
|
21 |
+
7 => 'map',
|
22 |
+
8 => 'int32',
|
23 |
+
9 => 'uint64',
|
24 |
+
10 => 'uint128',
|
25 |
+
11 => 'array',
|
26 |
+
12 => 'container',
|
27 |
+
13 => 'end_marker',
|
28 |
+
14 => 'boolean',
|
29 |
+
15 => 'float',
|
30 |
+
];
|
31 |
+
|
32 |
+
public function __construct(
|
33 |
+
$fileStream,
|
34 |
+
$pointerBase = 0,
|
35 |
+
$pointerTestHack = false
|
36 |
+
) {
|
37 |
+
$this->fileStream = $fileStream;
|
38 |
+
$this->pointerBase = $pointerBase;
|
39 |
+
$this->pointerTestHack = $pointerTestHack;
|
40 |
+
|
41 |
+
$this->switchByteOrder = $this->isPlatformLittleEndian();
|
42 |
+
}
|
43 |
+
|
44 |
+
public function decode($offset)
|
45 |
+
{
|
46 |
+
list(, $ctrlByte) = unpack(
|
47 |
+
'C',
|
48 |
+
Util::read($this->fileStream, $offset, 1)
|
49 |
+
);
|
50 |
+
$offset++;
|
51 |
+
|
52 |
+
$type = $this->types[$ctrlByte >> 5];
|
53 |
+
|
54 |
+
// Pointers are a special case, we don't read the next $size bytes, we
|
55 |
+
// use the size to determine the length of the pointer and then follow
|
56 |
+
// it.
|
57 |
+
if ($type === 'pointer') {
|
58 |
+
list($pointer, $offset) = $this->decodePointer($ctrlByte, $offset);
|
59 |
+
|
60 |
+
// for unit testing
|
61 |
+
if ($this->pointerTestHack) {
|
62 |
+
return [$pointer];
|
63 |
+
}
|
64 |
+
|
65 |
+
list($result) = $this->decode($pointer);
|
66 |
+
|
67 |
+
return [$result, $offset];
|
68 |
+
}
|
69 |
+
|
70 |
+
if ($type === 'extended') {
|
71 |
+
list(, $nextByte) = unpack(
|
72 |
+
'C',
|
73 |
+
Util::read($this->fileStream, $offset, 1)
|
74 |
+
);
|
75 |
+
|
76 |
+
$typeNum = $nextByte + 7;
|
77 |
+
|
78 |
+
if ($typeNum < 8) {
|
79 |
+
throw new InvalidDatabaseException(
|
80 |
+
'Something went horribly wrong in the decoder. An extended type '
|
81 |
+
. 'resolved to a type number < 8 ('
|
82 |
+
. $this->types[$typeNum]
|
83 |
+
. ')'
|
84 |
+
);
|
85 |
+
}
|
86 |
+
|
87 |
+
$type = $this->types[$typeNum];
|
88 |
+
$offset++;
|
89 |
+
}
|
90 |
+
|
91 |
+
list($size, $offset) = $this->sizeFromCtrlByte($ctrlByte, $offset);
|
92 |
+
|
93 |
+
return $this->decodeByType($type, $offset, $size);
|
94 |
+
}
|
95 |
+
|
96 |
+
private function decodeByType($type, $offset, $size)
|
97 |
+
{
|
98 |
+
switch ($type) {
|
99 |
+
case 'map':
|
100 |
+
return $this->decodeMap($size, $offset);
|
101 |
+
case 'array':
|
102 |
+
return $this->decodeArray($size, $offset);
|
103 |
+
case 'boolean':
|
104 |
+
return [$this->decodeBoolean($size), $offset];
|
105 |
+
}
|
106 |
+
|
107 |
+
$newOffset = $offset + $size;
|
108 |
+
$bytes = Util::read($this->fileStream, $offset, $size);
|
109 |
+
switch ($type) {
|
110 |
+
case 'utf8_string':
|
111 |
+
return [$this->decodeString($bytes), $newOffset];
|
112 |
+
case 'double':
|
113 |
+
$this->verifySize(8, $size);
|
114 |
+
|
115 |
+
return [$this->decodeDouble($bytes), $newOffset];
|
116 |
+
case 'float':
|
117 |
+
$this->verifySize(4, $size);
|
118 |
+
|
119 |
+
return [$this->decodeFloat($bytes), $newOffset];
|
120 |
+
case 'bytes':
|
121 |
+
return [$bytes, $newOffset];
|
122 |
+
case 'uint16':
|
123 |
+
case 'uint32':
|
124 |
+
return [$this->decodeUint($bytes), $newOffset];
|
125 |
+
case 'int32':
|
126 |
+
return [$this->decodeInt32($bytes), $newOffset];
|
127 |
+
case 'uint64':
|
128 |
+
case 'uint128':
|
129 |
+
return [$this->decodeBigUint($bytes, $size), $newOffset];
|
130 |
+
default:
|
131 |
+
throw new InvalidDatabaseException(
|
132 |
+
'Unknown or unexpected type: ' . $type
|
133 |
+
);
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
private function verifySize($expected, $actual)
|
138 |
+
{
|
139 |
+
if ($expected !== $actual) {
|
140 |
+
throw new InvalidDatabaseException(
|
141 |
+
"The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
|
142 |
+
);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
private function decodeArray($size, $offset)
|
147 |
+
{
|
148 |
+
$array = [];
|
149 |
+
|
150 |
+
for ($i = 0; $i < $size; $i++) {
|
151 |
+
list($value, $offset) = $this->decode($offset);
|
152 |
+
array_push($array, $value);
|
153 |
+
}
|
154 |
+
|
155 |
+
return [$array, $offset];
|
156 |
+
}
|
157 |
+
|
158 |
+
private function decodeBoolean($size)
|
159 |
+
{
|
160 |
+
return $size === 0 ? false : true;
|
161 |
+
}
|
162 |
+
|
163 |
+
private function decodeDouble($bits)
|
164 |
+
{
|
165 |
+
// XXX - Assumes IEEE 754 double on platform
|
166 |
+
list(, $double) = unpack('d', $this->maybeSwitchByteOrder($bits));
|
167 |
+
|
168 |
+
return $double;
|
169 |
+
}
|
170 |
+
|
171 |
+
private function decodeFloat($bits)
|
172 |
+
{
|
173 |
+
// XXX - Assumes IEEE 754 floats on platform
|
174 |
+
list(, $float) = unpack('f', $this->maybeSwitchByteOrder($bits));
|
175 |
+
|
176 |
+
return $float;
|
177 |
+
}
|
178 |
+
|
179 |
+
private function decodeInt32($bytes)
|
180 |
+
{
|
181 |
+
$bytes = $this->zeroPadLeft($bytes, 4);
|
182 |
+
list(, $int) = unpack('l', $this->maybeSwitchByteOrder($bytes));
|
183 |
+
|
184 |
+
return $int;
|
185 |
+
}
|
186 |
+
|
187 |
+
private function decodeMap($size, $offset)
|
188 |
+
{
|
189 |
+
$map = [];
|
190 |
+
|
191 |
+
for ($i = 0; $i < $size; $i++) {
|
192 |
+
list($key, $offset) = $this->decode($offset);
|
193 |
+
list($value, $offset) = $this->decode($offset);
|
194 |
+
$map[$key] = $value;
|
195 |
+
}
|
196 |
+
|
197 |
+
return [$map, $offset];
|
198 |
+
}
|
199 |
+
|
200 |
+
private $pointerValueOffset = [
|
201 |
+
1 => 0,
|
202 |
+
2 => 2048,
|
203 |
+
3 => 526336,
|
204 |
+
4 => 0,
|
205 |
+
];
|
206 |
+
|
207 |
+
private function decodePointer($ctrlByte, $offset)
|
208 |
+
{
|
209 |
+
$pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
|
210 |
+
|
211 |
+
$buffer = Util::read($this->fileStream, $offset, $pointerSize);
|
212 |
+
$offset = $offset + $pointerSize;
|
213 |
+
|
214 |
+
$packed = $pointerSize === 4
|
215 |
+
? $buffer
|
216 |
+
: (pack('C', $ctrlByte & 0x7)) . $buffer;
|
217 |
+
|
218 |
+
$unpacked = $this->decodeUint($packed);
|
219 |
+
$pointer = $unpacked + $this->pointerBase
|
220 |
+
+ $this->pointerValueOffset[$pointerSize];
|
221 |
+
|
222 |
+
return [$pointer, $offset];
|
223 |
+
}
|
224 |
+
|
225 |
+
private function decodeUint($bytes)
|
226 |
+
{
|
227 |
+
list(, $int) = unpack('N', $this->zeroPadLeft($bytes, 4));
|
228 |
+
|
229 |
+
return $int;
|
230 |
+
}
|
231 |
+
|
232 |
+
private function decodeBigUint($bytes, $byteLength)
|
233 |
+
{
|
234 |
+
$maxUintBytes = log(PHP_INT_MAX, 2) / 8;
|
235 |
+
|
236 |
+
if ($byteLength === 0) {
|
237 |
+
return 0;
|
238 |
+
}
|
239 |
+
|
240 |
+
$numberOfLongs = ceil($byteLength / 4);
|
241 |
+
$paddedLength = $numberOfLongs * 4;
|
242 |
+
$paddedBytes = $this->zeroPadLeft($bytes, $paddedLength);
|
243 |
+
$unpacked = array_merge(unpack("N$numberOfLongs", $paddedBytes));
|
244 |
+
|
245 |
+
$integer = 0;
|
246 |
+
|
247 |
+
// 2^32
|
248 |
+
$twoTo32 = '4294967296';
|
249 |
+
|
250 |
+
foreach ($unpacked as $part) {
|
251 |
+
// We only use gmp or bcmath if the final value is too big
|
252 |
+
if ($byteLength <= $maxUintBytes) {
|
253 |
+
$integer = ($integer << 32) + $part;
|
254 |
+
} elseif (extension_loaded('gmp')) {
|
255 |
+
$integer = gmp_strval(gmp_add(gmp_mul($integer, $twoTo32), $part));
|
256 |
+
} elseif (extension_loaded('bcmath')) {
|
257 |
+
$integer = bcadd(bcmul($integer, $twoTo32), $part);
|
258 |
+
} else {
|
259 |
+
throw new \RuntimeException(
|
260 |
+
'The gmp or bcmath extension must be installed to read this database.'
|
261 |
+
);
|
262 |
+
}
|
263 |
+
}
|
264 |
+
|
265 |
+
return $integer;
|
266 |
+
}
|
267 |
+
|
268 |
+
private function decodeString($bytes)
|
269 |
+
{
|
270 |
+
// XXX - NOOP. As far as I know, the end user has to explicitly set the
|
271 |
+
// encoding in PHP. Strings are just bytes.
|
272 |
+
return $bytes;
|
273 |
+
}
|
274 |
+
|
275 |
+
private function sizeFromCtrlByte($ctrlByte, $offset)
|
276 |
+
{
|
277 |
+
$size = $ctrlByte & 0x1f;
|
278 |
+
$bytesToRead = $size < 29 ? 0 : $size - 28;
|
279 |
+
$bytes = Util::read($this->fileStream, $offset, $bytesToRead);
|
280 |
+
$decoded = $this->decodeUint($bytes);
|
281 |
+
|
282 |
+
if ($size === 29) {
|
283 |
+
$size = 29 + $decoded;
|
284 |
+
} elseif ($size === 30) {
|
285 |
+
$size = 285 + $decoded;
|
286 |
+
} elseif ($size > 30) {
|
287 |
+
$size = ($decoded & (0x0FFFFFFF >> (32 - (8 * $bytesToRead))))
|
288 |
+
+ 65821;
|
289 |
+
}
|
290 |
+
|
291 |
+
return [$size, $offset + $bytesToRead];
|
292 |
+
}
|
293 |
+
|
294 |
+
private function zeroPadLeft($content, $desiredLength)
|
295 |
+
{
|
296 |
+
return str_pad($content, $desiredLength, "\x00", STR_PAD_LEFT);
|
297 |
+
}
|
298 |
+
|
299 |
+
private function maybeSwitchByteOrder($bytes)
|
300 |
+
{
|
301 |
+
return $this->switchByteOrder ? strrev($bytes) : $bytes;
|
302 |
+
}
|
303 |
+
|
304 |
+
private function isPlatformLittleEndian()
|
305 |
+
{
|
306 |
+
$testint = 0x00FF;
|
307 |
+
$packed = pack('S', $testint);
|
308 |
+
|
309 |
+
return $testint === current(unpack('v', $packed));
|
310 |
+
}
|
311 |
+
}
|
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Db\Reader;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class should be thrown when unexpected data is found in the database.
|
7 |
-
*/
|
8 |
-
class InvalidDatabaseException extends \Exception
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Db\Reader;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class should be thrown when unexpected data is found in the database.
|
7 |
+
*/
|
8 |
+
class InvalidDatabaseException extends \Exception
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php
CHANGED
@@ -1,69 +1,69 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Db\Reader;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class provides the metadata for the MaxMind DB file.
|
7 |
-
*
|
8 |
-
* @property int nodeCount This is an unsigned 32-bit integer indicating
|
9 |
-
* the number of nodes in the search tree.
|
10 |
-
* @property int recordSize This is an unsigned 16-bit integer. It
|
11 |
-
* indicates the number of bits in a record in the search tree. Note that each
|
12 |
-
* node consists of two records.
|
13 |
-
* @property int ipVersion This is an unsigned 16-bit integer which is
|
14 |
-
* always 4 or 6. It indicates whether the database contains IPv4 or IPv6
|
15 |
-
* address data.
|
16 |
-
* @property string databaseType This is a string that indicates the structure
|
17 |
-
* of each data record associated with an IP address. The actual definition of
|
18 |
-
* these structures is left up to the database creator.
|
19 |
-
* @property array languages An array of strings, each of which is a language
|
20 |
-
* code. A given record may contain data items that have been localized to
|
21 |
-
* some or all of these languages. This may be undefined.
|
22 |
-
* @property int binaryFormatMajorVersion This is an unsigned 16-bit
|
23 |
-
* integer indicating the major version number for the database's binary
|
24 |
-
* format.
|
25 |
-
* @property int binaryFormatMinorVersion This is an unsigned 16-bit
|
26 |
-
* integer indicating the minor version number for the database's binary format.
|
27 |
-
* @property int buildEpoch This is an unsigned 64-bit integer that
|
28 |
-
* contains the database build timestamp as a Unix epoch value.
|
29 |
-
* @property array description This key will always point to a map
|
30 |
-
* (associative array). The keys of that map will be language codes, and the
|
31 |
-
* values will be a description in that language as a UTF-8 string. May be
|
32 |
-
* undefined for some databases.
|
33 |
-
*/
|
34 |
-
class Metadata
|
35 |
-
{
|
36 |
-
private $binaryFormatMajorVersion;
|
37 |
-
private $binaryFormatMinorVersion;
|
38 |
-
private $buildEpoch;
|
39 |
-
private $databaseType;
|
40 |
-
private $description;
|
41 |
-
private $ipVersion;
|
42 |
-
private $languages;
|
43 |
-
private $nodeByteSize;
|
44 |
-
private $nodeCount;
|
45 |
-
private $recordSize;
|
46 |
-
private $searchTreeSize;
|
47 |
-
|
48 |
-
public function __construct($metadata)
|
49 |
-
{
|
50 |
-
$this->binaryFormatMajorVersion =
|
51 |
-
$metadata['binary_format_major_version'];
|
52 |
-
$this->binaryFormatMinorVersion =
|
53 |
-
$metadata['binary_format_minor_version'];
|
54 |
-
$this->buildEpoch = $metadata['build_epoch'];
|
55 |
-
$this->databaseType = $metadata['database_type'];
|
56 |
-
$this->languages = $metadata['languages'];
|
57 |
-
$this->description = $metadata['description'];
|
58 |
-
$this->ipVersion = $metadata['ip_version'];
|
59 |
-
$this->nodeCount = $metadata['node_count'];
|
60 |
-
$this->recordSize = $metadata['record_size'];
|
61 |
-
$this->nodeByteSize = $this->recordSize / 4;
|
62 |
-
$this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
|
63 |
-
}
|
64 |
-
|
65 |
-
public function __get($var)
|
66 |
-
{
|
67 |
-
return $this->$var;
|
68 |
-
}
|
69 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Db\Reader;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class provides the metadata for the MaxMind DB file.
|
7 |
+
*
|
8 |
+
* @property int nodeCount This is an unsigned 32-bit integer indicating
|
9 |
+
* the number of nodes in the search tree.
|
10 |
+
* @property int recordSize This is an unsigned 16-bit integer. It
|
11 |
+
* indicates the number of bits in a record in the search tree. Note that each
|
12 |
+
* node consists of two records.
|
13 |
+
* @property int ipVersion This is an unsigned 16-bit integer which is
|
14 |
+
* always 4 or 6. It indicates whether the database contains IPv4 or IPv6
|
15 |
+
* address data.
|
16 |
+
* @property string databaseType This is a string that indicates the structure
|
17 |
+
* of each data record associated with an IP address. The actual definition of
|
18 |
+
* these structures is left up to the database creator.
|
19 |
+
* @property array languages An array of strings, each of which is a language
|
20 |
+
* code. A given record may contain data items that have been localized to
|
21 |
+
* some or all of these languages. This may be undefined.
|
22 |
+
* @property int binaryFormatMajorVersion This is an unsigned 16-bit
|
23 |
+
* integer indicating the major version number for the database's binary
|
24 |
+
* format.
|
25 |
+
* @property int binaryFormatMinorVersion This is an unsigned 16-bit
|
26 |
+
* integer indicating the minor version number for the database's binary format.
|
27 |
+
* @property int buildEpoch This is an unsigned 64-bit integer that
|
28 |
+
* contains the database build timestamp as a Unix epoch value.
|
29 |
+
* @property array description This key will always point to a map
|
30 |
+
* (associative array). The keys of that map will be language codes, and the
|
31 |
+
* values will be a description in that language as a UTF-8 string. May be
|
32 |
+
* undefined for some databases.
|
33 |
+
*/
|
34 |
+
class Metadata
|
35 |
+
{
|
36 |
+
private $binaryFormatMajorVersion;
|
37 |
+
private $binaryFormatMinorVersion;
|
38 |
+
private $buildEpoch;
|
39 |
+
private $databaseType;
|
40 |
+
private $description;
|
41 |
+
private $ipVersion;
|
42 |
+
private $languages;
|
43 |
+
private $nodeByteSize;
|
44 |
+
private $nodeCount;
|
45 |
+
private $recordSize;
|
46 |
+
private $searchTreeSize;
|
47 |
+
|
48 |
+
public function __construct($metadata)
|
49 |
+
{
|
50 |
+
$this->binaryFormatMajorVersion =
|
51 |
+
$metadata['binary_format_major_version'];
|
52 |
+
$this->binaryFormatMinorVersion =
|
53 |
+
$metadata['binary_format_minor_version'];
|
54 |
+
$this->buildEpoch = $metadata['build_epoch'];
|
55 |
+
$this->databaseType = $metadata['database_type'];
|
56 |
+
$this->languages = $metadata['languages'];
|
57 |
+
$this->description = $metadata['description'];
|
58 |
+
$this->ipVersion = $metadata['ip_version'];
|
59 |
+
$this->nodeCount = $metadata['node_count'];
|
60 |
+
$this->recordSize = $metadata['record_size'];
|
61 |
+
$this->nodeByteSize = $this->recordSize / 4;
|
62 |
+
$this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
|
63 |
+
}
|
64 |
+
|
65 |
+
public function __get($var)
|
66 |
+
{
|
67 |
+
return $this->$var;
|
68 |
+
}
|
69 |
+
}
|
includes/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php
CHANGED
@@ -1,26 +1,26 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Db\Reader;
|
4 |
-
|
5 |
-
class Util
|
6 |
-
{
|
7 |
-
public static function read($stream, $offset, $numberOfBytes)
|
8 |
-
{
|
9 |
-
if ($numberOfBytes === 0) {
|
10 |
-
return '';
|
11 |
-
}
|
12 |
-
if (fseek($stream, $offset) === 0) {
|
13 |
-
$value = fread($stream, $numberOfBytes);
|
14 |
-
|
15 |
-
// We check that the number of bytes read is equal to the number
|
16 |
-
// asked for. We use ftell as getting the length of $value is
|
17 |
-
// much slower.
|
18 |
-
if (ftell($stream) - $offset === $numberOfBytes) {
|
19 |
-
return $value;
|
20 |
-
}
|
21 |
-
}
|
22 |
-
throw new InvalidDatabaseException(
|
23 |
-
'The MaxMind DB file contains bad data'
|
24 |
-
);
|
25 |
-
}
|
26 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Db\Reader;
|
4 |
+
|
5 |
+
class Util
|
6 |
+
{
|
7 |
+
public static function read($stream, $offset, $numberOfBytes)
|
8 |
+
{
|
9 |
+
if ($numberOfBytes === 0) {
|
10 |
+
return '';
|
11 |
+
}
|
12 |
+
if (fseek($stream, $offset) === 0) {
|
13 |
+
$value = fread($stream, $numberOfBytes);
|
14 |
+
|
15 |
+
// We check that the number of bytes read is equal to the number
|
16 |
+
// asked for. We use ftell as getting the length of $value is
|
17 |
+
// much slower.
|
18 |
+
if (ftell($stream) - $offset === $numberOfBytes) {
|
19 |
+
return $value;
|
20 |
+
}
|
21 |
+
}
|
22 |
+
throw new InvalidDatabaseException(
|
23 |
+
'The MaxMind DB file contains bad data'
|
24 |
+
);
|
25 |
+
}
|
26 |
+
}
|
includes/vendor/maxmind/web-service-common/CHANGELOG.md
CHANGED
@@ -1,79 +1,79 @@
|
|
1 |
-
CHANGELOG
|
2 |
-
=========
|
3 |
-
|
4 |
-
0.5.0 (2018-02-12)
|
5 |
-
------------------
|
6 |
-
|
7 |
-
* Refer to account IDs using the terminology "account" rather than "user".
|
8 |
-
|
9 |
-
0.4.0 (2017-07-10)
|
10 |
-
------------------
|
11 |
-
|
12 |
-
* PHP 5.4 is now required.
|
13 |
-
|
14 |
-
0.3.1 (2016-08-10)
|
15 |
-
------------------
|
16 |
-
|
17 |
-
* On Mac OS X when using a curl built against SecureTransport, the certs
|
18 |
-
in the system's keychain will now be used instead of the CA bundle on
|
19 |
-
the file system.
|
20 |
-
|
21 |
-
0.3.0 (2016-08-09)
|
22 |
-
------------------
|
23 |
-
|
24 |
-
* This package now uses `composer/ca-bundle` by default rather than a CA
|
25 |
-
bundle distributed with this package. `composer/ca-bundle` will first try
|
26 |
-
to use the system CA bundle and will fall back to the Mozilla CA bundle
|
27 |
-
when no system bundle is available. You may still specify your own bundle
|
28 |
-
using the `caBundle` option.
|
29 |
-
|
30 |
-
0.2.1 (2016-06-13)
|
31 |
-
------------------
|
32 |
-
|
33 |
-
* Fix typo in code to copy cert to temp directory.
|
34 |
-
|
35 |
-
0.2.0 (2016-06-10)
|
36 |
-
------------------
|
37 |
-
|
38 |
-
* Added handling of additional error codes that the web service may return.
|
39 |
-
* A `USER_ID_UNKNOWN` error will now throw a
|
40 |
-
`MaxMind\Exception\AuthenticationException`.
|
41 |
-
* Added support for `proxy` option. Closes #6.
|
42 |
-
|
43 |
-
0.1.0 (2016-05-23)
|
44 |
-
------------------
|
45 |
-
|
46 |
-
* A `PERMISSION_REQUIRED` error will now throw a `PermissionRequiredException`
|
47 |
-
exception.
|
48 |
-
* Added a `.gitattributes` file to exclude tests from Composer releases.
|
49 |
-
GitHub #7.
|
50 |
-
* Updated included cert bundle.
|
51 |
-
|
52 |
-
0.0.4 (2015-07-21)
|
53 |
-
------------------
|
54 |
-
|
55 |
-
* Added extremely basic tests for the curl calls.
|
56 |
-
* Fixed broken POSTs.
|
57 |
-
|
58 |
-
0.0.3 (2015-06-30)
|
59 |
-
------------------
|
60 |
-
|
61 |
-
* Floats now work with the `timeout` and `connectTimeout` options. Fix by
|
62 |
-
Benjamin Pick. GitHub PR #2.
|
63 |
-
* `curl_error` is now used instead of `curl_strerror`. The latter is only
|
64 |
-
available for PHP 5.5 or later. Fix by Benjamin Pick. GitHub PR #1.
|
65 |
-
|
66 |
-
|
67 |
-
0.0.2 (2015-06-09)
|
68 |
-
------------------
|
69 |
-
|
70 |
-
* An exception is now immediately thrown curl error rather than letting later
|
71 |
-
status code checks throw an exception. This improves the exception message
|
72 |
-
greatly.
|
73 |
-
* If this library is inside a phar archive, the CA certs are copied out of the
|
74 |
-
archive to a temporary file so that curl can use them.
|
75 |
-
|
76 |
-
0.0.1 (2015-06-01)
|
77 |
-
------------------
|
78 |
-
|
79 |
-
* Initial release.
|
1 |
+
CHANGELOG
|
2 |
+
=========
|
3 |
+
|
4 |
+
0.5.0 (2018-02-12)
|
5 |
+
------------------
|
6 |
+
|
7 |
+
* Refer to account IDs using the terminology "account" rather than "user".
|
8 |
+
|
9 |
+
0.4.0 (2017-07-10)
|
10 |
+
------------------
|
11 |
+
|
12 |
+
* PHP 5.4 is now required.
|
13 |
+
|
14 |
+
0.3.1 (2016-08-10)
|
15 |
+
------------------
|
16 |
+
|
17 |
+
* On Mac OS X when using a curl built against SecureTransport, the certs
|
18 |
+
in the system's keychain will now be used instead of the CA bundle on
|
19 |
+
the file system.
|
20 |
+
|
21 |
+
0.3.0 (2016-08-09)
|
22 |
+
------------------
|
23 |
+
|
24 |
+
* This package now uses `composer/ca-bundle` by default rather than a CA
|
25 |
+
bundle distributed with this package. `composer/ca-bundle` will first try
|
26 |
+
to use the system CA bundle and will fall back to the Mozilla CA bundle
|
27 |
+
when no system bundle is available. You may still specify your own bundle
|
28 |
+
using the `caBundle` option.
|
29 |
+
|
30 |
+
0.2.1 (2016-06-13)
|
31 |
+
------------------
|
32 |
+
|
33 |
+
* Fix typo in code to copy cert to temp directory.
|
34 |
+
|
35 |
+
0.2.0 (2016-06-10)
|
36 |
+
------------------
|
37 |
+
|
38 |
+
* Added handling of additional error codes that the web service may return.
|
39 |
+
* A `USER_ID_UNKNOWN` error will now throw a
|
40 |
+
`MaxMind\Exception\AuthenticationException`.
|
41 |
+
* Added support for `proxy` option. Closes #6.
|
42 |
+
|
43 |
+
0.1.0 (2016-05-23)
|
44 |
+
------------------
|
45 |
+
|
46 |
+
* A `PERMISSION_REQUIRED` error will now throw a `PermissionRequiredException`
|
47 |
+
exception.
|
48 |
+
* Added a `.gitattributes` file to exclude tests from Composer releases.
|
49 |
+
GitHub #7.
|
50 |
+
* Updated included cert bundle.
|
51 |
+
|
52 |
+
0.0.4 (2015-07-21)
|
53 |
+
------------------
|
54 |
+
|
55 |
+
* Added extremely basic tests for the curl calls.
|
56 |
+
* Fixed broken POSTs.
|
57 |
+
|
58 |
+
0.0.3 (2015-06-30)
|
59 |
+
------------------
|
60 |
+
|
61 |
+
* Floats now work with the `timeout` and `connectTimeout` options. Fix by
|
62 |
+
Benjamin Pick. GitHub PR #2.
|
63 |
+
* `curl_error` is now used instead of `curl_strerror`. The latter is only
|
64 |
+
available for PHP 5.5 or later. Fix by Benjamin Pick. GitHub PR #1.
|
65 |
+
|
66 |
+
|
67 |
+
0.0.2 (2015-06-09)
|
68 |
+
------------------
|
69 |
+
|
70 |
+
* An exception is now immediately thrown curl error rather than letting later
|
71 |
+
status code checks throw an exception. This improves the exception message
|
72 |
+
greatly.
|
73 |
+
* If this library is inside a phar archive, the CA certs are copied out of the
|
74 |
+
archive to a temporary file so that curl can use them.
|
75 |
+
|
76 |
+
0.0.1 (2015-06-01)
|
77 |
+
------------------
|
78 |
+
|
79 |
+
* Initial release.
|
includes/vendor/maxmind/web-service-common/LICENSE
CHANGED
@@ -1,202 +1,202 @@
|
|
1 |
-
|
2 |
-
Apache License
|
3 |
-
Version 2.0, January 2004
|
4 |
-
http://www.apache.org/licenses/
|
5 |
-
|
6 |
-
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
7 |
-
|
8 |
-
1. Definitions.
|
9 |
-
|
10 |
-
"License" shall mean the terms and conditions for use, reproduction,
|
11 |
-
and distribution as defined by Sections 1 through 9 of this document.
|
12 |
-
|
13 |
-
"Licensor" shall mean the copyright owner or entity authorized by
|
14 |
-
the copyright owner that is granting the License.
|
15 |
-
|
16 |
-
"Legal Entity" shall mean the union of the acting entity and all
|
17 |
-
other entities that control, are controlled by, or are under common
|
18 |
-
control with that entity. For the purposes of this definition,
|
19 |
-
"control" means (i) the power, direct or indirect, to cause the
|
20 |
-
direction or management of such entity, whether by contract or
|
21 |
-
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
22 |
-
outstanding shares, or (iii) beneficial ownership of such entity.
|
23 |
-
|
24 |
-
"You" (or "Your") shall mean an individual or Legal Entity
|
25 |
-
exercising permissions granted by this License.
|
26 |
-
|
27 |
-
"Source" form shall mean the preferred form for making modifications,
|
28 |
-
including but not limited to software source code, documentation
|
29 |
-
source, and configuration files.
|
30 |
-
|
31 |
-
"Object" form shall mean any form resulting from mechanical
|
32 |
-
transformation or translation of a Source form, including but
|
33 |
-
not limited to compiled object code, generated documentation,
|
34 |
-
and conversions to other media types.
|
35 |
-
|
36 |
-
"Work" shall mean the work of authorship, whether in Source or
|
37 |
-
Object form, made available under the License, as indicated by a
|
38 |
-
copyright notice that is included in or attached to the work
|
39 |
-
(an example is provided in the Appendix below).
|
40 |
-
|
41 |
-
"Derivative Works" shall mean any work, whether in Source or Object
|
42 |
-
form, that is based on (or derived from) the Work and for which the
|
43 |
-
editorial revisions, annotations, elaborations, or other modifications
|
44 |
-
represent, as a whole, an original work of authorship. For the purposes
|
45 |
-
of this License, Derivative Works shall not include works that remain
|
46 |
-
separable from, or merely link (or bind by name) to the interfaces of,
|
47 |
-
the Work and Derivative Works thereof.
|
48 |
-
|
49 |
-
"Contribution" shall mean any work of authorship, including
|
50 |
-
the original version of the Work and any modifications or additions
|
51 |
-
to that Work or Derivative Works thereof, that is intentionally
|
52 |
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
53 |
-
or by an individual or Legal Entity authorized to submit on behalf of
|
54 |
-
the copyright owner. For the purposes of this definition, "submitted"
|
55 |
-
means any form of electronic, verbal, or written communication sent
|
56 |
-
to the Licensor or its representatives, including but not limited to
|
57 |
-
communication on electronic mailing lists, source code control systems,
|
58 |
-
and issue tracking systems that are managed by, or on behalf of, the
|
59 |
-
Licensor for the purpose of discussing and improving the Work, but
|
60 |
-
excluding communication that is conspicuously marked or otherwise
|
61 |
-
designated in writing by the copyright owner as "Not a Contribution."
|
62 |
-
|
63 |
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
64 |
-
on behalf of whom a Contribution has been received by Licensor and
|
65 |
-
subsequently incorporated within the Work.
|
66 |
-
|
67 |
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
68 |
-
this License, each Contributor hereby grants to You a perpetual,
|
69 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
70 |
-
copyright license to reproduce, prepare Derivative Works of,
|
71 |
-
publicly display, publicly perform, sublicense, and distribute the
|
72 |
-
Work and such Derivative Works in Source or Object form.
|
73 |
-
|
74 |
-
3. Grant of Patent License. Subject to the terms and conditions of
|
75 |
-
this License, each Contributor hereby grants to You a perpetual,
|
76 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
77 |
-
(except as stated in this section) patent license to make, have made,
|
78 |
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
79 |
-
where such license applies only to those patent claims licensable
|
80 |
-
by such Contributor that are necessarily infringed by their
|
81 |
-
Contribution(s) alone or by combination of their Contribution(s)
|
82 |
-
with the Work to which such Contribution(s) was submitted. If You
|
83 |
-
institute patent litigation against any entity (including a
|
84 |
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
85 |
-
or a Contribution incorporated within the Work constitutes direct
|
86 |
-
or contributory patent infringement, then any patent licenses
|
87 |
-
granted to You under this License for that Work shall terminate
|
88 |
-
as of the date such litigation is filed.
|
89 |
-
|
90 |
-
4. Redistribution. You may reproduce and distribute copies of the
|
91 |
-
Work or Derivative Works thereof in any medium, with or without
|
92 |
-
modifications, and in Source or Object form, provided that You
|
93 |
-
meet the following conditions:
|
94 |
-
|
95 |
-
(a) You must give any other recipients of the Work or
|
96 |
-
Derivative Works a copy of this License; and
|
97 |
-
|
98 |
-
(b) You must cause any modified files to carry prominent notices
|
99 |
-
stating that You changed the files; and
|
100 |
-
|
101 |
-
(c) You must retain, in the Source form of any Derivative Works
|
102 |
-
that You distribute, all copyright, patent, trademark, and
|
103 |
-
attribution notices from the Source form of the Work,
|
104 |
-
excluding those notices that do not pertain to any part of
|
105 |
-
the Derivative Works; and
|
106 |
-
|
107 |
-
(d) If the Work includes a "NOTICE" text file as part of its
|
108 |
-
distribution, then any Derivative Works that You distribute must
|
109 |
-
include a readable copy of the attribution notices contained
|
110 |
-
within such NOTICE file, excluding those notices that do not
|
111 |
-
pertain to any part of the Derivative Works, in at least one
|
112 |
-
of the following places: within a NOTICE text file distributed
|
113 |
-
as part of the Derivative Works; within the Source form or
|
114 |
-
documentation, if provided along with the Derivative Works; or,
|
115 |
-
within a display generated by the Derivative Works, if and
|
116 |
-
wherever such third-party notices normally appear. The contents
|
117 |
-
of the NOTICE file are for informational purposes only and
|
118 |
-
do not modify the License. You may add Your own attribution
|
119 |
-
notices within Derivative Works that You distribute, alongside
|
120 |
-
or as an addendum to the NOTICE text from the Work, provided
|
121 |
-
that such additional attribution notices cannot be construed
|
122 |
-
as modifying the License.
|
123 |
-
|
124 |
-
You may add Your own copyright statement to Your modifications and
|
125 |
-
may provide additional or different license terms and conditions
|
126 |
-
for use, reproduction, or distribution of Your modifications, or
|
127 |
-
for any such Derivative Works as a whole, provided Your use,
|
128 |
-
reproduction, and distribution of the Work otherwise complies with
|
129 |
-
the conditions stated in this License.
|
130 |
-
|
131 |
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
132 |
-
any Contribution intentionally submitted for inclusion in the Work
|
133 |
-
by You to the Licensor shall be under the terms and conditions of
|
134 |
-
this License, without any additional terms or conditions.
|
135 |
-
Notwithstanding the above, nothing herein shall supersede or modify
|
136 |
-
the terms of any separate license agreement you may have executed
|
137 |
-
with Licensor regarding such Contributions.
|
138 |
-
|
139 |
-
6. Trademarks. This License does not grant permission to use the trade
|
140 |
-
names, trademarks, service marks, or product names of the Licensor,
|
141 |
-
except as required for reasonable and customary use in describing the
|
142 |
-
origin of the Work and reproducing the content of the NOTICE file.
|
143 |
-
|
144 |
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
145 |
-
agreed to in writing, Licensor provides the Work (and each
|
146 |
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
147 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
148 |
-
implied, including, without limitation, any warranties or conditions
|
149 |
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
150 |
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
151 |
-
appropriateness of using or redistributing the Work and assume any
|
152 |
-
risks associated with Your exercise of permissions under this License.
|
153 |
-
|
154 |
-
8. Limitation of Liability. In no event and under no legal theory,
|
155 |
-
whether in tort (including negligence), contract, or otherwise,
|
156 |
-
unless required by applicable law (such as deliberate and grossly
|
157 |
-
negligent acts) or agreed to in writing, shall any Contributor be
|
158 |
-
liable to You for damages, including any direct, indirect, special,
|
159 |
-
incidental, or consequential damages of any character arising as a
|
160 |
-
result of this License or out of the use or inability to use the
|
161 |
-
Work (including but not limited to damages for loss of goodwill,
|
162 |
-
work stoppage, computer failure or malfunction, or any and all
|
163 |
-
other commercial damages or losses), even if such Contributor
|
164 |
-
has been advised of the possibility of such damages.
|
165 |
-
|
166 |
-
9. Accepting Warranty or Additional Liability. While redistributing
|
167 |
-
the Work or Derivative Works thereof, You may choose to offer,
|
168 |
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
169 |
-
or other liability obligations and/or rights consistent with this
|
170 |
-
License. However, in accepting such obligations, You may act only
|
171 |
-
on Your own behalf and on Your sole responsibility, not on behalf
|
172 |
-
of any other Contributor, and only if You agree to indemnify,
|
173 |
-
defend, and hold each Contributor harmless for any liability
|
174 |
-
incurred by, or claims asserted against, such Contributor by reason
|
175 |
-
of your accepting any such warranty or additional liability.
|
176 |
-
|
177 |
-
END OF TERMS AND CONDITIONS
|
178 |
-
|
179 |
-
APPENDIX: How to apply the Apache License to your work.
|
180 |
-
|
181 |
-
To apply the Apache License to your work, attach the following
|
182 |
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
183 |
-
replaced with your own identifying information. (Don't include
|
184 |
-
the brackets!) The text should be enclosed in the appropriate
|
185 |
-
comment syntax for the file format. We also recommend that a
|
186 |
-
file or class name and description of purpose be included on the
|
187 |
-
same "printed page" as the copyright notice for easier
|
188 |
-
identification within third-party archives.
|
189 |
-
|
190 |
-
Copyright [yyyy] [name of copyright owner]
|
191 |
-
|
192 |
-
Licensed under the Apache License, Version 2.0 (the "License");
|
193 |
-
you may not use this file except in compliance with the License.
|
194 |
-
You may obtain a copy of the License at
|
195 |
-
|
196 |
-
http://www.apache.org/licenses/LICENSE-2.0
|
197 |
-
|
198 |
-
Unless required by applicable law or agreed to in writing, software
|
199 |
-
distributed under the License is distributed on an "AS IS" BASIS,
|
200 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
201 |
-
See the License for the specific language governing permissions and
|
202 |
-
limitations under the License.
|
1 |
+
|
2 |
+
Apache License
|
3 |
+
Version 2.0, January 2004
|
4 |
+
http://www.apache.org/licenses/
|
5 |
+
|
6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
7 |
+
|
8 |
+
1. Definitions.
|
9 |
+
|
10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
12 |
+
|
13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
14 |
+
the copyright owner that is granting the License.
|
15 |
+
|
16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
17 |
+
other entities that control, are controlled by, or are under common
|
18 |
+
control with that entity. For the purposes of this definition,
|
19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
20 |
+
direction or management of such entity, whether by contract or
|
21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
23 |
+
|
24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
25 |
+
exercising permissions granted by this License.
|
26 |
+
|
27 |
+
"Source" form shall mean the preferred form for making modifications,
|
28 |
+
including but not limited to software source code, documentation
|
29 |
+
source, and configuration files.
|
30 |
+
|
31 |
+
"Object" form shall mean any form resulting from mechanical
|
32 |
+
transformation or translation of a Source form, including but
|
33 |
+
not limited to compiled object code, generated documentation,
|
34 |
+
and conversions to other media types.
|
35 |
+
|
36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
37 |
+
Object form, made available under the License, as indicated by a
|
38 |
+
copyright notice that is included in or attached to the work
|
39 |
+
(an example is provided in the Appendix below).
|
40 |
+
|
41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
42 |
+
form, that is based on (or derived from) the Work and for which the
|
43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
45 |
+
of this License, Derivative Works shall not include works that remain
|
46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
47 |
+
the Work and Derivative Works thereof.
|
48 |
+
|
49 |
+
"Contribution" shall mean any work of authorship, including
|
50 |
+
the original version of the Work and any modifications or additions
|
51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
55 |
+
means any form of electronic, verbal, or written communication sent
|
56 |
+
to the Licensor or its representatives, including but not limited to
|
57 |
+
communication on electronic mailing lists, source code control systems,
|
58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
60 |
+
excluding communication that is conspicuously marked or otherwise
|
61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
62 |
+
|
63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
65 |
+
subsequently incorporated within the Work.
|
66 |
+
|
67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
72 |
+
Work and such Derivative Works in Source or Object form.
|
73 |
+
|
74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
77 |
+
(except as stated in this section) patent license to make, have made,
|
78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
79 |
+
where such license applies only to those patent claims licensable
|
80 |
+
by such Contributor that are necessarily infringed by their
|
81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
83 |
+
institute patent litigation against any entity (including a
|
84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
85 |
+
or a Contribution incorporated within the Work constitutes direct
|
86 |
+
or contributory patent infringement, then any patent licenses
|
87 |
+
granted to You under this License for that Work shall terminate
|
88 |
+
as of the date such litigation is filed.
|
89 |
+
|
90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
91 |
+
Work or Derivative Works thereof in any medium, with or without
|
92 |
+
modifications, and in Source or Object form, provided that You
|
93 |
+
meet the following conditions:
|
94 |
+
|
95 |
+
(a) You must give any other recipients of the Work or
|
96 |
+
Derivative Works a copy of this License; and
|
97 |
+
|
98 |
+
(b) You must cause any modified files to carry prominent notices
|
99 |
+
stating that You changed the files; and
|
100 |
+
|
101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
102 |
+
that You distribute, all copyright, patent, trademark, and
|
103 |
+
attribution notices from the Source form of the Work,
|
104 |
+
excluding those notices that do not pertain to any part of
|
105 |
+
the Derivative Works; and
|
106 |
+
|
107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
108 |
+
distribution, then any Derivative Works that You distribute must
|
109 |
+
include a readable copy of the attribution notices contained
|
110 |
+
within such NOTICE file, excluding those notices that do not
|
111 |
+
pertain to any part of the Derivative Works, in at least one
|
112 |
+
of the following places: within a NOTICE text file distributed
|
113 |
+
as part of the Derivative Works; within the Source form or
|
114 |
+
documentation, if provided along with the Derivative Works; or,
|
115 |
+
within a display generated by the Derivative Works, if and
|
116 |
+
wherever such third-party notices normally appear. The contents
|
117 |
+
of the NOTICE file are for informational purposes only and
|
118 |
+
do not modify the License. You may add Your own attribution
|
119 |
+
notices within Derivative Works that You distribute, alongside
|
120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
121 |
+
that such additional attribution notices cannot be construed
|
122 |
+
as modifying the License.
|
123 |
+
|
124 |
+
You may add Your own copyright statement to Your modifications and
|
125 |
+
may provide additional or different license terms and conditions
|
126 |
+
for use, reproduction, or distribution of Your modifications, or
|
127 |
+
for any such Derivative Works as a whole, provided Your use,
|
128 |
+
reproduction, and distribution of the Work otherwise complies with
|
129 |
+
the conditions stated in this License.
|
130 |
+
|
131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
133 |
+
by You to the Licensor shall be under the terms and conditions of
|
134 |
+
this License, without any additional terms or conditions.
|
135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
136 |
+
the terms of any separate license agreement you may have executed
|
137 |
+
with Licensor regarding such Contributions.
|
138 |
+
|
139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
141 |
+
except as required for reasonable and customary use in describing the
|
142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
143 |
+
|
144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
145 |
+
agreed to in writing, Licensor provides the Work (and each
|
146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
148 |
+
implied, including, without limitation, any warranties or conditions
|
149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
151 |
+
appropriateness of using or redistributing the Work and assume any
|
152 |
+
risks associated with Your exercise of permissions under this License.
|
153 |
+
|
154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
155 |
+
whether in tort (including negligence), contract, or otherwise,
|
156 |
+
unless required by applicable law (such as deliberate and grossly
|
157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
158 |
+
liable to You for damages, including any direct, indirect, special,
|
159 |
+
incidental, or consequential damages of any character arising as a
|
160 |
+
result of this License or out of the use or inability to use the
|
161 |
+
Work (including but not limited to damages for loss of goodwill,
|
162 |
+
work stoppage, computer failure or malfunction, or any and all
|
163 |
+
other commercial damages or losses), even if such Contributor
|
164 |
+
has been advised of the possibility of such damages.
|
165 |
+
|
166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
169 |
+
or other liability obligations and/or rights consistent with this
|
170 |
+
License. However, in accepting such obligations, You may act only
|
171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
172 |
+
of any other Contributor, and only if You agree to indemnify,
|
173 |
+
defend, and hold each Contributor harmless for any liability
|
174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
175 |
+
of your accepting any such warranty or additional liability.
|
176 |
+
|
177 |
+
END OF TERMS AND CONDITIONS
|
178 |
+
|
179 |
+
APPENDIX: How to apply the Apache License to your work.
|
180 |
+
|
181 |
+
To apply the Apache License to your work, attach the following
|
182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
183 |
+
replaced with your own identifying information. (Don't include
|
184 |
+
the brackets!) The text should be enclosed in the appropriate
|
185 |
+
comment syntax for the file format. We also recommend that a
|
186 |
+
file or class name and description of purpose be included on the
|
187 |
+
same "printed page" as the copyright notice for easier
|
188 |
+
identification within third-party archives.
|
189 |
+
|
190 |
+
Copyright [yyyy] [name of copyright owner]
|
191 |
+
|
192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
193 |
+
you may not use this file except in compliance with the License.
|
194 |
+
You may obtain a copy of the License at
|
195 |
+
|
196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
197 |
+
|
198 |
+
Unless required by applicable law or agreed to in writing, software
|
199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
201 |
+
See the License for the specific language governing permissions and
|
202 |
+
limitations under the License.
|
includes/vendor/maxmind/web-service-common/README.md
CHANGED
@@ -1,26 +1,26 @@
|
|
1 |
-
# Common Code for MaxMind Web Service Clients #
|
2 |
-
|
3 |
-
This is _not_ intended for direct use by third parties. Rather, it is for
|
4 |
-
shared code between MaxMind's various web service client APIs.
|
5 |
-
|
6 |
-
## Requirements ##
|
7 |
-
|
8 |
-
The library requires PHP 5.4 or greater. This library works and is tested
|
9 |
-
with HHVM.
|
10 |
-
|
11 |
-
There are several other dependencies as defined in the `composer.json` file.
|
12 |
-
|
13 |
-
## Contributing ##
|
14 |
-
|
15 |
-
Patches and pull requests are encouraged. All code should follow the PSR-2
|
16 |
-
style guidelines. Please include unit tests whenever possible.
|
17 |
-
|
18 |
-
## Versioning ##
|
19 |
-
|
20 |
-
This API uses [Semantic Versioning](http://semver.org/).
|
21 |
-
|
22 |
-
## Copyright and License ##
|
23 |
-
|
24 |
-
This software is Copyright (c) 2015-2018 by MaxMind, Inc.
|
25 |
-
|
26 |
-
This is free software, licensed under the Apache License, Version 2.0.
|
1 |
+
# Common Code for MaxMind Web Service Clients #
|
2 |
+
|
3 |
+
This is _not_ intended for direct use by third parties. Rather, it is for
|
4 |
+
shared code between MaxMind's various web service client APIs.
|
5 |
+
|
6 |
+
## Requirements ##
|
7 |
+
|
8 |
+
The library requires PHP 5.4 or greater. This library works and is tested
|
9 |
+
with HHVM.
|
10 |
+
|
11 |
+
There are several other dependencies as defined in the `composer.json` file.
|
12 |
+
|
13 |
+
## Contributing ##
|
14 |
+
|
15 |
+
Patches and pull requests are encouraged. All code should follow the PSR-2
|
16 |
+
style guidelines. Please include unit tests whenever possible.
|
17 |
+
|
18 |
+
## Versioning ##
|
19 |
+
|
20 |
+
This API uses [Semantic Versioning](http://semver.org/).
|
21 |
+
|
22 |
+
## Copyright and License ##
|
23 |
+
|
24 |
+
This software is Copyright (c) 2015-2018 by MaxMind, Inc.
|
25 |
+
|
26 |
+
This is free software, licensed under the Apache License, Version 2.0.
|
includes/vendor/maxmind/web-service-common/composer.json
CHANGED
@@ -1,31 +1,31 @@
|
|
1 |
-
{
|
2 |
-
"name": "maxmind/web-service-common",
|
3 |
-
"description": "Internal MaxMind Web Service API",
|
4 |
-
"minimum-stability": "stable",
|
5 |
-
"homepage": "https://github.com/maxmind/web-service-common-php",
|
6 |
-
"type": "library",
|
7 |
-
"license": "Apache-2.0",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "Gregory Oschwald",
|
11 |
-
"email": "goschwald@maxmind.com"
|
12 |
-
}
|
13 |
-
],
|
14 |
-
"require": {
|
15 |
-
"php": ">=5.4",
|
16 |
-
"composer/ca-bundle": "^1.0.3",
|
17 |
-
"ext-curl": "*",
|
18 |
-
"ext-json": "*"
|
19 |
-
},
|
20 |
-
"require-dev": {
|
21 |
-
"friendsofphp/php-cs-fixer": "2.*",
|
22 |
-
"phpunit/phpunit": "4.*",
|
23 |
-
"squizlabs/php_codesniffer": "3.*"
|
24 |
-
},
|
25 |
-
"autoload": {
|
26 |
-
"psr-4": {
|
27 |
-
"MaxMind\\Exception\\": "src/Exception",
|
28 |
-
"MaxMind\\WebService\\": "src/WebService"
|
29 |
-
}
|
30 |
-
}
|
31 |
-
}
|
1 |
+
{
|
2 |
+
"name": "maxmind/web-service-common",
|
3 |
+
"description": "Internal MaxMind Web Service API",
|
4 |
+
"minimum-stability": "stable",
|
5 |
+
"homepage": "https://github.com/maxmind/web-service-common-php",
|
6 |
+
"type": "library",
|
7 |
+
"license": "Apache-2.0",
|
8 |
+
"authors": [
|
9 |
+
{
|
10 |
+
"name": "Gregory Oschwald",
|
11 |
+
"email": "goschwald@maxmind.com"
|
12 |
+
}
|
13 |
+
],
|
14 |
+
"require": {
|
15 |
+
"php": ">=5.4",
|
16 |
+
"composer/ca-bundle": "^1.0.3",
|
17 |
+
"ext-curl": "*",
|
18 |
+
"ext-json": "*"
|
19 |
+
},
|
20 |
+
"require-dev": {
|
21 |
+
"friendsofphp/php-cs-fixer": "2.*",
|
22 |
+
"phpunit/phpunit": "4.*",
|
23 |
+
"squizlabs/php_codesniffer": "3.*"
|
24 |
+
},
|
25 |
+
"autoload": {
|
26 |
+
"psr-4": {
|
27 |
+
"MaxMind\\Exception\\": "src/Exception",
|
28 |
+
"MaxMind\\WebService\\": "src/WebService"
|
29 |
+
}
|
30 |
+
}
|
31 |
+
}
|
includes/vendor/maxmind/web-service-common/dev-bin/release.sh
CHANGED
@@ -1,60 +1,60 @@
|
|
1 |
-
#!/bin/bash
|
2 |
-
|
3 |
-
set -eu -o pipefail
|
4 |
-
|
5 |
-
|
6 |
-
changelog=$(cat CHANGELOG.md)
|
7 |
-
|
8 |
-
regex='
|
9 |
-
([0-9]+\.[0-9]+\.[0-9]+) \(([0-9]{4}-[0-9]{2}-[0-9]{2})\)
|
10 |
-
-*
|
11 |
-
|
12 |
-
((.|
|
13 |
-
)*)
|
14 |
-
'
|
15 |
-
|
16 |
-
if [[ ! $changelog =~ $regex ]]; then
|
17 |
-
echo "Could not find date line in change log!"
|
18 |
-
exit 1
|
19 |
-
fi
|
20 |
-
|
21 |
-
version="${BASH_REMATCH[1]}"
|
22 |
-
date="${BASH_REMATCH[2]}"
|
23 |
-
notes="$(echo "${BASH_REMATCH[3]}" | sed -n -e '/^[0-9]\+\.[0-9]\+\.[0-9]\+/,$!p')"
|
24 |
-
|
25 |
-
if [[ "$date" != $(date +"%Y-%m-%d") ]]; then
|
26 |
-
echo "$date is not today!"
|
27 |
-
exit 1
|
28 |
-
fi
|
29 |
-
|
30 |
-
tag="v$version"
|
31 |
-
|
32 |
-
if [ -n "$(git status --porcelain)" ]; then
|
33 |
-
echo ". is not clean." >&2
|
34 |
-
exit 1
|
35 |
-
fi
|
36 |
-
|
37 |
-
php composer.phar self-update
|
38 |
-
php composer.phar update
|
39 |
-
|
40 |
-
./vendor/bin/phpunit
|
41 |
-
|
42 |
-
echo "Release notes for $tag:"
|
43 |
-
echo "$notes"
|
44 |
-
|
45 |
-
read -e -p "Commit changes and push to origin? " should_push
|
46 |
-
|
47 |
-
if [ "$should_push" != "y" ]; then
|
48 |
-
echo "Aborting"
|
49 |
-
exit 1
|
50 |
-
fi
|
51 |
-
|
52 |
-
git push
|
53 |
-
|
54 |
-
message="$version
|
55 |
-
|
56 |
-
$notes"
|
57 |
-
|
58 |
-
hub release create -m "$message" "$tag"
|
59 |
-
|
60 |
-
git push --tags
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
set -eu -o pipefail
|
4 |
+
|
5 |
+
|
6 |
+
changelog=$(cat CHANGELOG.md)
|
7 |
+
|
8 |
+
regex='
|
9 |
+
([0-9]+\.[0-9]+\.[0-9]+) \(([0-9]{4}-[0-9]{2}-[0-9]{2})\)
|
10 |
+
-*
|
11 |
+
|
12 |
+
((.|
|
13 |
+
)*)
|
14 |
+
'
|
15 |
+
|
16 |
+
if [[ ! $changelog =~ $regex ]]; then
|
17 |
+
echo "Could not find date line in change log!"
|
18 |
+
exit 1
|
19 |
+
fi
|
20 |
+
|
21 |
+
version="${BASH_REMATCH[1]}"
|
22 |
+
date="${BASH_REMATCH[2]}"
|
23 |
+
notes="$(echo "${BASH_REMATCH[3]}" | sed -n -e '/^[0-9]\+\.[0-9]\+\.[0-9]\+/,$!p')"
|
24 |
+
|
25 |
+
if [[ "$date" != $(date +"%Y-%m-%d") ]]; then
|
26 |
+
echo "$date is not today!"
|
27 |
+
exit 1
|
28 |
+
fi
|
29 |
+
|
30 |
+
tag="v$version"
|
31 |
+
|
32 |
+
if [ -n "$(git status --porcelain)" ]; then
|
33 |
+
echo ". is not clean." >&2
|
34 |
+
exit 1
|
35 |
+
fi
|
36 |
+
|
37 |
+
php composer.phar self-update
|
38 |
+
php composer.phar update
|
39 |
+
|
40 |
+
./vendor/bin/phpunit
|
41 |
+
|
42 |
+
echo "Release notes for $tag:"
|
43 |
+
echo "$notes"
|
44 |
+
|
45 |
+
read -e -p "Commit changes and push to origin? " should_push
|
46 |
+
|
47 |
+
if [ "$should_push" != "y" ]; then
|
48 |
+
echo "Aborting"
|
49 |
+
exit 1
|
50 |
+
fi
|
51 |
+
|
52 |
+
git push
|
53 |
+
|
54 |
+
message="$version
|
55 |
+
|
56 |
+
$notes"
|
57 |
+
|
58 |
+
hub release create -m "$message" "$tag"
|
59 |
+
|
60 |
+
git push --tags
|
includes/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents an error authenticating.
|
7 |
-
*/
|
8 |
-
class AuthenticationException extends InvalidRequestException
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents an error authenticating.
|
7 |
+
*/
|
8 |
+
class AuthenticationException extends InvalidRequestException
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/maxmind/web-service-common/src/Exception/HttpException.php
CHANGED
@@ -1,40 +1,40 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents an HTTP transport error.
|
7 |
-
*/
|
8 |
-
class HttpException extends WebServiceException
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* The URI queried.
|
12 |
-
*/
|
13 |
-
private $uri;
|
14 |
-
|
15 |
-
/**
|
16 |
-
* @param string $message a message describing the error
|
17 |
-
* @param int $httpStatus the HTTP status code of the response
|
18 |
-
* @param string $uri the URI used in the request
|
19 |
-
* @param \Exception $previous the previous exception, if any
|
20 |
-
*/
|
21 |
-
public function __construct(
|
22 |
-
$message,
|
23 |
-
$httpStatus,
|
24 |
-
$uri,
|
25 |
-
\Exception $previous = null
|
26 |
-
) {
|
27 |
-
$this->uri = $uri;
|
28 |
-
parent::__construct($message, $httpStatus, $previous);
|
29 |
-
}
|
30 |
-
|
31 |
-
public function getUri()
|
32 |
-
{
|
33 |
-
return $this->uri;
|
34 |
-
}
|
35 |
-
|
36 |
-
public function getStatusCode()
|
37 |
-
{
|
38 |
-
return $this->getCode();
|
39 |
-
}
|
40 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents an HTTP transport error.
|
7 |
+
*/
|
8 |
+
class HttpException extends WebServiceException
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* The URI queried.
|
12 |
+
*/
|
13 |
+
private $uri;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @param string $message a message describing the error
|
17 |
+
* @param int $httpStatus the HTTP status code of the response
|
18 |
+
* @param string $uri the URI used in the request
|
19 |
+
* @param \Exception $previous the previous exception, if any
|
20 |
+
*/
|
21 |
+
public function __construct(
|
22 |
+
$message,
|
23 |
+
$httpStatus,
|
24 |
+
$uri,
|
25 |
+
\Exception $previous = null
|
26 |
+
) {
|
27 |
+
$this->uri = $uri;
|
28 |
+
parent::__construct($message, $httpStatus, $previous);
|
29 |
+
}
|
30 |
+
|
31 |
+
public function getUri()
|
32 |
+
{
|
33 |
+
return $this->uri;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function getStatusCode()
|
37 |
+
{
|
38 |
+
return $this->getCode();
|
39 |
+
}
|
40 |
+
}
|
includes/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Thrown when the account is out of credits.
|
7 |
-
*/
|
8 |
-
class InsufficientFundsException extends InvalidRequestException
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Thrown when the account is out of credits.
|
7 |
+
*/
|
8 |
+
class InsufficientFundsException extends InvalidRequestException
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents an error in creating the request to be sent to the
|
7 |
-
* web service. For example, if the array cannot be encoded as JSON or if there
|
8 |
-
* is a missing or invalid field.
|
9 |
-
*/
|
10 |
-
class InvalidInputException extends WebServiceException
|
11 |
-
{
|
12 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents an error in creating the request to be sent to the
|
7 |
+
* web service. For example, if the array cannot be encoded as JSON or if there
|
8 |
+
* is a missing or invalid field.
|
9 |
+
*/
|
10 |
+
class InvalidInputException extends WebServiceException
|
11 |
+
{
|
12 |
+
}
|
includes/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php
CHANGED
@@ -1,37 +1,37 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Thrown when a MaxMind web service returns an error relating to the request.
|
7 |
-
*/
|
8 |
-
class InvalidRequestException extends HttpException
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* The code returned by the MaxMind web service.
|
12 |
-
*/
|
13 |
-
private $error;
|
14 |
-
|
15 |
-
/**
|
16 |
-
* @param string $message the exception message
|
17 |
-
* @param int $error the error code returned by the MaxMind web service
|
18 |
-
* @param int $httpStatus the HTTP status code of the response
|
19 |
-
* @param string $uri the URI queries
|
20 |
-
* @param \Exception $previous the previous exception, if any
|
21 |
-
*/
|
22 |
-
public function __construct(
|
23 |
-
$message,
|
24 |
-
$error,
|
25 |
-
$httpStatus,
|
26 |
-
$uri,
|
27 |
-
\Exception $previous = null
|
28 |
-
) {
|
29 |
-
$this->error = $error;
|
30 |
-
parent::__construct($message, $httpStatus, $uri, $previous);
|
31 |
-
}
|
32 |
-
|
33 |
-
public function getErrorCode()
|
34 |
-
{
|
35 |
-
return $this->error;
|
36 |
-
}
|
37 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Thrown when a MaxMind web service returns an error relating to the request.
|
7 |
+
*/
|
8 |
+
class InvalidRequestException extends HttpException
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* The code returned by the MaxMind web service.
|
12 |
+
*/
|
13 |
+
private $error;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @param string $message the exception message
|
17 |
+
* @param int $error the error code returned by the MaxMind web service
|
18 |
+
* @param int $httpStatus the HTTP status code of the response
|
19 |
+
* @param string $uri the URI queries
|
20 |
+
* @param \Exception $previous the previous exception, if any
|
21 |
+
*/
|
22 |
+
public function __construct(
|
23 |
+
$message,
|
24 |
+
$error,
|
25 |
+
$httpStatus,
|
26 |
+
$uri,
|
27 |
+
\Exception $previous = null
|
28 |
+
) {
|
29 |
+
$this->error = $error;
|
30 |
+
parent::__construct($message, $httpStatus, $uri, $previous);
|
31 |
+
}
|
32 |
+
|
33 |
+
public function getErrorCode()
|
34 |
+
{
|
35 |
+
return $this->error;
|
36 |
+
}
|
37 |
+
}
|
includes/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
class IpAddressNotFoundException extends InvalidRequestException
|
6 |
-
{
|
7 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
class IpAddressNotFoundException extends InvalidRequestException
|
6 |
+
{
|
7 |
+
}
|
includes/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This exception is thrown when the service requires permission to access.
|
7 |
-
*/
|
8 |
-
class PermissionRequiredException extends InvalidRequestException
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This exception is thrown when the service requires permission to access.
|
7 |
+
*/
|
8 |
+
class PermissionRequiredException extends InvalidRequestException
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\Exception;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* This class represents a generic web service error.
|
7 |
-
*/
|
8 |
-
class WebServiceException extends \Exception
|
9 |
-
{
|
10 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This class represents a generic web service error.
|
7 |
+
*/
|
8 |
+
class WebServiceException extends \Exception
|
9 |
+
{
|
10 |
+
}
|
includes/vendor/maxmind/web-service-common/src/WebService/Client.php
CHANGED
@@ -1,472 +1,472 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\WebService;
|
4 |
-
|
5 |
-
use Composer\CaBundle\CaBundle;
|
6 |
-
use MaxMind\Exception\AuthenticationException;
|
7 |
-
use MaxMind\Exception\HttpException;
|
8 |
-
use MaxMind\Exception\InsufficientFundsException;
|
9 |
-
use MaxMind\Exception\InvalidInputException;
|
10 |
-
use MaxMind\Exception\InvalidRequestException;
|
11 |
-
use MaxMind\Exception\IpAddressNotFoundException;
|
12 |
-
use MaxMind\Exception\PermissionRequiredException;
|
13 |
-
use MaxMind\Exception\WebServiceException;
|
14 |
-
use MaxMind\WebService\Http\RequestFactory;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* This class is not intended to be used directly by an end-user of a
|
18 |
-
* MaxMind web service. Please use the appropriate client API for the service
|
19 |
-
* that you are using.
|
20 |
-
*
|
21 |
-
* @internal
|
22 |
-
*/
|
23 |
-
class Client
|
24 |
-
{
|
25 |
-
const VERSION = '0.2.0';
|
26 |
-
|
27 |
-
private $caBundle;
|
28 |
-
private $connectTimeout;
|
29 |
-
private $host = 'api.maxmind.com';
|
30 |
-
private $httpRequestFactory;
|
31 |
-
private $licenseKey;
|
32 |
-
private $proxy;
|
33 |
-
private $timeout;
|
34 |
-
private $userAgentPrefix;
|
35 |
-
private $accountId;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* @param int $accountId your MaxMind account ID
|
39 |
-
* @param string $licenseKey your MaxMind license key
|
40 |
-
* @param array $options an array of options. Possible keys:
|
41 |
-
* * `host` - The host to use when connecting to the web service.
|
42 |
-
* * `userAgent` - The prefix of the User-Agent to use in the request.
|
43 |
-
* * `caBundle` - The bundle of CA root certificates to use in the request.
|
44 |
-
* * `connectTimeout` - The connect timeout to use for the request.
|
45 |
-
* * `timeout` - The timeout to use for the request.
|
46 |
-
* * `proxy` - The HTTP proxy to use. May include a schema, port,
|
47 |
-
* username, and password, e.g., `http://username:password@127.0.0.1:10`.
|
48 |
-
*/
|
49 |
-
public function __construct(
|
50 |
-
$accountId,
|
51 |
-
$licenseKey,
|
52 |
-
$options = []
|
53 |
-
) {
|
54 |
-
$this->accountId = $accountId;
|
55 |
-
$this->licenseKey = $licenseKey;
|
56 |
-
|
57 |
-
$this->httpRequestFactory = isset($options['httpRequestFactory'])
|
58 |
-
? $options['httpRequestFactory']
|
59 |
-
: new RequestFactory();
|
60 |
-
|
61 |
-
if (isset($options['host'])) {
|
62 |
-
$this->host = $options['host'];
|
63 |
-
}
|
64 |
-
if (isset($options['userAgent'])) {
|
65 |
-
$this->userAgentPrefix = $options['userAgent'] . ' ';
|
66 |
-
}
|
67 |
-
|
68 |
-
$this->caBundle = isset($options['caBundle']) ?
|
69 |
-
$this->caBundle = $options['caBundle'] : $this->getCaBundle();
|
70 |
-
|
71 |
-
if (isset($options['connectTimeout'])) {
|
72 |
-
$this->connectTimeout = $options['connectTimeout'];
|
73 |
-
}
|
74 |
-
if (isset($options['timeout'])) {
|
75 |
-
$this->timeout = $options['timeout'];
|
76 |
-
}
|
77 |
-
|
78 |
-
if (isset($options['proxy'])) {
|
79 |
-
$this->proxy = $options['proxy'];
|
80 |
-
}
|
81 |
-
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* @param string $service name of the service querying
|
85 |
-
* @param string $path the URI path to use
|
86 |
-
* @param array $input the data to be posted as JSON
|
87 |
-
*
|
88 |
-
* @throws InvalidInputException when the request has missing or invalid
|
89 |
-
* data
|
90 |
-
* @throws AuthenticationException when there is an issue authenticating the
|
91 |
-
* request
|
92 |
-
* @throws InsufficientFundsException when your account is out of funds
|
93 |
-
* @throws InvalidRequestException when the request is invalid for some
|
94 |
-
* other reason, e.g., invalid JSON in the POST.
|
95 |
-
* @throws HttpException when an unexpected HTTP error occurs
|
96 |
-
* @throws WebServiceException when some other error occurs. This also
|
97 |
-
* serves as the base class for the above exceptions.
|
98 |
-
*
|
99 |
-
* @return array The decoded content of a successful response
|
100 |
-
*/
|
101 |
-
public function post($service, $path, $input)
|
102 |
-
{
|
103 |
-
$body = json_encode($input);
|
104 |
-
if ($body === false) {
|
105 |
-
throw new InvalidInputException(
|
106 |
-
'Error encoding input as JSON: '
|
107 |
-
. $this->jsonErrorDescription()
|
108 |
-
);
|
109 |
-
}
|
110 |
-
|
111 |
-
$request = $this->createRequest(
|
112 |
-
$path,
|
113 |
-
['Content-Type: application/json']
|
114 |
-
);
|
115 |
-
|
116 |
-
list($statusCode, $contentType, $body) = $request->post($body);
|
117 |
-
|
118 |
-
return $this->handleResponse(
|
119 |
-
$statusCode,
|
120 |
-
$contentType,
|
121 |
-
$body,
|
122 |
-
$service,
|
123 |
-
$path
|
124 |
-
);
|
125 |
-
}
|
126 |
-
|
127 |
-
public function get($service, $path)
|
128 |
-
{
|
129 |
-
$request = $this->createRequest($path);
|
130 |
-
|
131 |
-
list($statusCode, $contentType, $body) = $request->get();
|
132 |
-
|
133 |
-
return $this->handleResponse(
|
134 |
-
$statusCode,
|
135 |
-
$contentType,
|
136 |
-
$body,
|
137 |
-
$service,
|
138 |
-
$path
|
139 |
-
);
|
140 |
-
}
|
141 |
-
|
142 |
-
private function userAgent()
|
143 |
-
{
|
144 |
-
$curlVersion = curl_version();
|
145 |
-
|
146 |
-
return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . PHP_VERSION .
|
147 |
-
' curl/' . $curlVersion['version'];
|
148 |
-
}
|
149 |
-
|
150 |
-
private function createRequest($path, $headers = [])
|
151 |
-
{
|
152 |
-
array_push(
|
153 |
-
$headers,
|
154 |
-
'Authorization: Basic '
|
155 |
-
. base64_encode($this->accountId . ':' . $this->licenseKey),
|
156 |
-
'Accept: application/json'
|
157 |
-
);
|
158 |
-
|
159 |
-
return $this->httpRequestFactory->request(
|
160 |
-
$this->urlFor($path),
|
161 |
-
[
|
162 |
-
'caBundle' => $this->caBundle,
|
163 |
-
'connectTimeout' => $this->connectTimeout,
|
164 |
-
'headers' => $headers,
|
165 |
-
'proxy' => $this->proxy,
|
166 |
-
'timeout' => $this->timeout,
|
167 |
-
'userAgent' => $this->userAgent(),
|
168 |
-
]
|
169 |
-
);
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* @param int $statusCode the HTTP status code of the response
|
174 |
-
* @param string $contentType the Content-Type of the response
|
175 |
-
* @param string $body the response body
|
176 |
-
* @param string $service the name of the service
|
177 |
-
* @param string $path the path used in the request
|
178 |
-
*
|
179 |
-
* @throws AuthenticationException when there is an issue authenticating the
|
180 |
-
* request
|
181 |
-
* @throws InsufficientFundsException when your account is out of funds
|
182 |
-
* @throws InvalidRequestException when the request is invalid for some
|
183 |
-
* other reason, e.g., invalid JSON in the POST.
|
184 |
-
* @throws HttpException when an unexpected HTTP error occurs
|
185 |
-
* @throws WebServiceException when some other error occurs. This also
|
186 |
-
* serves as the base class for the above exceptions
|
187 |
-
*
|
188 |
-
* @return array The decoded content of a successful response
|
189 |
-
*/
|
190 |
-
private function handleResponse(
|
191 |
-
$statusCode,
|
192 |
-
$contentType,
|
193 |
-
$body,
|
194 |
-
$service,
|
195 |
-
$path
|
196 |
-
) {
|
197 |
-
if ($statusCode >= 400 && $statusCode <= 499) {
|
198 |
-
$this->handle4xx($statusCode, $contentType, $body, $service, $path);
|
199 |
-
} elseif ($statusCode >= 500) {
|
200 |
-
$this->handle5xx($statusCode, $service, $path);
|
201 |
-
} elseif ($statusCode !== 200) {
|
202 |
-
$this->handleUnexpectedStatus($statusCode, $service, $path);
|
203 |
-
}
|
204 |
-
|
205 |
-
return $this->handleSuccess($body, $service);
|
206 |
-
}
|
207 |
-
|
208 |
-
/**
|
209 |
-
* @return string describing the JSON error
|
210 |
-
*/
|
211 |
-
private function jsonErrorDescription()
|
212 |
-
{
|
213 |
-
$errno = json_last_error();
|
214 |
-
switch ($errno) {
|
215 |
-
case JSON_ERROR_DEPTH:
|
216 |
-
return 'The maximum stack depth has been exceeded.';
|
217 |
-
case JSON_ERROR_STATE_MISMATCH:
|
218 |
-
return 'Invalid or malformed JSON.';
|
219 |
-
case JSON_ERROR_CTRL_CHAR:
|
220 |
-
return 'Control character error.';
|
221 |
-
case JSON_ERROR_SYNTAX:
|
222 |
-
return 'Syntax error.';
|
223 |
-
case JSON_ERROR_UTF8:
|
224 |
-
return 'Malformed UTF-8 characters.';
|
225 |
-
default:
|
226 |
-
return "Other JSON error ($errno).";
|
227 |
-
}
|
228 |
-
}
|
229 |
-
|
230 |
-
/**
|
231 |
-
* @param string $path the path to use in the URL
|
232 |
-
*
|
233 |
-
* @return string the constructed URL
|
234 |
-
*/
|
235 |
-
private function urlFor($path)
|
236 |
-
{
|
237 |
-
return 'https://' . $this->host . $path;
|
238 |
-
}
|
239 |
-
|
240 |
-
/**
|
241 |
-
* @param int $statusCode the HTTP status code
|
242 |
-
* @param string $contentType the response content-type
|
243 |
-
* @param string $body the response body
|
244 |
-
* @param string $service the service name
|
245 |
-
* @param string $path the path used in the request
|
246 |
-
*
|
247 |
-
* @throws AuthenticationException
|
248 |
-
* @throws HttpException
|
249 |
-
* @throws InsufficientFundsException
|
250 |
-
* @throws InvalidRequestException
|
251 |
-
*/
|
252 |
-
private function handle4xx(
|
253 |
-
$statusCode,
|
254 |
-
$contentType,
|
255 |
-
$body,
|
256 |
-
$service,
|
257 |
-
$path
|
258 |
-
) {
|
259 |
-
if (strlen($body) === 0) {
|
260 |
-
throw new HttpException(
|
261 |
-
"Received a $statusCode error for $service with no body",
|
262 |
-
$statusCode,
|
263 |
-
$this->urlFor($path)
|
264 |
-
);
|
265 |
-
}
|
266 |
-
if (!strstr($contentType, 'json')) {
|
267 |
-
throw new HttpException(
|
268 |
-
"Received a $statusCode error for $service with " .
|
269 |
-
'the following body: ' . $body,
|
270 |
-
$statusCode,
|
271 |
-
$this->urlFor($path)
|
272 |
-
);
|
273 |
-
}
|
274 |
-
|
275 |
-
$message = json_decode($body, true);
|
276 |
-
if ($message === null) {
|
277 |
-
throw new HttpException(
|
278 |
-
"Received a $statusCode error for $service but could " .
|
279 |
-
'not decode the response as JSON: '
|
280 |
-
. $this->jsonErrorDescription() . ' Body: ' . $body,
|
281 |
-
$statusCode,
|
282 |
-
$this->urlFor($path)
|
283 |
-
);
|
284 |
-
}
|
285 |
-
|
286 |
-
if (!isset($message['code']) || !isset($message['error'])) {
|
287 |
-
throw new HttpException(
|
288 |
-
'Error response contains JSON but it does not ' .
|
289 |
-
'specify code or error keys: ' . $body,
|
290 |
-
$statusCode,
|
291 |
-
$this->urlFor($path)
|
292 |
-
);
|
293 |
-
}
|
294 |
-
|
295 |
-
$this->handleWebServiceError(
|
296 |
-
$message['error'],
|
297 |
-
$message['code'],
|
298 |
-
$statusCode,
|
299 |
-
$path
|
300 |
-
);
|
301 |
-
}
|
302 |
-
|
303 |
-
/**
|
304 |
-
* @param string $message the error message from the web service
|
305 |
-
* @param string $code the error code from the web service
|
306 |
-
* @param int $statusCode the HTTP status code
|
307 |
-
* @param string $path the path used in the request
|
308 |
-
*
|
309 |
-
* @throws AuthenticationException
|
310 |
-
* @throws InvalidRequestException
|
311 |
-
* @throws InsufficientFundsException
|
312 |
-
*/
|
313 |
-
private function handleWebServiceError(
|
314 |
-
$message,
|
315 |
-
$code,
|
316 |
-
$statusCode,
|
317 |
-
$path
|
318 |
-
) {
|
319 |
-
switch ($code) {
|
320 |
-
case 'IP_ADDRESS_NOT_FOUND':
|
321 |
-
case 'IP_ADDRESS_RESERVED':
|
322 |
-
throw new IpAddressNotFoundException(
|
323 |
-
$message,
|
324 |
-
$code,
|
325 |
-
$statusCode,
|
326 |
-
$this->urlFor($path)
|
327 |
-
);
|
328 |
-
case 'ACCOUNT_ID_REQUIRED':
|
329 |
-
case 'ACCOUNT_ID_UNKNOWN':
|
330 |
-
case 'AUTHORIZATION_INVALID':
|
331 |
-
case 'LICENSE_KEY_REQUIRED':
|
332 |
-
case 'USER_ID_REQUIRED':
|
333 |
-
case 'USER_ID_UNKNOWN':
|
334 |
-
throw new AuthenticationException(
|
335 |
-
$message,
|
336 |
-
$code,
|
337 |
-
$statusCode,
|
338 |
-
$this->urlFor($path)
|
339 |
-
);
|
340 |
-
case 'OUT_OF_QUERIES':
|
341 |
-
case 'INSUFFICIENT_FUNDS':
|
342 |
-
throw new InsufficientFundsException(
|
343 |
-
$message,
|
344 |
-
$code,
|
345 |
-
$statusCode,
|
346 |
-
$this->urlFor($path)
|
347 |
-
);
|
348 |
-
case 'PERMISSION_REQUIRED':
|
349 |
-
throw new PermissionRequiredException(
|
350 |
-
$message,
|
351 |
-
$code,
|
352 |
-
$statusCode,
|
353 |
-
$this->urlFor($path)
|
354 |
-
);
|
355 |
-
default:
|
356 |
-
throw new InvalidRequestException(
|
357 |
-
$message,
|
358 |
-
$code,
|
359 |
-
$statusCode,
|
360 |
-
$this->urlFor($path)
|
361 |
-
);
|
362 |
-
}
|
363 |
-
}
|
364 |
-
|
365 |
-
/**
|
366 |
-
* @param int $statusCode the HTTP status code
|
367 |
-
* @param string $service the service name
|
368 |
-
* @param string $path the URI path used in the request
|
369 |
-
*
|
370 |
-
* @throws HttpException
|
371 |
-
*/
|
372 |
-
private function handle5xx($statusCode, $service, $path)
|
373 |
-
{
|
374 |
-
throw new HttpException(
|
375 |
-
"Received a server error ($statusCode) for $service",
|
376 |
-
$statusCode,
|
377 |
-
$this->urlFor($path)
|
378 |
-
);
|
379 |
-
}
|
380 |
-
|
381 |
-
/**
|
382 |
-
* @param int $statusCode the HTTP status code
|
383 |
-
* @param string $service the service name
|
384 |
-
* @param string $path the URI path used in the request
|
385 |
-
*
|
386 |
-
* @throws HttpException
|
387 |
-
*/
|
388 |
-
private function handleUnexpectedStatus($statusCode, $service, $path)
|
389 |
-
{
|
390 |
-
throw new HttpException(
|
391 |
-
'Received an unexpected HTTP status ' .
|
392 |
-
"($statusCode) for $service",
|
393 |
-
$statusCode,
|
394 |
-
$this->urlFor($path)
|
395 |
-
);
|
396 |
-
}
|
397 |
-
|
398 |
-
/**
|
399 |
-
* @param string $body the successful request body
|
400 |
-
* @param string $service the service name
|
401 |
-
*
|
402 |
-
* @throws WebServiceException if the request body cannot be decoded as
|
403 |
-
* JSON
|
404 |
-
*
|
405 |
-
* @return array the decoded request body
|
406 |
-
*/
|
407 |
-
private function handleSuccess($body, $service)
|
408 |
-
{
|
409 |
-
if (strlen($body) === 0) {
|
410 |
-
throw new WebServiceException(
|
411 |
-
"Received a 200 response for $service but did not " .
|
412 |
-
'receive a HTTP body.'
|
413 |
-
);
|
414 |
-
}
|
415 |
-
|
416 |
-
$decodedContent = json_decode($body, true);
|
417 |
-
if ($decodedContent === null) {
|
418 |
-
throw new WebServiceException(
|
419 |
-
"Received a 200 response for $service but could " .
|
420 |
-
'not decode the response as JSON: '
|
421 |
-
. $this->jsonErrorDescription() . ' Body: ' . $body
|
422 |
-
);
|
423 |
-
}
|
424 |
-
|
425 |
-
return $decodedContent;
|
426 |
-
}
|
427 |
-
|
428 |
-
private function getCaBundle()
|
429 |
-
{
|
430 |
-
$curlVersion = curl_version();
|
431 |
-
|
432 |
-
// On OS X, when the SSL version is "SecureTransport", the system's
|
433 |
-
// keychain will be used.
|
434 |
-
if ($curlVersion['ssl_version'] === 'SecureTransport') {
|
435 |
-
return;
|
436 |
-
}
|
437 |
-
$cert = CaBundle::getSystemCaRootBundlePath();
|
438 |
-
|
439 |
-
// Check if the cert is inside a phar. If so, we need to copy the cert
|
440 |
-
// to a temp file so that curl can see it.
|
441 |
-
if (substr($cert, 0, 7) === 'phar://') {
|
442 |
-
$tempDir = sys_get_temp_dir();
|
443 |
-
$newCert = tempnam($tempDir, 'geoip2-');
|
444 |
-
if ($newCert === false) {
|
445 |
-
throw new \RuntimeException(
|
446 |
-
"Unable to create temporary file in $tempDir"
|
447 |
-
);
|
448 |
-
}
|
449 |
-
if (!copy($cert, $newCert)) {
|
450 |
-
throw new \RuntimeException(
|
451 |
-
"Could not copy $cert to $newCert: "
|
452 |
-
. var_export(error_get_last(), true)
|
453 |
-
);
|
454 |
-
}
|
455 |
-
|
456 |
-
// We use a shutdown function rather than the destructor as the
|
457 |
-
// destructor isn't called on a fatal error such as an uncaught
|
458 |
-
// exception.
|
459 |
-
register_shutdown_function(
|
460 |
-
function () use ($newCert) {
|
461 |
-
unlink($newCert);
|
462 |
-
}
|
463 |
-
);
|
464 |
-
$cert = $newCert;
|
465 |
-
}
|
466 |
-
if (!file_exists($cert)) {
|
467 |
-
throw new \RuntimeException("CA cert does not exist at $cert");
|
468 |
-
}
|
469 |
-
|
470 |
-
return $cert;
|
471 |
-
}
|
472 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\WebService;
|
4 |
+
|
5 |
+
use Composer\CaBundle\CaBundle;
|
6 |
+
use MaxMind\Exception\AuthenticationException;
|
7 |
+
use MaxMind\Exception\HttpException;
|
8 |
+
use MaxMind\Exception\InsufficientFundsException;
|
9 |
+
use MaxMind\Exception\InvalidInputException;
|
10 |
+
use MaxMind\Exception\InvalidRequestException;
|
11 |
+
use MaxMind\Exception\IpAddressNotFoundException;
|
12 |
+
use MaxMind\Exception\PermissionRequiredException;
|
13 |
+
use MaxMind\Exception\WebServiceException;
|
14 |
+
use MaxMind\WebService\Http\RequestFactory;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* This class is not intended to be used directly by an end-user of a
|
18 |
+
* MaxMind web service. Please use the appropriate client API for the service
|
19 |
+
* that you are using.
|
20 |
+
*
|
21 |
+
* @internal
|
22 |
+
*/
|
23 |
+
class Client
|
24 |
+
{
|
25 |
+
const VERSION = '0.2.0';
|
26 |
+
|
27 |
+
private $caBundle;
|
28 |
+
private $connectTimeout;
|
29 |
+
private $host = 'api.maxmind.com';
|
30 |
+
private $httpRequestFactory;
|
31 |
+
private $licenseKey;
|
32 |
+
private $proxy;
|
33 |
+
private $timeout;
|
34 |
+
private $userAgentPrefix;
|
35 |
+
private $accountId;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @param int $accountId your MaxMind account ID
|
39 |
+
* @param string $licenseKey your MaxMind license key
|
40 |
+
* @param array $options an array of options. Possible keys:
|
41 |
+
* * `host` - The host to use when connecting to the web service.
|
42 |
+
* * `userAgent` - The prefix of the User-Agent to use in the request.
|
43 |
+
* * `caBundle` - The bundle of CA root certificates to use in the request.
|
44 |
+
* * `connectTimeout` - The connect timeout to use for the request.
|
45 |
+
* * `timeout` - The timeout to use for the request.
|
46 |
+
* * `proxy` - The HTTP proxy to use. May include a schema, port,
|
47 |
+
* username, and password, e.g., `http://username:password@127.0.0.1:10`.
|
48 |
+
*/
|
49 |
+
public function __construct(
|
50 |
+
$accountId,
|
51 |
+
$licenseKey,
|
52 |
+
$options = []
|
53 |
+
) {
|
54 |
+
$this->accountId = $accountId;
|
55 |
+
$this->licenseKey = $licenseKey;
|
56 |
+
|
57 |
+
$this->httpRequestFactory = isset($options['httpRequestFactory'])
|
58 |
+
? $options['httpRequestFactory']
|
59 |
+
: new RequestFactory();
|
60 |
+
|
61 |
+
if (isset($options['host'])) {
|
62 |
+
$this->host = $options['host'];
|
63 |
+
}
|
64 |
+
if (isset($options['userAgent'])) {
|
65 |
+
$this->userAgentPrefix = $options['userAgent'] . ' ';
|
66 |
+
}
|
67 |
+
|
68 |
+
$this->caBundle = isset($options['caBundle']) ?
|
69 |
+
$this->caBundle = $options['caBundle'] : $this->getCaBundle();
|
70 |
+
|
71 |
+
if (isset($options['connectTimeout'])) {
|
72 |
+
$this->connectTimeout = $options['connectTimeout'];
|
73 |
+
}
|
74 |
+
if (isset($options['timeout'])) {
|
75 |
+
$this->timeout = $options['timeout'];
|
76 |
+
}
|
77 |
+
|
78 |
+
if (isset($options['proxy'])) {
|
79 |
+
$this->proxy = $options['proxy'];
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @param string $service name of the service querying
|
85 |
+
* @param string $path the URI path to use
|
86 |
+
* @param array $input the data to be posted as JSON
|
87 |
+
*
|
88 |
+
* @throws InvalidInputException when the request has missing or invalid
|
89 |
+
* data
|
90 |
+
* @throws AuthenticationException when there is an issue authenticating the
|
91 |
+
* request
|
92 |
+
* @throws InsufficientFundsException when your account is out of funds
|
93 |
+
* @throws InvalidRequestException when the request is invalid for some
|
94 |
+
* other reason, e.g., invalid JSON in the POST.
|
95 |
+
* @throws HttpException when an unexpected HTTP error occurs
|
96 |
+
* @throws WebServiceException when some other error occurs. This also
|
97 |
+
* serves as the base class for the above exceptions.
|
98 |
+
*
|
99 |
+
* @return array The decoded content of a successful response
|
100 |
+
*/
|
101 |
+
public function post($service, $path, $input)
|
102 |
+
{
|
103 |
+
$body = json_encode($input);
|
104 |
+
if ($body === false) {
|
105 |
+
throw new InvalidInputException(
|
106 |
+
'Error encoding input as JSON: '
|
107 |
+
. $this->jsonErrorDescription()
|
108 |
+
);
|
109 |
+
}
|
110 |
+
|
111 |
+
$request = $this->createRequest(
|
112 |
+
$path,
|
113 |
+
['Content-Type: application/json']
|
114 |
+
);
|
115 |
+
|
116 |
+
list($statusCode, $contentType, $body) = $request->post($body);
|
117 |
+
|
118 |
+
return $this->handleResponse(
|
119 |
+
$statusCode,
|
120 |
+
$contentType,
|
121 |
+
$body,
|
122 |
+
$service,
|
123 |
+
$path
|
124 |
+
);
|
125 |
+
}
|
126 |
+
|
127 |
+
public function get($service, $path)
|
128 |
+
{
|
129 |
+
$request = $this->createRequest($path);
|
130 |
+
|
131 |
+
list($statusCode, $contentType, $body) = $request->get();
|
132 |
+
|
133 |
+
return $this->handleResponse(
|
134 |
+
$statusCode,
|
135 |
+
$contentType,
|
136 |
+
$body,
|
137 |
+
$service,
|
138 |
+
$path
|
139 |
+
);
|
140 |
+
}
|
141 |
+
|
142 |
+
private function userAgent()
|
143 |
+
{
|
144 |
+
$curlVersion = curl_version();
|
145 |
+
|
146 |
+
return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . PHP_VERSION .
|
147 |
+
' curl/' . $curlVersion['version'];
|
148 |
+
}
|
149 |
+
|
150 |
+
private function createRequest($path, $headers = [])
|
151 |
+
{
|
152 |
+
array_push(
|
153 |
+
$headers,
|
154 |
+
'Authorization: Basic '
|
155 |
+
. base64_encode($this->accountId . ':' . $this->licenseKey),
|
156 |
+
'Accept: application/json'
|
157 |
+
);
|
158 |
+
|
159 |
+
return $this->httpRequestFactory->request(
|
160 |
+
$this->urlFor($path),
|
161 |
+
[
|
162 |
+
'caBundle' => $this->caBundle,
|
163 |
+
'connectTimeout' => $this->connectTimeout,
|
164 |
+
'headers' => $headers,
|
165 |
+
'proxy' => $this->proxy,
|
166 |
+
'timeout' => $this->timeout,
|
167 |
+
'userAgent' => $this->userAgent(),
|
168 |
+
]
|
169 |
+
);
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* @param int $statusCode the HTTP status code of the response
|
174 |
+
* @param string $contentType the Content-Type of the response
|
175 |
+
* @param string $body the response body
|
176 |
+
* @param string $service the name of the service
|
177 |
+
* @param string $path the path used in the request
|
178 |
+
*
|
179 |
+
* @throws AuthenticationException when there is an issue authenticating the
|
180 |
+
* request
|
181 |
+
* @throws InsufficientFundsException when your account is out of funds
|
182 |
+
* @throws InvalidRequestException when the request is invalid for some
|
183 |
+
* other reason, e.g., invalid JSON in the POST.
|
184 |
+
* @throws HttpException when an unexpected HTTP error occurs
|
185 |
+
* @throws WebServiceException when some other error occurs. This also
|
186 |
+
* serves as the base class for the above exceptions
|
187 |
+
*
|
188 |
+
* @return array The decoded content of a successful response
|
189 |
+
*/
|
190 |
+
private function handleResponse(
|
191 |
+
$statusCode,
|
192 |
+
$contentType,
|
193 |
+
$body,
|
194 |
+
$service,
|
195 |
+
$path
|
196 |
+
) {
|
197 |
+
if ($statusCode >= 400 && $statusCode <= 499) {
|
198 |
+
$this->handle4xx($statusCode, $contentType, $body, $service, $path);
|
199 |
+
} elseif ($statusCode >= 500) {
|
200 |
+
$this->handle5xx($statusCode, $service, $path);
|
201 |
+
} elseif ($statusCode !== 200) {
|
202 |
+
$this->handleUnexpectedStatus($statusCode, $service, $path);
|
203 |
+
}
|
204 |
+
|
205 |
+
return $this->handleSuccess($body, $service);
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* @return string describing the JSON error
|
210 |
+
*/
|
211 |
+
private function jsonErrorDescription()
|
212 |
+
{
|
213 |
+
$errno = json_last_error();
|
214 |
+
switch ($errno) {
|
215 |
+
case JSON_ERROR_DEPTH:
|
216 |
+
return 'The maximum stack depth has been exceeded.';
|
217 |
+
case JSON_ERROR_STATE_MISMATCH:
|
218 |
+
return 'Invalid or malformed JSON.';
|
219 |
+
case JSON_ERROR_CTRL_CHAR:
|
220 |
+
return 'Control character error.';
|
221 |
+
case JSON_ERROR_SYNTAX:
|
222 |
+
return 'Syntax error.';
|
223 |
+
case JSON_ERROR_UTF8:
|
224 |
+
return 'Malformed UTF-8 characters.';
|
225 |
+
default:
|
226 |
+
return "Other JSON error ($errno).";
|
227 |
+
}
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* @param string $path the path to use in the URL
|
232 |
+
*
|
233 |
+
* @return string the constructed URL
|
234 |
+
*/
|
235 |
+
private function urlFor($path)
|
236 |
+
{
|
237 |
+
return 'https://' . $this->host . $path;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* @param int $statusCode the HTTP status code
|
242 |
+
* @param string $contentType the response content-type
|
243 |
+
* @param string $body the response body
|
244 |
+
* @param string $service the service name
|
245 |
+
* @param string $path the path used in the request
|
246 |
+
*
|
247 |
+
* @throws AuthenticationException
|
248 |
+
* @throws HttpException
|
249 |
+
* @throws InsufficientFundsException
|
250 |
+
* @throws InvalidRequestException
|
251 |
+
*/
|
252 |
+
private function handle4xx(
|
253 |
+
$statusCode,
|
254 |
+
$contentType,
|
255 |
+
$body,
|
256 |
+
$service,
|
257 |
+
$path
|
258 |
+
) {
|
259 |
+
if (strlen($body) === 0) {
|
260 |
+
throw new HttpException(
|
261 |
+
"Received a $statusCode error for $service with no body",
|
262 |
+
$statusCode,
|
263 |
+
$this->urlFor($path)
|
264 |
+
);
|
265 |
+
}
|
266 |
+
if (!strstr($contentType, 'json')) {
|
267 |
+
throw new HttpException(
|
268 |
+
"Received a $statusCode error for $service with " .
|
269 |
+
'the following body: ' . $body,
|
270 |
+
$statusCode,
|
271 |
+
$this->urlFor($path)
|
272 |
+
);
|
273 |
+
}
|
274 |
+
|
275 |
+
$message = json_decode($body, true);
|
276 |
+
if ($message === null) {
|
277 |
+
throw new HttpException(
|
278 |
+
"Received a $statusCode error for $service but could " .
|
279 |
+
'not decode the response as JSON: '
|
280 |
+
. $this->jsonErrorDescription() . ' Body: ' . $body,
|
281 |
+
$statusCode,
|
282 |
+
$this->urlFor($path)
|
283 |
+
);
|
284 |
+
}
|
285 |
+
|
286 |
+
if (!isset($message['code']) || !isset($message['error'])) {
|
287 |
+
throw new HttpException(
|
288 |
+
'Error response contains JSON but it does not ' .
|
289 |
+
'specify code or error keys: ' . $body,
|
290 |
+
$statusCode,
|
291 |
+
$this->urlFor($path)
|
292 |
+
);
|
293 |
+
}
|
294 |
+
|
295 |
+
$this->handleWebServiceError(
|
296 |
+
$message['error'],
|
297 |
+
$message['code'],
|
298 |
+
$statusCode,
|
299 |
+
$path
|
300 |
+
);
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
* @param string $message the error message from the web service
|
305 |
+
* @param string $code the error code from the web service
|
306 |
+
* @param int $statusCode the HTTP status code
|
307 |
+
* @param string $path the path used in the request
|
308 |
+
*
|
309 |
+
* @throws AuthenticationException
|
310 |
+
* @throws InvalidRequestException
|
311 |
+
* @throws InsufficientFundsException
|
312 |
+
*/
|
313 |
+
private function handleWebServiceError(
|
314 |
+
$message,
|
315 |
+
$code,
|
316 |
+
$statusCode,
|
317 |
+
$path
|
318 |
+
) {
|
319 |
+
switch ($code) {
|
320 |
+
case 'IP_ADDRESS_NOT_FOUND':
|
321 |
+
case 'IP_ADDRESS_RESERVED':
|
322 |
+
throw new IpAddressNotFoundException(
|
323 |
+
$message,
|
324 |
+
$code,
|
325 |
+
$statusCode,
|
326 |
+
$this->urlFor($path)
|
327 |
+
);
|
328 |
+
case 'ACCOUNT_ID_REQUIRED':
|
329 |
+
case 'ACCOUNT_ID_UNKNOWN':
|
330 |
+
case 'AUTHORIZATION_INVALID':
|
331 |
+
case 'LICENSE_KEY_REQUIRED':
|
332 |
+
case 'USER_ID_REQUIRED':
|
333 |
+
case 'USER_ID_UNKNOWN':
|
334 |
+
throw new AuthenticationException(
|
335 |
+
$message,
|
336 |
+
$code,
|
337 |
+
$statusCode,
|
338 |
+
$this->urlFor($path)
|
339 |
+
);
|
340 |
+
case 'OUT_OF_QUERIES':
|
341 |
+
case 'INSUFFICIENT_FUNDS':
|
342 |
+
throw new InsufficientFundsException(
|
343 |
+
$message,
|
344 |
+
$code,
|
345 |
+
$statusCode,
|
346 |
+
$this->urlFor($path)
|
347 |
+
);
|
348 |
+
case 'PERMISSION_REQUIRED':
|
349 |
+
throw new PermissionRequiredException(
|
350 |
+
$message,
|
351 |
+
$code,
|
352 |
+
$statusCode,
|
353 |
+
$this->urlFor($path)
|
354 |
+
);
|
355 |
+
default:
|
356 |
+
throw new InvalidRequestException(
|
357 |
+
$message,
|
358 |
+
$code,
|
359 |
+
$statusCode,
|
360 |
+
$this->urlFor($path)
|
361 |
+
);
|
362 |
+
}
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* @param int $statusCode the HTTP status code
|
367 |
+
* @param string $service the service name
|
368 |
+
* @param string $path the URI path used in the request
|
369 |
+
*
|
370 |
+
* @throws HttpException
|
371 |
+
*/
|
372 |
+
private function handle5xx($statusCode, $service, $path)
|
373 |
+
{
|
374 |
+
throw new HttpException(
|
375 |
+
"Received a server error ($statusCode) for $service",
|
376 |
+
$statusCode,
|
377 |
+
$this->urlFor($path)
|
378 |
+
);
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* @param int $statusCode the HTTP status code
|
383 |
+
* @param string $service the service name
|
384 |
+
* @param string $path the URI path used in the request
|
385 |
+
*
|
386 |
+
* @throws HttpException
|
387 |
+
*/
|
388 |
+
private function handleUnexpectedStatus($statusCode, $service, $path)
|
389 |
+
{
|
390 |
+
throw new HttpException(
|
391 |
+
'Received an unexpected HTTP status ' .
|
392 |
+
"($statusCode) for $service",
|
393 |
+
$statusCode,
|
394 |
+
$this->urlFor($path)
|
395 |
+
);
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* @param string $body the successful request body
|
400 |
+
* @param string $service the service name
|
401 |
+
*
|
402 |
+
* @throws WebServiceException if the request body cannot be decoded as
|
403 |
+
* JSON
|
404 |
+
*
|
405 |
+
* @return array the decoded request body
|
406 |
+
*/
|
407 |
+
private function handleSuccess($body, $service)
|
408 |
+
{
|
409 |
+
if (strlen($body) === 0) {
|
410 |
+
throw new WebServiceException(
|
411 |
+
"Received a 200 response for $service but did not " .
|
412 |
+
'receive a HTTP body.'
|
413 |
+
);
|
414 |
+
}
|
415 |
+
|
416 |
+
$decodedContent = json_decode($body, true);
|
417 |
+
if ($decodedContent === null) {
|
418 |
+
throw new WebServiceException(
|
419 |
+
"Received a 200 response for $service but could " .
|
420 |
+
'not decode the response as JSON: '
|
421 |
+
. $this->jsonErrorDescription() . ' Body: ' . $body
|
422 |
+
);
|
423 |
+
}
|
424 |
+
|
425 |
+
return $decodedContent;
|
426 |
+
}
|
427 |
+
|
428 |
+
private function getCaBundle()
|
429 |
+
{
|
430 |
+
$curlVersion = curl_version();
|
431 |
+
|
432 |
+
// On OS X, when the SSL version is "SecureTransport", the system's
|
433 |
+
// keychain will be used.
|
434 |
+
if ($curlVersion['ssl_version'] === 'SecureTransport') {
|
435 |
+
return;
|
436 |
+
}
|
437 |
+
$cert = CaBundle::getSystemCaRootBundlePath();
|
438 |
+
|
439 |
+
// Check if the cert is inside a phar. If so, we need to copy the cert
|
440 |
+
// to a temp file so that curl can see it.
|
441 |
+
if (substr($cert, 0, 7) === 'phar://') {
|
442 |
+
$tempDir = sys_get_temp_dir();
|
443 |
+
$newCert = tempnam($tempDir, 'geoip2-');
|
444 |
+
if ($newCert === false) {
|
445 |
+
throw new \RuntimeException(
|
446 |
+
"Unable to create temporary file in $tempDir"
|
447 |
+
);
|
448 |
+
}
|
449 |
+
if (!copy($cert, $newCert)) {
|
450 |
+
throw new \RuntimeException(
|
451 |
+
"Could not copy $cert to $newCert: "
|
452 |
+
. var_export(error_get_last(), true)
|
453 |
+
);
|
454 |
+
}
|
455 |
+
|
456 |
+
// We use a shutdown function rather than the destructor as the
|
457 |
+
// destructor isn't called on a fatal error such as an uncaught
|
458 |
+
// exception.
|
459 |
+
register_shutdown_function(
|
460 |
+
function () use ($newCert) {
|
461 |
+
unlink($newCert);
|
462 |
+
}
|
463 |
+
);
|
464 |
+
$cert = $newCert;
|
465 |
+
}
|
466 |
+
if (!file_exists($cert)) {
|
467 |
+
throw new \RuntimeException("CA cert does not exist at $cert");
|
468 |
+
}
|
469 |
+
|
470 |
+
return $cert;
|
471 |
+
}
|
472 |
+
}
|
includes/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php
CHANGED
@@ -1,110 +1,110 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\WebService\Http;
|
4 |
-
|
5 |
-
use MaxMind\Exception\HttpException;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* This class is for internal use only. Semantic versioning does not not apply.
|
9 |
-
*
|
10 |
-
* @internal
|
11 |
-
*/
|
12 |
-
class CurlRequest implements Request
|
13 |
-
{
|
14 |
-
private $url;
|
15 |
-
private $options;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @param $url
|
19 |
-
* @param $options
|
20 |
-
*/
|
21 |
-
public function __construct($url, $options)
|
22 |
-
{
|
23 |
-
$this->url = $url;
|
24 |
-
$this->options = $options;
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @param $body
|
29 |
-
*
|
30 |
-
* @return array
|
31 |
-
*/
|
32 |
-
public function post($body)
|
33 |
-
{
|
34 |
-
$curl = $this->createCurl();
|
35 |
-
|
36 |
-
curl_setopt($curl, CURLOPT_POST, true);
|
37 |
-
curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
|
38 |
-
|
39 |
-
return $this->execute($curl);
|
40 |
-
}
|
41 |
-
|
42 |
-
public function get()
|
43 |
-
{
|
44 |
-
$curl = $this->createCurl();
|
45 |
-
|
46 |
-
curl_setopt($curl, CURLOPT_HTTPGET, true);
|
47 |
-
|
48 |
-
return $this->execute($curl);
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* @return resource
|
53 |
-
*/
|
54 |
-
private function createCurl()
|
55 |
-
{
|
56 |
-
$curl = curl_init($this->url);
|
57 |
-
|
58 |
-
if (!empty($this->options['caBundle'])) {
|
59 |
-
$opts[CURLOPT_CAINFO] = $this->options['caBundle'];
|
60 |
-
}
|
61 |
-
$opts[CURLOPT_SSL_VERIFYHOST] = 2;
|
62 |
-
$opts[CURLOPT_FOLLOWLOCATION] = false;
|
63 |
-
$opts[CURLOPT_SSL_VERIFYPEER] = true;
|
64 |
-
$opts[CURLOPT_RETURNTRANSFER] = true;
|
65 |
-
|
66 |
-
$opts[CURLOPT_HTTPHEADER] = $this->options['headers'];
|
67 |
-
$opts[CURLOPT_USERAGENT] = $this->options['userAgent'];
|
68 |
-
$opts[CURLOPT_PROXY] = $this->options['proxy'];
|
69 |
-
|
70 |
-
// The defined()s are here as the *_MS opts are not available on older
|
71 |
-
// cURL versions
|
72 |
-
$connectTimeout = $this->options['connectTimeout'];
|
73 |
-
if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
|
74 |
-
$opts[CURLOPT_CONNECTTIMEOUT_MS] = ceil($connectTimeout * 1000);
|
75 |
-
} else {
|
76 |
-
$opts[CURLOPT_CONNECTTIMEOUT] = ceil($connectTimeout);
|
77 |
-
}
|
78 |
-
|
79 |
-
$timeout = $this->options['timeout'];
|
80 |
-
if (defined('CURLOPT_TIMEOUT_MS')) {
|
81 |
-
$opts[CURLOPT_TIMEOUT_MS] = ceil($timeout * 1000);
|
82 |
-
} else {
|
83 |
-
$opts[CURLOPT_TIMEOUT] = ceil($timeout);
|
84 |
-
}
|
85 |
-
|
86 |
-
curl_setopt_array($curl, $opts);
|
87 |
-
|
88 |
-
return $curl;
|
89 |
-
}
|
90 |
-
|
91 |
-
private function execute($curl)
|
92 |
-
{
|
93 |
-
$body = curl_exec($curl);
|
94 |
-
if ($errno = curl_errno($curl)) {
|
95 |
-
$errorMessage = curl_error($curl);
|
96 |
-
|
97 |
-
throw new HttpException(
|
98 |
-
"cURL error ({$errno}): {$errorMessage}",
|
99 |
-
0,
|
100 |
-
$this->url
|
101 |
-
);
|
102 |
-
}
|
103 |
-
|
104 |
-
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
105 |
-
$contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
106 |
-
curl_close($curl);
|
107 |
-
|
108 |
-
return [$statusCode, $contentType, $body];
|
109 |
-
}
|
110 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\WebService\Http;
|
4 |
+
|
5 |
+
use MaxMind\Exception\HttpException;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* This class is for internal use only. Semantic versioning does not not apply.
|
9 |
+
*
|
10 |
+
* @internal
|
11 |
+
*/
|
12 |
+
class CurlRequest implements Request
|
13 |
+
{
|
14 |
+
private $url;
|
15 |
+
private $options;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param $url
|
19 |
+
* @param $options
|
20 |
+
*/
|
21 |
+
public function __construct($url, $options)
|
22 |
+
{
|
23 |
+
$this->url = $url;
|
24 |
+
$this->options = $options;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @param $body
|
29 |
+
*
|
30 |
+
* @return array
|
31 |
+
*/
|
32 |
+
public function post($body)
|
33 |
+
{
|
34 |
+
$curl = $this->createCurl();
|
35 |
+
|
36 |
+
curl_setopt($curl, CURLOPT_POST, true);
|
37 |
+
curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
|
38 |
+
|
39 |
+
return $this->execute($curl);
|
40 |
+
}
|
41 |
+
|
42 |
+
public function get()
|
43 |
+
{
|
44 |
+
$curl = $this->createCurl();
|
45 |
+
|
46 |
+
curl_setopt($curl, CURLOPT_HTTPGET, true);
|
47 |
+
|
48 |
+
return $this->execute($curl);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @return resource
|
53 |
+
*/
|
54 |
+
private function createCurl()
|
55 |
+
{
|
56 |
+
$curl = curl_init($this->url);
|
57 |
+
|
58 |
+
if (!empty($this->options['caBundle'])) {
|
59 |
+
$opts[CURLOPT_CAINFO] = $this->options['caBundle'];
|
60 |
+
}
|
61 |
+
$opts[CURLOPT_SSL_VERIFYHOST] = 2;
|
62 |
+
$opts[CURLOPT_FOLLOWLOCATION] = false;
|
63 |
+
$opts[CURLOPT_SSL_VERIFYPEER] = true;
|
64 |
+
$opts[CURLOPT_RETURNTRANSFER] = true;
|
65 |
+
|
66 |
+
$opts[CURLOPT_HTTPHEADER] = $this->options['headers'];
|
67 |
+
$opts[CURLOPT_USERAGENT] = $this->options['userAgent'];
|
68 |
+
$opts[CURLOPT_PROXY] = $this->options['proxy'];
|
69 |
+
|
70 |
+
// The defined()s are here as the *_MS opts are not available on older
|
71 |
+
// cURL versions
|
72 |
+
$connectTimeout = $this->options['connectTimeout'];
|
73 |
+
if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
|
74 |
+
$opts[CURLOPT_CONNECTTIMEOUT_MS] = ceil($connectTimeout * 1000);
|
75 |
+
} else {
|
76 |
+
$opts[CURLOPT_CONNECTTIMEOUT] = ceil($connectTimeout);
|
77 |
+
}
|
78 |
+
|
79 |
+
$timeout = $this->options['timeout'];
|
80 |
+
if (defined('CURLOPT_TIMEOUT_MS')) {
|
81 |
+
$opts[CURLOPT_TIMEOUT_MS] = ceil($timeout * 1000);
|
82 |
+
} else {
|
83 |
+
$opts[CURLOPT_TIMEOUT] = ceil($timeout);
|
84 |
+
}
|
85 |
+
|
86 |
+
curl_setopt_array($curl, $opts);
|
87 |
+
|
88 |
+
return $curl;
|
89 |
+
}
|
90 |
+
|
91 |
+
private function execute($curl)
|
92 |
+
{
|
93 |
+
$body = curl_exec($curl);
|
94 |
+
if ($errno = curl_errno($curl)) {
|
95 |
+
$errorMessage = curl_error($curl);
|
96 |
+
|
97 |
+
throw new HttpException(
|
98 |
+
"cURL error ({$errno}): {$errorMessage}",
|
99 |
+
0,
|
100 |
+
$this->url
|
101 |
+
);
|
102 |
+
}
|
103 |
+
|
104 |
+
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
105 |
+
$contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
106 |
+
curl_close($curl);
|
107 |
+
|
108 |
+
return [$statusCode, $contentType, $body];
|
109 |
+
}
|
110 |
+
}
|
includes/vendor/maxmind/web-service-common/src/WebService/Http/Request.php
CHANGED
@@ -1,29 +1,29 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\WebService\Http;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Interface Request.
|
7 |
-
*
|
8 |
-
* @internal
|
9 |
-
*/
|
10 |
-
interface Request
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* @param $url
|
14 |
-
* @param $options
|
15 |
-
*/
|
16 |
-
public function __construct($url, $options);
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @param $body
|
20 |
-
*
|
21 |
-
* @return mixed
|
22 |
-
*/
|
23 |
-
public function post($body);
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @return mixed
|
27 |
-
*/
|
28 |
-
public function get();
|
29 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\WebService\Http;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Interface Request.
|
7 |
+
*
|
8 |
+
* @internal
|
9 |
+
*/
|
10 |
+
interface Request
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @param $url
|
14 |
+
* @param $options
|
15 |
+
*/
|
16 |
+
public function __construct($url, $options);
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param $body
|
20 |
+
*
|
21 |
+
* @return mixed
|
22 |
+
*/
|
23 |
+
public function post($body);
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return mixed
|
27 |
+
*/
|
28 |
+
public function get();
|
29 |
+
}
|
includes/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php
CHANGED
@@ -1,26 +1,26 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MaxMind\WebService\Http;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class RequestFactory.
|
7 |
-
*
|
8 |
-
* @internal
|
9 |
-
*/
|
10 |
-
class RequestFactory
|
11 |
-
{
|
12 |
-
public function __construct()
|
13 |
-
{
|
14 |
-
}
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @param $url
|
18 |
-
* @param $options
|
19 |
-
*
|
20 |
-
* @return CurlRequest
|
21 |
-
*/
|
22 |
-
public function request($url, $options)
|
23 |
-
{
|
24 |
-
return new CurlRequest($url, $options);
|
25 |
-
}
|
26 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MaxMind\WebService\Http;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class RequestFactory.
|
7 |
+
*
|
8 |
+
* @internal
|
9 |
+
*/
|
10 |
+
class RequestFactory
|
11 |
+
{
|
12 |
+
public function __construct()
|
13 |
+
{
|
14 |
+
}
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @param $url
|
18 |
+
* @param $options
|
19 |
+
*
|
20 |
+
* @return CurlRequest
|
21 |
+
*/
|
22 |
+
public function request($url, $options)
|
23 |
+
{
|
24 |
+
return new CurlRequest($url, $options);
|
25 |
+
}
|
26 |
+
}
|
readme.txt
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
=== WP Statistics ===
|
2 |
-
Contributors: mostafa.s1990, GregRoss, dedidata
|
3 |
Donate link: https://wp-statistics.com/donate/
|
4 |
Tags: analytics, wordpress analytics, stats, statistics, visit, visitors, hits, chart, browser, today, yesterday, week, month, year, total, post, page, sidebar, google, live visit, search word, agent, google analytics, webmasters, google webmasters, geoip, location
|
5 |
Requires at least: 3.0
|
6 |
Tested up to: 4.9
|
7 |
-
Stable tag: 12.5.
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
@@ -113,6 +113,9 @@ We implement GDPR into the WP-Statistics. for more information read [the blog po
|
|
113 |
Important: with this update, Opt-out feature is removed.
|
114 |
|
115 |
== Changelog ==
|
|
|
|
|
|
|
116 |
= 12.5.1 =
|
117 |
* Added: Cache option for support when the cache enabled in the WordPress.
|
118 |
* Added: Visitor's city name with GeoIP, you can enable the city name in Settings > Externals > GeoIP City
|
1 |
=== WP Statistics ===
|
2 |
+
Contributors: mostafa.s1990, mehrshaddarzi, ghasemi71ir, GregRoss, dedidata
|
3 |
Donate link: https://wp-statistics.com/donate/
|
4 |
Tags: analytics, wordpress analytics, stats, statistics, visit, visitors, hits, chart, browser, today, yesterday, week, month, year, total, post, page, sidebar, google, live visit, search word, agent, google analytics, webmasters, google webmasters, geoip, location
|
5 |
Requires at least: 3.0
|
6 |
Tested up to: 4.9
|
7 |
+
Stable tag: 12.5.2
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
113 |
Important: with this update, Opt-out feature is removed.
|
114 |
|
115 |
== Changelog ==
|
116 |
+
= 12.5.2 =
|
117 |
+
* Improved: Some issues in php v5.4
|
118 |
+
|
119 |
= 12.5.1 =
|
120 |
* Added: Cache option for support when the cache enabled in the WordPress.
|
121 |
* Added: Visitor's city name with GeoIP, you can enable the city name in Settings > Externals > GeoIP City
|
wp-statistics.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: WP Statistics
|
4 |
* Plugin URI: https://wp-statistics.com/
|
5 |
* Description: Complete WordPress Analytics and Statistics for your site!
|
6 |
-
* Version: 12.5.
|
7 |
* Author: Verona Labs
|
8 |
* Author URI: http://veronalabs.com/
|
9 |
*
|
3 |
* Plugin Name: WP Statistics
|
4 |
* Plugin URI: https://wp-statistics.com/
|
5 |
* Description: Complete WordPress Analytics and Statistics for your site!
|
6 |
+
* Version: 12.5.2
|
7 |
* Author: Verona Labs
|
8 |
* Author URI: http://veronalabs.com/
|
9 |
*
|