Changeset 3160131
- Timestamp:
- 09/30/2024 10:30:03 PM (18 months ago)
- Location:
- termageddon-usercentrics
- Files:
-
- 154 added
- 71 edited
-
tags/v1.5.0 (added)
-
tags/v1.5.0/LICENSE.txt (added)
-
tags/v1.5.0/README.txt (added)
-
tags/v1.5.0/admin (added)
-
tags/v1.5.0/admin/class-termageddon-usercentrics-admin.php (added)
-
tags/v1.5.0/admin/css (added)
-
tags/v1.5.0/admin/css/termageddon-usercentrics-admin.css (added)
-
tags/v1.5.0/admin/css/termageddon-usercentrics-admin.min.css (added)
-
tags/v1.5.0/admin/index.php (added)
-
tags/v1.5.0/admin/js (added)
-
tags/v1.5.0/admin/js/termageddon-usercentrics-admin.js (added)
-
tags/v1.5.0/admin/js/termageddon-usercentrics-admin.min.js (added)
-
tags/v1.5.0/composer.json (added)
-
tags/v1.5.0/composer.lock (added)
-
tags/v1.5.0/includes (added)
-
tags/v1.5.0/includes/class-termageddon-usercentrics-activator.php (added)
-
tags/v1.5.0/includes/class-termageddon-usercentrics-deactivator.php (added)
-
tags/v1.5.0/includes/class-termageddon-usercentrics-i18n.php (added)
-
tags/v1.5.0/includes/class-termageddon-usercentrics-loader.php (added)
-
tags/v1.5.0/includes/class-termageddon-usercentrics.php (added)
-
tags/v1.5.0/includes/index.php (added)
-
tags/v1.5.0/index.php (added)
-
tags/v1.5.0/languages (added)
-
tags/v1.5.0/languages/termageddon-usercentrics-en_US.mo (added)
-
tags/v1.5.0/languages/termageddon-usercentrics-en_US.po (added)
-
tags/v1.5.0/languages/termageddon-usercentrics.pot (added)
-
tags/v1.5.0/public (added)
-
tags/v1.5.0/public/class-termageddon-usercentrics-public.php (added)
-
tags/v1.5.0/public/index.php (added)
-
tags/v1.5.0/public/js (added)
-
tags/v1.5.0/public/js/termageddon-usercentrics-ajax.js (added)
-
tags/v1.5.0/public/js/termageddon-usercentrics-ajax.min.js (added)
-
tags/v1.5.0/termageddon-usercentrics.code-workspace (added)
-
tags/v1.5.0/termageddon-usercentrics.php (added)
-
tags/v1.5.0/uninstall.php (added)
-
tags/v1.5.0/vendor (added)
-
tags/v1.5.0/vendor/autoload.php (added)
-
tags/v1.5.0/vendor/bin (added)
-
tags/v1.5.0/vendor/composer (added)
-
tags/v1.5.0/vendor/composer/ClassLoader.php (added)
-
tags/v1.5.0/vendor/composer/InstalledVersions.php (added)
-
tags/v1.5.0/vendor/composer/LICENSE (added)
-
tags/v1.5.0/vendor/composer/autoload_classmap.php (added)
-
tags/v1.5.0/vendor/composer/autoload_namespaces.php (added)
-
tags/v1.5.0/vendor/composer/autoload_psr4.php (added)
-
tags/v1.5.0/vendor/composer/autoload_real.php (added)
-
tags/v1.5.0/vendor/composer/autoload_static.php (added)
-
tags/v1.5.0/vendor/composer/ca-bundle (added)
-
tags/v1.5.0/vendor/composer/ca-bundle/LICENSE (added)
-
tags/v1.5.0/vendor/composer/ca-bundle/README.md (added)
-
tags/v1.5.0/vendor/composer/ca-bundle/composer.json (added)
-
tags/v1.5.0/vendor/composer/ca-bundle/res (added)
-
tags/v1.5.0/vendor/composer/ca-bundle/res/cacert.pem (added)
-
tags/v1.5.0/vendor/composer/ca-bundle/src (added)
-
tags/v1.5.0/vendor/composer/ca-bundle/src/CaBundle.php (added)
-
tags/v1.5.0/vendor/composer/installed.json (added)
-
tags/v1.5.0/vendor/composer/installed.php (added)
-
tags/v1.5.0/vendor/composer/platform_check.php (added)
-
tags/v1.5.0/vendor/geoip2 (added)
-
tags/v1.5.0/vendor/geoip2/geoip2 (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/CHANGELOG.md (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/LICENSE (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/README.md (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/composer.json (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/examples (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/examples/benchmark.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Database (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Database/Reader.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Exception (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Exception/HttpException.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/AbstractModel.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/AnonymousIp.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/Asn.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/City.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/ConnectionType.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/Country.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/Domain.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/Enterprise.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/Insights.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Model/Isp.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/ProviderInterface.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/AbstractRecord.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/City.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/Continent.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/Country.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/Location.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/MaxMind.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/Postal.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/Subdivision.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Record/Traits.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/Util.php (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/WebService (added)
-
tags/v1.5.0/vendor/geoip2/geoip2/src/WebService/Client.php (added)
-
tags/v1.5.0/vendor/maxmind (added)
-
tags/v1.5.0/vendor/maxmind-db (added)
-
tags/v1.5.0/vendor/maxmind-db/reader (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/CHANGELOG.md (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/LICENSE (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/README.md (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/autoload.php (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/composer.json (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/config.m4 (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/config.w32 (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/maxminddb.c (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/php_maxminddb.h (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/tests (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/tests/001-load.phpt (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/tests/002-final.phpt (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/ext/tests/003-open-basedir.phpt (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/package.xml (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind/Db (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind/Db/Reader (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php (added)
-
tags/v1.5.0/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/CHANGELOG.md (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/LICENSE (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/README.md (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/composer.json (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/dev-bin (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/dev-bin/release.sh (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/phpstan.neon (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/HttpException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/WebService (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/WebService/Client.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/WebService/Http (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/WebService/Http/Request.php (added)
-
tags/v1.5.0/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php (added)
-
trunk/README.txt (modified) (2 diffs)
-
trunk/admin/class-termageddon-usercentrics-admin.php (modified) (6 diffs)
-
trunk/admin/css/termageddon-usercentrics-admin.css (modified) (2 diffs)
-
trunk/admin/css/termageddon-usercentrics-admin.min.css (modified) (1 diff)
-
trunk/includes/class-termageddon-usercentrics.php (modified) (5 diffs)
-
trunk/languages/termageddon-usercentrics.pot (modified) (23 diffs)
-
trunk/public/class-termageddon-usercentrics-public.php (modified) (2 diffs)
-
trunk/public/js/termageddon-usercentrics-ajax.js (modified) (1 diff)
-
trunk/public/js/termageddon-usercentrics-ajax.min.js (modified) (1 diff)
-
trunk/termageddon-usercentrics.php (modified) (2 diffs)
-
trunk/vendor/autoload.php (modified) (1 diff)
-
trunk/vendor/composer/ClassLoader.php (modified) (2 diffs)
-
trunk/vendor/composer/InstalledVersions.php (modified) (1 diff)
-
trunk/vendor/composer/autoload_classmap.php (modified) (1 diff)
-
trunk/vendor/composer/autoload_namespaces.php (modified) (1 diff)
-
trunk/vendor/composer/autoload_psr4.php (modified) (1 diff)
-
trunk/vendor/composer/autoload_real.php (modified) (1 diff)
-
trunk/vendor/composer/autoload_static.php (modified) (1 diff)
-
trunk/vendor/composer/ca-bundle/src/CaBundle.php (modified) (2 diffs)
-
trunk/vendor/composer/installed.php (modified) (1 diff)
-
trunk/vendor/composer/platform_check.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/examples/benchmark.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Database/Reader.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Exception/HttpException.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/AbstractModel.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/AnonymousIp.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/Asn.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/City.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/ConnectionType.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/Country.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/Domain.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/Enterprise.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/Insights.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Model/Isp.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/ProviderInterface.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/AbstractRecord.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/City.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/Continent.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/Country.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/Location.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/MaxMind.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/Postal.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/Subdivision.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Record/Traits.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/Util.php (modified) (1 diff)
-
trunk/vendor/geoip2/geoip2/src/WebService/Client.php (modified) (1 diff)
-
trunk/vendor/maxmind-db/reader/autoload.php (modified) (1 diff)
-
trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php (modified) (1 diff)
-
trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php (modified) (1 diff)
-
trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php (modified) (1 diff)
-
trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php (modified) (1 diff)
-
trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/HttpException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/WebService/Client.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/WebService/Http/Request.php (modified) (1 diff)
-
trunk/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
termageddon-usercentrics/trunk/README.txt
r3148378 r3160131 5 5 Requires at least: 3.0.1 6 6 Tested up to: 6.6.1 7 Stable tag: 1. 4.57 Stable tag: 1.5.0 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 26 26 27 27 == Changelog == 28 29 = 1.5.0 = 30 31 - [ADD] New states are now requiring cookie consent forms. The plugin now supports additional locations: Colorado, Virginia, Connecticut, Oregon, Texas, Utah 28 32 29 33 = 1.4.5 = -
termageddon-usercentrics/trunk/admin/class-termageddon-usercentrics-admin.php
r3126962 r3160131 240 240 $name = ( isset( $options['name'] ) ? $options['name'] : false ); 241 241 $description = ( isset( $options['description'] ) ? $options['description'] : false ); 242 $indent = ( isset( $options['indent'] ) ? true === $options['indent'] : false ); 243 $slim = ( isset( $options['slim'] ) ? true === $options['slim'] : false ); 242 // Indent specifies whether or not the subsection should be indented. 243 $indent = ( isset( $options['indent'] ) ? true === $options['indent'] : false ); 244 245 // Slim slims down the column width for the initial options. 246 $slim = ( isset( $options['slim'] ) ? true === $options['slim'] : false ); 247 248 // Helper slims down the divider and displays a helper text by itself. 249 $helper = ( isset( $options['helper'] ) ? true === $options['helper'] : false ); 250 251 $section_contents = $helper ? 252 ' 253 <span class="tu-section-title-helper">' . esc_html( $name ) . ':</span> 254 ' . ( empty( $description ) ? '' : '<p>' . wp_kses_post( $description ) . '</p>' ) 255 : ' </div> 256 <div class="tu-toggle-section"> 257 <span class="tu-section-title">' . esc_html( $name ) . ':</span> 258 ' . ( empty( $description ) ? '' : '<p>' . wp_kses_post( $description ) . '</p>' ) . ' 259 </div> 260 <div class="' . ( $indent ? 'tu-toggle-section' : 'tu-settings-section' ) . ( $slim ? ' slim-section' : '' ) . '">'; 244 261 245 262 add_settings_field( 246 263 'termageddon_usercentrics_end-section-' . Termageddon_Usercentrics::generate_random_string( 5 ), 247 264 ' </th></tr></tbody></table> 248 </div> 249 <div class="tu-toggle-section"> 250 <span class="tu-section-title">' . esc_html( $name ) . ':</span> 251 ' . ( empty( $description ) ? '' : '<p>' . wp_kses_post( $description ) . '</p>' ) . ' 252 </div> 253 <div class="' . ( $indent ? 'tu-toggle-section' : 'tu-settings-section' ) . ( $slim ? ' slim-section' : '' ) . '"> 265 ' . $section_contents . ' 254 266 <table class="form-table" role="presentation"> 255 267 <tbody> … … 263 275 } 264 276 277 278 /** Generates and appends the popular label for a field. 279 * 280 * @return string */ 281 public static function mark_as_popular() { 282 return ' <span class="tu-label-info">POPULAR</span>'; 283 } 265 284 266 285 /** Generates and appends the beta label for a field. … … 635 654 // ============================================ // 636 655 637 // Show only in EU. 638 add_settings_field( 639 'termageddon_usercentrics_show_in_eu', 640 __( 'European Union & European Economic Area (GDPR)', 'termageddon-usercentrics' ), 641 array( &$this, 'show_in_eu_html' ), // function which prints the field. 642 'termageddon-usercentrics', // page slug. 643 'termageddon_usercentrics_section_geolocation', // section ID. 644 array( 645 'label_for' => 'termageddon_usercentrics_show_in_eu', 646 ) 647 ); 648 649 register_setting( 650 'termageddon_usercentrics_settings', // settings group name. 651 'termageddon_usercentrics_show_in_eu', // option name. 652 '' // sanitization function. 653 ); 654 655 // Show only in UK. 656 add_settings_field( 657 'termageddon_usercentrics_show_in_uk', 658 __( 'United Kingdom (UK DPA)', 'termageddon-usercentrics' ), 659 array( &$this, 'show_in_uk_html' ), // function which prints the field. 660 'termageddon-usercentrics', // page slug. 661 'termageddon_usercentrics_section_geolocation', // section ID. 662 array( 663 'label_for' => 'termageddon_usercentrics_show_in_uk', 664 ) 665 ); 666 667 register_setting( 668 'termageddon_usercentrics_settings', // settings group name. 669 'termageddon_usercentrics_show_in_uk', // option name. 670 '' // sanitization function. 671 ); 672 673 // Show only in Canada. 674 add_settings_field( 675 'termageddon_usercentrics_show_in_canada', 676 __( 'Canada (PIPEDA)', 'termageddon-usercentrics' ), 677 array( &$this, 'show_in_canada_html' ), // function which prints the field. 678 'termageddon-usercentrics', // page slug. 679 'termageddon_usercentrics_section_geolocation', // section ID. 680 array( 681 'label_for' => 'termageddon_usercentrics_show_in_canada', 682 ) 683 ); 684 685 register_setting( 686 'termageddon_usercentrics_settings', // settings group name. 687 'termageddon_usercentrics_show_in_canada', // option name. 688 '' // sanitization function. 689 ); 656 $register_geolocation_heading = function( $loc_key, $loc_name ) { 657 // echo '<pre>' . json_encode( 'Register', JSON_PRETTY_PRINT ) . '</pre>'; 658 // BREAK SECTION FOR PSL SETTINGS. 659 $this->add_new_subsection( 660 'termageddon_usercentrics_section_geolocation', 661 array( 662 'name' => $loc_name, 663 'indent' => true, 664 'helper' => true, 665 ) 666 ); 667 }; 668 669 $register_geolocation = function( $loc_key, $loc ) { 670 list ( 'title' => $loc_name, 'popular' => $loc_popular ) = $loc; 671 add_settings_field( 672 'termageddon_usercentrics_show_in_' . $loc_key, 673 $loc_name . ( $loc_popular ? self::mark_as_popular() : '' ), 674 array( &$this, 'geolocation_toggle_html' ), // function which prints the field. 675 'termageddon-usercentrics', // page slug. 676 'termageddon_usercentrics_section_geolocation', // section ID. 677 array( 678 'label_for' => 'termageddon_usercentrics_show_in_' . $loc_key, 679 'location' => $loc_key, 680 ) 681 ); 682 683 register_setting( 684 'termageddon_usercentrics_settings', // settings group name. 685 'termageddon_usercentrics_show_in_' . $loc_key, // option name. 686 '' // sanitization function. 687 ); 688 }; 690 689 691 690 // Show only in California. 692 add_settings_field( 693 'termageddon_usercentrics_show_in_california', 694 __( 'California (CPRA or CIPA)', 'termageddon-usercentrics' ), 695 array( &$this, 'show_in_california_html' ), // function which prints the field. 696 'termageddon-usercentrics', // page slug. 697 'termageddon_usercentrics_section_geolocation', // section ID. 698 array( 699 'label_for' => 'termageddon_usercentrics_show_in_california', 700 ) 701 ); 702 703 register_setting( 704 'termageddon_usercentrics_settings', // settings group name. 705 'termageddon_usercentrics_show_in_california', // option name. 706 '' // sanitization function. 707 ); 708 709 // Show only in Virginia. 710 add_settings_field( 711 'termageddon_usercentrics_show_in_virginia', 712 __( 'Virginia (VCDPA)', 'termageddon-usercentrics' ), 713 array( &$this, 'show_in_virginia_html' ), // function which prints the field. 714 'termageddon-usercentrics', // page slug. 715 'termageddon_usercentrics_section_geolocation', // section ID. 716 array( 717 'label_for' => 'termageddon_usercentrics_show_in_virginia', 718 ) 719 ); 720 721 register_setting( 722 'termageddon_usercentrics_settings', // settings group name. 723 'termageddon_usercentrics_show_in_virginia', // option name. 724 '' // sanitization function. 725 ); 691 $current_section = null; 692 foreach ( Termageddon_Usercentrics::get_geolocation_locations( true ) as $loc_key => $loc ) { 693 list ( 'title' => $loc_name ) = $loc; 694 if ( substr( $loc_key, 0, 8 ) === 'section_' ) { // Skip section headings. 695 $current_section = substr( $loc_key, 8 ); 696 $register_geolocation_heading( $current_section, $loc_name ); 697 continue; 698 } 699 $register_geolocation( $loc_key, $loc, $current_section ); 700 } 726 701 727 702 // BREAK SECTION FOR GEOLOCATION SETTINGS. … … 1032 1007 1033 1008 /** 1034 * The HTML field for the admin disable checkbox. 1035 * 1036 * @return void 1037 */ 1038 public function show_in_eu_html() { 1039 self::generate_checkbox( 'eu' ); 1040 } 1041 1042 /** 1043 * The HTML field for the admin disable checkbox. 1044 * 1045 * @return void 1046 */ 1047 public function show_in_uk_html() { 1048 self::generate_checkbox( 'uk' ); 1049 1050 } 1051 1052 /** 1053 * The HTML field for the admin disable checkbox. 1054 * 1055 * @return void 1056 */ 1057 public function show_in_canada_html() { 1058 self::generate_checkbox( 'canada' ); 1059 1060 } 1061 1062 /** 1063 * The HTML field for the admin disable checkbox. 1064 * 1065 * @return void 1066 */ 1067 public function show_in_california_html() { 1068 self::generate_checkbox( 'california' ); 1069 1070 } 1071 1072 /** 1073 * The HTML field for the admin disable checkbox. 1074 * 1075 * @return void 1076 */ 1077 public function show_in_virginia_html() { 1078 self::generate_checkbox( 'virginia' ); 1079 1009 * Generate the checkbox for the geolocation toggles. 1010 * 1011 * @param array $args are the arguments provided by the add_settings_field() method. 1012 * @return void 1013 */ 1014 public static function geolocation_toggle_html( array $args ) { 1015 $location = $args['location']; 1016 self::generate_checkbox( $location ); 1080 1017 } 1081 1018 … … 1180 1117 1181 1118 echo '<p>' . 1182 esc_html__( 'Not sure what to select? Review', 'termageddon-usercentrics' ) . ' <a href="https://termageddon.freshdesk.com/support/solutions/articles/66000503289-how-to-activate-a-cookie-policy-and-cookie-consent-solution" target="_blank">' . esc_html__( 'this article', 'termageddon-usercentrics' ) . '</a> ' . '' . esc_html__( 'along with page 1 of your Privacy Policy questionnaire within ', 'termageddon-usercentrics' ) . '<a href="https://app.termageddon.com/home" target="_blank">app.termageddon.com</a>.' .1119 esc_html__( 'Not sure what to select? Review', 'termageddon-usercentrics' ) . ' <a href="https://termageddon.freshdesk.com/support/solutions/articles/66000503289-how-to-activate-a-cookie-policy-and-cookie-consent-solution" target="_blank">' . esc_html__( 'this article', 'termageddon-usercentrics' ) . '</a> ' . esc_html__( 'along with page 1 of your Privacy Policy questionnaire within ', 'termageddon-usercentrics' ) . '<a href="https://app.termageddon.com/home" target="_blank">app.termageddon.com</a>.' . 1183 1120 '</p>'; 1184 1121 … … 1186 1123 <div class="tu-section-settings"> 1187 1124 <div class="tu-toggle-section"> 1188 <div class="tu-section-title">' . esc_html__( 'Show widget if visitor is located in' ) . ':</div>1189 <div class="tu-section-title-helper">' . esc_html__( 'Not sure what to select? Review page 1 of your Privacy Policy questionnaire within' ) . ' <a href="https://app.termageddon.com" target="_blank">app.termageddon.com</a>.</div>1125 <div class="tu-section-title">' . esc_html__( 'Show widget if visitor is located in', 'termageddon-usercentrics' ) . ':</div> 1126 <div class="tu-section-title-helper">' . esc_html__( 'Not sure what to select?', 'termageddon-usercentrics' ) . ' <a href="https://termageddon.freshdesk.com/support/solutions/articles/66000526304-using-the-geolocation-feature-of-the-termageddon-usercentrics-plugin" target="_blank">' . esc_html__( 'This article outlines which regions to select', 'termageddon-usercentrics' ) . '</a> ' . esc_html__( 'based on which privacy laws apply to you', 'termageddon-usercentrics' ) . '.</div> 1190 1127 <div class="notice-inline notice-alt notice-warning" id="no-geolocation-locations-selected" style="display:none"> 1191 1128 <p><strong>' . esc_html__( 'Geo-Location is enabled, but no locations have been toggled on. This means that the cookie-consent will be hidden to all users.', 'termageddon-usercentrics' ) . '</strong></p> -
termageddon-usercentrics/trunk/admin/css/termageddon-usercentrics-admin.css
r3049451 r3160131 38 38 padding: 0.5rem 0; 39 39 } 40 .tu-toggle-section .form-table th { 41 width: 300px; 42 } 40 43 .tu-toggle-section.slim-section .form-table th { 41 44 width: 125px; … … 49 52 .tu-section-hidden { 50 53 display: none; 54 } 55 .tu-label-success { 56 background-color: #3db44c; 57 color: white; 58 padding: 3px 5px; 59 border-radius: 5px; 60 font-size: 60%; 61 } 62 .tu-label-info { 63 background-color: #019ed5; 64 color: white; 65 padding: 3px 5px; 66 border-radius: 5px; 67 font-size: 60%; 51 68 } 52 69 .tu-label-warning { -
termageddon-usercentrics/trunk/admin/css/termageddon-usercentrics-admin.min.css
r3049451 r3160131 1 textarea.termageddon-embed-code{width:100%;height:250px}.tu-section-settings,.tu-toggle-section{margin-top:2rem}.tu-toggle-section .tu-section-title{font-size:125%;font-weight:800}.tu-toggle-section .tu-section-title-helper{padding:1rem;color:#6c6c6c;font-style:italic}.tu-toggle-section input[readonly]{opacity:50%;pointer-events:none}.tu-toggle-section .form-table{margin-left:2rem}.tu-toggle-section .form-table td,.tu-toggle-section .form-table th{padding:.5rem 0}.tu-toggle-section .slim-section .form-table th{width:125px}.tu-settings-section .form-table th{width:300px}.tu-section-hidden{display:none}.tu-label-warning{background-color:orange;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}input[type=checkbox].wppd-ui-toggle{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent;width:auto;height:auto;vertical-align:middle;position:relative;border:0;outline:0;cursor:pointer;margin:0 4px;background:0 0;box-shadow:none}input[type=checkbox].wppd-ui-toggle:focus{box-shadow:none}input[type=checkbox].wppd-ui-toggle:after{content:"";font-size:6px;font-weight:400;line-height:18px;text-indent:-14px;color:#fff;width:36px;height:18px;display:inline-block;background-color:#a7aaad;border-radius:72px;box-shadow:0 0 12px rgb(0 0 0 / 15%) inset}input[type=checkbox].wppd-ui-toggle:before{content:"";width:14px;height:14px;display:block;position:absolute;top:2px;left:2px;margin:0;border-radius:50%;background-color:#fff}input[type=checkbox].wppd-ui-toggle:checked:before{left:20px;margin:0;background-color:#fff}input[type=checkbox].wppd-ui-toggle,input[type=checkbox].wppd-ui-toggle:after,input[type=checkbox].wppd-ui-toggle:before,input[type=checkbox].wppd-ui-toggle:checked:after,input[type=checkbox].wppd-ui-toggle:checked:before{transition:ease .15s}input[type=checkbox].wppd-ui-toggle:checked:after{content:"ON";background-color:#2271b1}input[type=checkbox].wppd-ui-toggle.label-hidden:after{width:48px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:before{left:32px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:after{content:"HIDDEN"}input[type=checkbox].wppd-ui-toggle.label-enabled:after{font-size:8px;width:60px;content:"DISABLED";text-indent:15px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:before{left:44px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:after{background-color:#1ed14b;content:"ENABLED";text-indent:-14px}.notice-inline{border-top:1px solid #c3c4c7;border-bottom:1px solid #c3c4c7;border-right:1px solid #c3c4c7;border-left-width:4px;border-left-style:solid;background:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04);margin:5px 15px 2px;padding:1px 12px}.tu-settings-section label em{font-size:12px;font-weight:400}1 textarea.termageddon-embed-code{width:100%;height:250px}.tu-section-settings,.tu-toggle-section{margin-top:2rem}.tu-toggle-section .tu-section-title{font-size:125%;font-weight:800}.tu-toggle-section .tu-section-title-helper{padding:1rem;color:#6c6c6c;font-style:italic}.tu-toggle-section input[readonly]{opacity:50%;pointer-events:none}.tu-toggle-section .form-table{margin-left:2rem}.tu-toggle-section .form-table td,.tu-toggle-section .form-table th{padding:.5rem 0}.tu-toggle-section .form-table th{width:300px}.tu-toggle-section.slim-section .form-table th{width:125px}.tu-settings-section .form-table th{width:300px}.tu-section-hidden{display:none}.tu-label-success{background-color:#3db44c;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}.tu-label-info{background-color:#019ed5;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}.tu-label-warning{background-color:orange;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}input[type=checkbox].wppd-ui-toggle{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent;width:auto;height:auto;vertical-align:middle;position:relative;border:0;outline:0;cursor:pointer;margin:0 4px;background:0 0;box-shadow:none}input[type=checkbox].wppd-ui-toggle:focus{box-shadow:none}input[type=checkbox].wppd-ui-toggle:after{content:"";font-size:6px;font-weight:400;line-height:18px;text-indent:-14px;color:#fff;width:36px;height:18px;display:inline-block;background-color:#a7aaad;border-radius:72px;box-shadow:0 0 12px rgb(0 0 0 / 15%) inset}input[type=checkbox].wppd-ui-toggle:before{content:"";width:14px;height:14px;display:block;position:absolute;top:2px;left:2px;margin:0;border-radius:50%;background-color:#fff}input[type=checkbox].wppd-ui-toggle:checked:before{left:20px;margin:0;background-color:#fff}input[type=checkbox].wppd-ui-toggle,input[type=checkbox].wppd-ui-toggle:after,input[type=checkbox].wppd-ui-toggle:before,input[type=checkbox].wppd-ui-toggle:checked:after,input[type=checkbox].wppd-ui-toggle:checked:before{transition:ease .15s}input[type=checkbox].wppd-ui-toggle:checked:after{content:"ON";background-color:#2271b1}input[type=checkbox].wppd-ui-toggle.label-hidden:after{width:48px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:before{left:32px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:after{content:"HIDDEN"}input[type=checkbox].wppd-ui-toggle.label-enabled:after{font-size:8px;width:60px;content:"DISABLED";text-indent:15px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:before{left:44px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:after{background-color:#1ed14b;content:"ENABLED";text-indent:-14px}.notice-inline{border-top:1px solid #c3c4c7;border-bottom:1px solid #c3c4c7;border-right:1px solid #c3c4c7;border-left-width:4px;border-left-style:solid;background:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04);margin:5px 15px 2px;padding:1px 12px}.tu-settings-section label em{font-size:12px;font-weight:400} -
termageddon-usercentrics/trunk/includes/class-termageddon-usercentrics.php
r3126965 r3160131 110 110 111 111 /** 112 * Returns a key value pair of geolocations to iterate over. 113 * To add support for a new state, add a new key to the array and add the state to the $GEOLOCATION_KEY_TO_STATE array. 114 * 115 * @param boolean $include_sections Whether or not to include the section keys. Defaults to false. 116 * @return array 117 */ 118 public static function get_geolocation_locations( $include_sections = false ): array { 119 $list = array( 120 'eu' => array( 121 'title' => __( 'European Union & European Economic Area (GDPR)', 'termageddon-usercentrics' ), 122 'popular' => true, 123 ), 124 'uk' => array( 125 'title' => __( 'United Kingdom (UK DPA)', 'termageddon-usercentrics' ), 126 'popular' => true, 127 ), 128 'canada' => array( 129 'title' => __( 'Canada (PIPEDA, Quebec 25)', 'termageddon-usercentrics' ), 130 'popular' => true, 131 ), 132 'section_usa' => array( 133 'title' => __( 'United States of America', 'termageddon-usercentrics' ), 134 'popular' => false, 135 ), 136 'california' => array( 137 'title' => __( 'California (CPRA, CIPA)', 'termageddon-usercentrics' ), 138 'popular' => true, 139 ), 140 'colorado' => array( 141 'title' => __( 'Colorado (CPA)', 'termageddon-usercentrics' ), 142 'popular' => false, 143 ), 144 'connecticut' => array( 145 'title' => __( 'Connecticut (CTDPA)', 'termageddon-usercentrics' ), 146 'popular' => false, 147 ), 148 'oregon' => array( 149 'title' => __( 'Oregon (OCPA)', 'termageddon-usercentrics' ), 150 'popular' => false, 151 ), 152 'texas' => array( 153 'title' => __( 'Texas (TDPSA)', 'termageddon-usercentrics' ), 154 'popular' => false, 155 ), 156 'utah' => array( 157 'title' => __( 'Utah (UCPA)', 'termageddon-usercentrics' ), 158 'popular' => false, 159 ), 160 'virginia' => array( 161 'title' => __( 'Virginia (VCDPA)', 'termageddon-usercentrics' ), 162 'popular' => false, 163 ), 164 ); 165 166 if ( $include_sections ) { 167 return $list; 168 } 169 return array_filter( 170 $list, 171 function( $key ) { 172 return strpos( $key, 'section_' ) !== 0; 173 }, 174 ARRAY_FILTER_USE_KEY 175 ); 176 } 177 178 /** 179 * Maps the geolocation key to the state returned by the geolocation lookup. 180 * 181 * @return array of key value matchups 182 */ 183 public const GEOLOCATION_KEY_TO_STATE = array( 184 'california' => 'California', 185 'colorado' => 'Colorado', 186 'connecticut' => 'Connecticut', 187 'oregon' => 'Oregon', 188 'texas' => 'Texas', 189 'utah' => 'Utah', 190 'virginia' => 'Virginia', 191 ); 192 193 /** 112 194 * Load the required dependencies for this plugin. 113 195 * … … 973 1055 */ 974 1056 public static function is_geoip_location_enabled(): bool { 975 $show_in_eu = get_option( 'termageddon_usercentrics_show_in_eu', false ) ? true : false; 976 $show_in_uk = get_option( 'termageddon_usercentrics_show_in_uk', false ) ? true : false; 977 $show_in_canada = get_option( 'termageddon_usercentrics_show_in_canada', false ) ? true : false; 978 $show_in_california = get_option( 'termageddon_usercentrics_show_in_california', false ) ? true : false; 979 $show_in_virginia = get_option( 'termageddon_usercentrics_show_in_virginia', false ) ? true : false; 980 return ( $show_in_eu || $show_in_uk || $show_in_canada || $show_in_california || $show_in_virginia ); 1057 $enabled = false; 1058 1059 foreach ( self::get_geolocation_locations() as $loc_key => $loc ) { 1060 if ( self::is_geoip_location_enabled_in( $loc_key ) ) { 1061 $enabled = true; 1062 break; 1063 } 1064 } 1065 return $enabled; 1066 } 1067 1068 /** 1069 * Identifies if geoip location is required for a specific location. 1070 * 1071 * @param string $loc_key The location key to check. 1072 * @return bool 1073 */ 1074 public static function is_geoip_location_enabled_in( string $loc_key ): bool { 1075 return get_option( 'termageddon_usercentrics_show_in_' . $loc_key, false ) ? true : false; 981 1076 } 982 1077 … … 1011 1106 * Helper method to identify if the user is located in Colorado. 1012 1107 * 1013 * @return bool */ 1014 public static function is_located_in_colorado(): bool { 1108 * @param string $loc_key The location key to check. 1109 * @return bool 1110 * @throws Exception If unable to locate location key. 1111 */ 1112 public static function is_located_in( string $loc_key ): bool { 1113 $function_name = 'is_located_in_' . $loc_key; 1114 if ( is_callable( array( self::class, $function_name ) ) ) { 1115 return call_user_func( array( self::class, $function_name ) ); 1116 } 1117 // Default to state. Check if state mapping exists. 1118 if ( ! array_key_exists( $loc_key, self::GEOLOCATION_KEY_TO_STATE ) ) { 1119 throw new Exception( 'Unable to locate location key for ' . $loc_key ); 1120 } 1121 1122 $loc_key = self::GEOLOCATION_KEY_TO_STATE[ $loc_key ]; 1015 1123 list( 'state' => $state ) = self::lookup_ip_address(); 1016 return ( null === $state || 'Colorado' === $state ); 1017 1018 } 1019 1020 /** 1021 * Helper method to identify if the user is located in California. 1022 * 1023 * @return bool */ 1024 public static function is_located_in_california(): bool { 1025 list( 'state' => $state ) = self::lookup_ip_address(); 1026 return ( null === $state || 'California' === $state ); 1027 1028 } 1029 1030 /** 1031 * Helper method to identify if the user is located in Virginia. 1032 * 1033 * @return bool */ 1034 public static function is_located_in_virginia(): bool { 1035 list( 'state' => $state ) = self::lookup_ip_address(); 1036 return ( null === $state || 'Virginia' === $state ); 1124 return ( null === $state || $loc_key === $state ); 1037 1125 1038 1126 } … … 1108 1196 * @return bool */ 1109 1197 public static function should_hide_due_to_location(): bool { 1110 $show_in_eu = get_option( 'termageddon_usercentrics_show_in_eu', false ) ? true : false; 1111 $show_in_uk = get_option( 'termageddon_usercentrics_show_in_uk', false ) ? true : false;1112 $ show_in_canada = get_option( 'termageddon_usercentrics_show_in_canada', false ) ? true :false;1113 $show_in_california = get_option( 'termageddon_usercentrics_show_in_california', false ) ? true : false;1114 $show_in_virginia = get_option( 'termageddon_usercentrics_show_in_virginia', false ) ? true : false;1115 1116 // Hide if all of the rules come back negative for specific locations.1117 $located_in_eu = self::is_located_in_eu();1118 $located_in_uk = self::is_located_in_uk();1119 $located_in_canada = self::is_located_in_canada();1120 $located_in_california = self::is_located_in_california();1121 $located_in_virginia = self::is_located_in_virginia();1198 1199 // Iterate through locations and identify if user is located in any of them, and site has it enabled. If so, hide consent. 1200 $located_in_location_that_needs_consent = false; 1201 foreach ( self::get_geolocation_locations() as $loc_key => $loc ) { 1202 $is_located_in = self::is_located_in( $loc_key ); 1203 if ( $is_located_in ) { 1204 $located_in_location_that_needs_consent = true; 1205 } 1206 if ( $is_located_in && ! self::is_geoip_location_enabled_in( $loc_key ) ) { 1207 return true; // User is located in a location that needs it, but it is disabled, so hide. 1208 } 1209 } 1122 1210 1123 1211 // If not in any applicable zones, hide cookie consent. 1124 if ( ! $located_in_eu && ! $located_in_uk && ! $located_in_canada && ! $located_in_california && ! $located_in_virginia ) { 1125 return true; 1126 } 1127 1128 // Based on where you are located, check the location. 1129 if ( $located_in_eu && ! $show_in_eu ) { 1130 return true; 1131 } 1132 if ( $located_in_uk && ! $show_in_uk ) { 1133 return true; 1134 } 1135 if ( $located_in_canada && ! $show_in_canada ) { 1136 return true; 1137 } 1138 if ( $located_in_california && ! $show_in_california ) { 1139 return true; 1140 } 1141 if ( $located_in_virginia && ! $show_in_virginia ) { 1142 return true; 1212 if ( ! $located_in_location_that_needs_consent ) { 1213 return true; // Not in a location that needs it, so continue. 1143 1214 } 1144 1215 … … 1183 1254 list('city' => $city, 'state' => $state, 'country' => $country) = self::lookup_ip_address( $ip_address ); 1184 1255 1185 $result['ipAddress'] = $ip_address; 1186 $result['city'] = ( $city ?? 'Unknown' ); 1187 $result['state'] = ( $state ?? 'Unknown' ); 1188 $result['country'] = ( $country ?? 'Unknown' ); 1189 $result['inEU'] = self::is_located_in_eu(); 1190 $result['inUK'] = self::is_located_in_uk(); 1191 $result['inCanada'] = self::is_located_in_canada(); 1192 $result['inCalifornia'] = self::is_located_in_california(); 1193 $result['inVirginia'] = self::is_located_in_virginia(); 1256 $result['ipAddress'] = $ip_address; 1257 $result['city'] = ( $city ?? 'Unknown' ); 1258 $result['state'] = ( $state ?? 'Unknown' ); 1259 $result['country'] = ( $country ?? 'Unknown' ); 1260 1261 // Iterate through locations. 1262 $locations = array(); 1263 foreach ( self::get_geolocation_locations() as $loc_key => $loc ) { 1264 $locations[ $loc_key ] = self::is_located_in( $loc_key ); 1265 } 1266 $result['locations'] = $locations; 1194 1267 } 1195 1268 -
termageddon-usercentrics/trunk/languages/termageddon-usercentrics.pot
r3126962 r3160131 4 4 "Project-Id-Version: Termageddon + Usercentrics\n" 5 5 "Report-Msgid-Bugs-To: \n" 6 "POT-Creation-Date: 2024-0 7-29 01:53+0000\n"6 "POT-Creation-Date: 2024-09-24 04:08+0000\n" 7 7 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 8 8 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 17 17 "X-Domain: termageddon-usercentrics" 18 18 19 #: admin/class-termageddon-usercentrics-admin.php: 39419 #: admin/class-termageddon-usercentrics-admin.php:413 20 20 msgid "Administrators" 21 21 msgstr "" … … 29 29 msgstr "" 30 30 31 #: admin/class-termageddon-usercentrics-admin.php:11 8231 #: admin/class-termageddon-usercentrics-admin.php:1119 32 32 msgid "along with page 1 of your Privacy Policy questionnaire within " 33 33 msgstr "" 34 34 35 #: admin/class-termageddon-usercentrics-admin.php:694 36 msgid "California (CPRA or CIPA)" 37 msgstr "" 38 39 #: admin/class-termageddon-usercentrics-admin.php:676 40 msgid "Canada (PIPEDA)" 35 #: admin/class-termageddon-usercentrics-admin.php:1126 36 msgid "based on which privacy laws apply to you" 37 msgstr "" 38 39 #: includes/class-termageddon-usercentrics.php:137 40 msgid "California (CPRA, CIPA)" 41 msgstr "" 42 43 #: includes/class-termageddon-usercentrics.php:129 44 msgid "Canada (PIPEDA, Quebec 25)" 45 msgstr "" 46 47 #: includes/class-termageddon-usercentrics.php:141 48 msgid "Colorado (CPA)" 49 msgstr "" 50 51 #: includes/class-termageddon-usercentrics.php:145 52 msgid "Connecticut (CTDPA)" 41 53 msgstr "" 42 54 43 55 #. section ID. 44 #: admin/class-termageddon-usercentrics-admin.php:7 8656 #: admin/class-termageddon-usercentrics-admin.php:761 45 57 msgid "Control Panel" 46 58 msgstr "" 47 59 48 #: admin/class-termageddon-usercentrics-admin.php:1 14260 #: admin/class-termageddon-usercentrics-admin.php:1079 49 61 msgid "Cookie Policy and Consent Solution" 50 62 msgstr "" … … 54 66 msgstr "" 55 67 56 #: admin/class-termageddon-usercentrics-admin.php: 59268 #: admin/class-termageddon-usercentrics-admin.php:611 57 69 msgid "Disable for Troubleshooting" 58 70 msgstr "" 59 71 60 #: admin/class-termageddon-usercentrics-admin.php:5 0572 #: admin/class-termageddon-usercentrics-admin.php:524 61 73 msgid "Divi Video Player Integration" 62 74 msgstr "" … … 68 80 msgstr "" 69 81 70 #: admin/class-termageddon-usercentrics-admin.php:4 1282 #: admin/class-termageddon-usercentrics-admin.php:431 71 83 msgid "Editors" 72 84 msgstr "" 73 85 74 #: admin/class-termageddon-usercentrics-admin.php:5 2486 #: admin/class-termageddon-usercentrics-admin.php:543 75 87 msgid "Elementor Video Player Integration" 76 88 msgstr "" 77 89 78 90 #: admin/class-termageddon-usercentrics-admin.php:170 79 #: admin/class-termageddon-usercentrics-admin.php:3 5791 #: admin/class-termageddon-usercentrics-admin.php:376 80 92 msgid "Embed Code" 81 93 msgstr "" 82 94 83 #: admin/class-termageddon-usercentrics-admin.php:5 7095 #: admin/class-termageddon-usercentrics-admin.php:589 84 96 msgid "Embed Code Priority" 85 97 msgstr "" 86 98 87 #: admin/class-termageddon-usercentrics-admin.php:7 3999 #: admin/class-termageddon-usercentrics-admin.php:714 88 100 msgid "Enable location logging" 89 101 msgstr "" 90 102 91 #: admin/class-termageddon-usercentrics-admin.php:7 59103 #: admin/class-termageddon-usercentrics-admin.php:734 92 104 msgid "Enable page caching support via AJAX" 93 105 msgstr "" 94 106 95 #: admin/class-termageddon-usercentrics-admin.php: 800107 #: admin/class-termageddon-usercentrics-admin.php:775 96 108 msgid "Error Count" 97 109 msgstr "" … … 101 113 msgstr "" 102 114 103 #: admin/class-termageddon-usercentrics-admin.php: 818115 #: admin/class-termageddon-usercentrics-admin.php:793 104 116 msgid "Error List" 105 117 msgstr "" 106 118 107 #: admin/class-termageddon-usercentrics-admin.php:640119 #: includes/class-termageddon-usercentrics.php:121 108 120 msgid "European Union & European Economic Area (GDPR)" 109 121 msgstr "" 110 122 111 #: includes/class-termageddon-usercentrics.php: 225123 #: includes/class-termageddon-usercentrics.php:307 112 124 msgid "Every Month" 113 125 msgstr "" 114 126 115 #: admin/class-termageddon-usercentrics-admin.php: 483127 #: admin/class-termageddon-usercentrics-admin.php:502 116 128 msgid "" 117 129 "For some theme builders including Divi, the footer (bottom bar) does not " … … 123 135 #. section ID. 124 136 #: admin/class-termageddon-usercentrics-admin.php:172 125 #: admin/class-termageddon-usercentrics-admin.php:6 20137 #: admin/class-termageddon-usercentrics-admin.php:639 126 138 msgid "Geo-Location" 127 139 msgstr "" 128 140 129 141 #: admin/class-termageddon-usercentrics-admin.php:143 130 #: admin/class-termageddon-usercentrics-admin.php:11 91142 #: admin/class-termageddon-usercentrics-admin.php:1128 131 143 msgid "" 132 144 "Geo-Location is enabled, but no locations have been toggled on. This means " … … 158 170 msgstr "" 159 171 160 #: admin/class-termageddon-usercentrics-admin.php:4 58172 #: admin/class-termageddon-usercentrics-admin.php:477 161 173 msgid "Hide Privacy Settings Link when cookie consent tool is disabled" 162 174 msgstr "" … … 166 178 msgstr "" 167 179 168 #: admin/class-termageddon-usercentrics-admin.php:1 160180 #: admin/class-termageddon-usercentrics-admin.php:1097 169 181 msgid "If you are using the Divi theme" 170 182 msgstr "" 171 183 172 #: admin/class-termageddon-usercentrics-admin.php:1 159184 #: admin/class-termageddon-usercentrics-admin.php:1096 173 185 msgid "" 174 186 "If you would like to remove Usercentrics for logged in users such as admins, " … … 184 196 msgstr "" 185 197 186 #: admin/class-termageddon-usercentrics-admin.php:4 30198 #: admin/class-termageddon-usercentrics-admin.php:449 187 199 msgid "Logged-in Users" 188 200 msgstr "" 189 201 190 #: admin/class-termageddon-usercentrics-admin.php:1182 202 #: admin/class-termageddon-usercentrics-admin.php:1126 203 msgid "Not sure what to select?" 204 msgstr "" 205 206 #: admin/class-termageddon-usercentrics-admin.php:1119 191 207 msgid "Not sure what to select? Review" 192 208 msgstr "" 193 209 194 #: admin/class-termageddon-usercentrics-admin.php:576 210 #: includes/class-termageddon-usercentrics.php:149 211 msgid "Oregon (OCPA)" 212 msgstr "" 213 214 #: admin/class-termageddon-usercentrics-admin.php:595 195 215 msgid "" 196 216 "Override the default priority of the embed code (Defaults to 1). By " … … 206 226 msgstr "" 207 227 208 #: admin/class-termageddon-usercentrics-admin.php:5 43228 #: admin/class-termageddon-usercentrics-admin.php:562 209 229 msgid "Presto Player" 210 230 msgstr "" 211 231 212 #: admin/class-termageddon-usercentrics-admin.php:4 77232 #: admin/class-termageddon-usercentrics-admin.php:496 213 233 msgid "Privacy Settings Link - Alternative Implementation" 214 234 msgstr "" 215 235 216 236 #. section ID. 217 #: includes/class-termageddon-usercentrics.php:4 11237 #: includes/class-termageddon-usercentrics.php:492 218 238 #: admin/class-termageddon-usercentrics-admin.php:171 219 #: admin/class-termageddon-usercentrics-admin.php: 385239 #: admin/class-termageddon-usercentrics-admin.php:404 220 240 msgid "Settings" 241 msgstr "" 242 243 #: admin/class-termageddon-usercentrics-admin.php:1125 244 msgid "Show widget if visitor is located in" 221 245 msgstr "" 222 246 … … 230 254 msgstr "" 231 255 232 #: admin/class-termageddon-usercentrics-admin.php:1182 256 #: includes/class-termageddon-usercentrics.php:153 257 msgid "Texas (TDPSA)" 258 msgstr "" 259 260 #: admin/class-termageddon-usercentrics-admin.php:1119 233 261 msgid "this article" 262 msgstr "" 263 264 #: admin/class-termageddon-usercentrics-admin.php:1126 265 msgid "This article outlines which regions to select" 234 266 msgstr "" 235 267 … … 240 272 msgstr "" 241 273 242 #: admin/class-termageddon-usercentrics-admin.php:5 06274 #: admin/class-termageddon-usercentrics-admin.php:525 243 275 msgid "" 244 276 "This resolves and improves the cookie-consent implementation when using an " … … 246 278 msgstr "" 247 279 248 #: admin/class-termageddon-usercentrics-admin.php:5 25280 #: admin/class-termageddon-usercentrics-admin.php:544 249 281 msgid "" 250 282 "This resolves and improves the cookie-consent implementation when using an " … … 252 284 msgstr "" 253 285 254 #: admin/class-termageddon-usercentrics-admin.php:1 203286 #: admin/class-termageddon-usercentrics-admin.php:1140 255 287 msgid "" 256 288 "To reset any of the backend variables, update the values below and save your " … … 258 290 msgstr "" 259 291 260 #: admin/class-termageddon-usercentrics-admin.php:658292 #: includes/class-termageddon-usercentrics.php:125 261 293 msgid "United Kingdom (UK DPA)" 262 294 msgstr "" 263 295 264 #: admin/class-termageddon-usercentrics-admin.php:1141 296 #: includes/class-termageddon-usercentrics.php:133 297 msgid "United States of America" 298 msgstr "" 299 300 #: admin/class-termageddon-usercentrics-admin.php:1078 265 301 msgid "Upon generating your " 266 302 msgstr "" 267 303 268 #: admin/class-termageddon-usercentrics-admin.php:1 127304 #: admin/class-termageddon-usercentrics-admin.php:1064 269 305 msgid "Upon saving, all previous errors in the log will be deleted." 270 306 msgstr "" 271 307 272 #: admin/class-termageddon-usercentrics-admin.php:712 308 #: includes/class-termageddon-usercentrics.php:157 309 msgid "Utah (UCPA)" 310 msgstr "" 311 312 #: includes/class-termageddon-usercentrics.php:161 273 313 msgid "Virginia (VCDPA)" 274 314 msgstr "" … … 281 321 msgstr "" 282 322 283 #: admin/class-termageddon-usercentrics-admin.php:4 64323 #: admin/class-termageddon-usercentrics-admin.php:483 284 324 msgid "" 285 325 "When enabled, the Privacy Settings link will be hidden from certain users, " … … 294 334 msgstr "" 295 335 296 #: admin/class-termageddon-usercentrics-admin.php:7 45336 #: admin/class-termageddon-usercentrics-admin.php:720 297 337 msgid "" 298 338 "When enabled, the visitor's location can be viewed in the browser console, " … … 300 340 msgstr "" 301 341 302 #: admin/class-termageddon-usercentrics-admin.php:7 65342 #: admin/class-termageddon-usercentrics-admin.php:740 303 343 msgid "" 304 344 "When enabled, the visitor's location is checked via javascript to allow " … … 306 346 msgstr "" 307 347 308 #: admin/class-termageddon-usercentrics-admin.php: 598348 #: admin/class-termageddon-usercentrics-admin.php:617 309 349 msgid "" 310 350 "When enabled, this feature allows you to turn off the consent tool for all " … … 315 355 msgstr "" 316 356 317 #: admin/class-termageddon-usercentrics-admin.php:11 78357 #: admin/class-termageddon-usercentrics-admin.php:1115 318 358 msgid "" 319 359 "When enabled, you will be collecting IP addresses for the purposes of " … … 331 371 msgstr "" 332 372 333 #: admin/class-termageddon-usercentrics-admin.php:1 143373 #: admin/class-termageddon-usercentrics-admin.php:1080 334 374 msgid "" 335 375 "within your Termageddon account, you will be brought to the \"View embed " … … 338 378 msgstr "" 339 379 340 #: admin/class-termageddon-usercentrics-admin.php:1 161380 #: admin/class-termageddon-usercentrics-admin.php:1098 341 381 msgid "" 342 382 "you will need to enable at least one of the settings below to ensure logged " -
termageddon-usercentrics/trunk/public/class-termageddon-usercentrics-public.php
r3148378 r3160131 135 135 list('city' => $city, 'state' => $state, 'country' => $country) = Termageddon_Usercentrics::lookup_ip_address(); 136 136 137 // Iterate through locations. 138 $locations = array_map( 139 function( $loc_key, $loc ) { 140 list ( 'title' => $loc_name ) = $loc; 141 return 'Located in ' . $loc_name . ': ' . ( Termageddon_Usercentrics::is_located_in( $loc_key ) ? 'Yes' : 'No' ); 142 }, 143 Termageddon_Usercentrics::get_geolocation_locations() 144 ); 145 137 146 // Output debug message to console. 138 147 Termageddon_Usercentrics::debug( … … 142 151 'Country: ' . ( $country ?? 'Unknown' ), 143 152 '--', 144 'Located in EU?: ' . ( Termageddon_Usercentrics::is_located_in_eu() ? 'Yes' : 'No' ), 145 'Located in UK?: ' . ( Termageddon_Usercentrics::is_located_in_uk() ? 'Yes' : 'No' ), 146 'Located in Canada?: ' . ( Termageddon_Usercentrics::is_located_in_canada() ? 'Yes' : 'No' ), 147 'Located in California?: ' . ( Termageddon_Usercentrics::is_located_in_california() ? 'Yes' : 'No' ), 148 'Located in Virginia?: ' . ( Termageddon_Usercentrics::is_located_in_virginia() ? 'Yes' : 'No' ), 153 $locations, 149 154 '--', 150 155 'Geo-Location Mode?: ' . ( Termageddon_Usercentrics::is_geoip_enabled() ? 'Yes' : 'No' ), -
termageddon-usercentrics/trunk/public/js/termageddon-usercentrics-ajax.js
r3104855 r3160131 126 126 (data.country || "Unknown") + 127 127 "\n" + 128 "--" + 129 "\n" + 130 "Located in EU?: " + 131 (data.inEU ? "Yes" : "No") + 132 "\n" + 133 "Located in UK?: " + 134 (data.inUK ? "Yes" : "No") + 135 "\n" + 136 "Located in Canada?: " + 137 (data.inCanada ? "Yes" : "No") + 138 "\n" + 139 "Located in California?: " + 140 (data.inCalifornia ? "Yes" : "No") + 141 "\n" + 142 "Located in Virginia?: " + 143 (data.inVirginia ? "Yes" : "No") 128 "Locations: ", 129 data.locations 144 130 ); 145 131 } -
termageddon-usercentrics/trunk/public/js/termageddon-usercentrics-ajax.min.js
r3104855 r3160131 1 const tuCookieHideName="tu-geoip-hide",tuDebug="true"===termageddon_usercentrics_obj.debug,tuPSLHide="true"===termageddon_usercentrics_obj.psl_hide;tuDebug&&console.log("UC: AJAX script initialized"),window.addEventListener("UC_UI_INITIALIZED",(function(){const getCookie=name=>{const value=`; ${document.cookie}`,parts=value.split(`; ${name}=`);if(2===parts.length)return parts.pop().split(";").shift()},getQueryParams=param=>{const params=new Proxy(new URLSearchParams(window.location.search),{get:(searchParams,prop)=>searchParams.get(prop)});return params[param]},setCookie=(name,value,days)=>{var expires="";if(days){var date=new Date;date.setTime(date.getTime()+24*days*60*60*1e3),expires="; expires="+date.toUTCString()}document.cookie=name+"="+(value||"")+expires+"; path=/"},updateCookieConsent=hide=>{if(!hide)return tuDebug&&console.log("UC: Showing consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").show(),jQuery("div#usercentrics-root").show(),UC_UI.isConsentRequired()?UC_UI.showFirstLayer():UC_UI.closeCMP();tuDebug&&console.log("UC: Hiding consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").hide(),jQuery("div#usercentrics-root").hide(),UC_UI.areAllConsentsAccepted()||UC_UI.acceptAllConsents().then(()=>{tuDebug&&console.log("UC: All consents have been accepted."),UC_UI.closeCMP().then(()=>{tuDebug&&console.log("UC: CMP Widget has been closed.")})})};if("undefined"==typeof UC_UI)return console.error("Usercentrics not loaded");const query_hide=""===getQueryParams("enable-usercentrics"),cookie_hide=getCookie("tu-geoip-hide");if(null==cookie_hide||tuDebug){tuDebug&&console.log("UC: Making AJAX Call");var data={action:"uc_geolocation_lookup",nonce:termageddon_usercentrics_obj.nonce};void 0!==termageddon_usercentrics_obj.location&&(data.location=termageddon_usercentrics_obj.location),jQuery.post(termageddon_usercentrics_obj.ajax_url,data).done((function(response){if(!response.success)return console.error("Unable to lookup location.",response.message||"");if(!response.data)return console.error("Location data was not provided.",response.data);const data=response.data;if(tuDebug&&console.log("TERMAGEDDON USERCENTRICS (AJAX)\nIP Address: "+data.ipAddress+"\nCity: "+(data.city||"Unknown")+"\nState: "+(data.state||"Unknown")+"\nCountry: "+(data.country||"Unknown")+"\n --\nLocated in EU?: "+(data.inEU?"Yes":"No")+"\nLocated in UK?: "+(data.inUK?"Yes":"No")+"\nLocated in Canada?: "+(data.inCanada?"Yes":"No")+"\nLocated in California?: "+(data.inCalifornia?"Yes":"No")+"\nLocated in Virginia?: "+(data.inVirginia?"Yes":"No")),query_hide)return tuDebug&&console.log("UC: Enabling due to query parameter override.","Showing Usercentrics"),updateCookieConsent(!1);setCookie("tu-geoip-hide",data.hide?"true":"false"),updateCookieConsent(data.hide)})).fail((function(response){console.error("Usercentrics: Invalid response returned. Showing widget as a default.",response),updateCookieConsent(!1)}))}else tuDebug&&console.log("UC: Cookie found.",(cookie_hide?"Showing":"Hiding")+" Usercentrics"),updateCookieConsent("true"===cookie_hide)}));1 const tuCookieHideName="tu-geoip-hide",tuDebug="true"===termageddon_usercentrics_obj.debug,tuPSLHide="true"===termageddon_usercentrics_obj.psl_hide;tuDebug&&console.log("UC: AJAX script initialized"),window.addEventListener("UC_UI_INITIALIZED",(function(){const getCookie=name=>{const value=`; ${document.cookie}`,parts=value.split(`; ${name}=`);if(2===parts.length)return parts.pop().split(";").shift()},getQueryParams=param=>{const params=new Proxy(new URLSearchParams(window.location.search),{get:(searchParams,prop)=>searchParams.get(prop)});return params[param]},setCookie=(name,value,days)=>{var expires="";if(days){var date=new Date;date.setTime(date.getTime()+24*days*60*60*1e3),expires="; expires="+date.toUTCString()}document.cookie=name+"="+(value||"")+expires+"; path=/"},updateCookieConsent=hide=>{if(!hide)return tuDebug&&console.log("UC: Showing consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").show(),jQuery("div#usercentrics-root").show(),UC_UI.isConsentRequired()?UC_UI.showFirstLayer():UC_UI.closeCMP();tuDebug&&console.log("UC: Hiding consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").hide(),jQuery("div#usercentrics-root").hide(),UC_UI.areAllConsentsAccepted()||UC_UI.acceptAllConsents().then(()=>{tuDebug&&console.log("UC: All consents have been accepted."),UC_UI.closeCMP().then(()=>{tuDebug&&console.log("UC: CMP Widget has been closed.")})})};if("undefined"==typeof UC_UI)return console.error("Usercentrics not loaded");const query_hide=""===getQueryParams("enable-usercentrics"),cookie_hide=getCookie("tu-geoip-hide");if(null==cookie_hide||tuDebug){tuDebug&&console.log("UC: Making AJAX Call");var data={action:"uc_geolocation_lookup",nonce:termageddon_usercentrics_obj.nonce};void 0!==termageddon_usercentrics_obj.location&&(data.location=termageddon_usercentrics_obj.location),jQuery.post(termageddon_usercentrics_obj.ajax_url,data).done((function(response){if(!response.success)return console.error("Unable to lookup location.",response.message||"");if(!response.data)return console.error("Location data was not provided.",response.data);const data=response.data;if(tuDebug&&console.log("TERMAGEDDON USERCENTRICS (AJAX)\nIP Address: "+data.ipAddress+"\nCity: "+(data.city||"Unknown")+"\nState: "+(data.state||"Unknown")+"\nCountry: "+(data.country||"Unknown")+"\nLocations: ",data.locations),query_hide)return tuDebug&&console.log("UC: Enabling due to query parameter override.","Showing Usercentrics"),updateCookieConsent(!1);setCookie("tu-geoip-hide",data.hide?"true":"false"),updateCookieConsent(data.hide)})).fail((function(response){console.error("Usercentrics: Invalid response returned. Showing widget as a default.",response),updateCookieConsent(!1)}))}else tuDebug&&console.log("UC: Cookie found.",(cookie_hide?"Showing":"Hiding")+" Usercentrics"),updateCookieConsent("true"===cookie_hide)})); -
termageddon-usercentrics/trunk/termageddon-usercentrics.php
r3148378 r3160131 15 15 * Plugin Name: Termageddon + Usercentrics 16 16 * Description: Easily integrate the Usercentrics consent solution into your website while controlling visibility for logged in users and admins. 17 * Version: 1. 4.517 * Version: 1.5.0 18 18 * Author: Termageddon 19 19 * Author URI: https://termageddon.com … … 34 34 * Rename this for your plugin and update it as you release new versions. 35 35 */ 36 define( 'TERMAGEDDON_COOKIE_VERSION', '1. 4.5' );36 define( 'TERMAGEDDON_COOKIE_VERSION', '1.5.0' ); 37 37 38 38 define( 'TERMAGEDDON_COOKIE_PLUGIN_PATH', dirname( __FILE__ ) );// No trailing slash. -
termageddon-usercentrics/trunk/vendor/autoload.php
r2771752 r3160131 3 3 // autoload.php @generated by Composer 4 4 5 if ( PHP_VERSION_ID < 50600) {6 echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;7 exit(1);5 if ( PHP_VERSION_ID < 50600 ) { 6 echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running ' . PHP_VERSION . ', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.' . PHP_EOL; 7 exit( 1 ); 8 8 } 9 9 -
termageddon-usercentrics/trunk/vendor/composer/ClassLoader.php
r2976730 r3160131 41 41 * @see https://www.php-fig.org/psr/psr-4/ 42 42 */ 43 class ClassLoader 44 { 45 /** @var ?string */ 46 private $vendorDir; 47 48 // PSR-4 49 /** 50 * @var array[] 51 * @psalm-var array<string, array<string, int>> 52 */ 53 private $prefixLengthsPsr4 = array(); 54 /** 55 * @var array[] 56 * @psalm-var array<string, array<int, string>> 57 */ 58 private $prefixDirsPsr4 = array(); 59 /** 60 * @var array[] 61 * @psalm-var array<string, string> 62 */ 63 private $fallbackDirsPsr4 = array(); 64 65 // PSR-0 66 /** 67 * @var array[] 68 * @psalm-var array<string, array<string, string[]>> 69 */ 70 private $prefixesPsr0 = array(); 71 /** 72 * @var array[] 73 * @psalm-var array<string, string> 74 */ 75 private $fallbackDirsPsr0 = array(); 76 77 /** @var bool */ 78 private $useIncludePath = false; 79 80 /** 81 * @var string[] 82 * @psalm-var array<string, string> 83 */ 84 private $classMap = array(); 85 86 /** @var bool */ 87 private $classMapAuthoritative = false; 88 89 /** 90 * @var bool[] 91 * @psalm-var array<string, bool> 92 */ 93 private $missingClasses = array(); 94 95 /** @var ?string */ 96 private $apcuPrefix; 97 98 /** 99 * @var self[] 100 */ 101 private static $registeredLoaders = array(); 102 103 /** 104 * @param ?string $vendorDir 105 */ 106 public function __construct($vendorDir = null) 107 { 108 $this->vendorDir = $vendorDir; 109 } 110 111 /** 112 * @return string[] 113 */ 114 public function getPrefixes() 115 { 116 if (!empty($this->prefixesPsr0)) { 117 return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); 118 } 119 120 return array(); 121 } 122 123 /** 124 * @return array[] 125 * @psalm-return array<string, array<int, string>> 126 */ 127 public function getPrefixesPsr4() 128 { 129 return $this->prefixDirsPsr4; 130 } 131 132 /** 133 * @return array[] 134 * @psalm-return array<string, string> 135 */ 136 public function getFallbackDirs() 137 { 138 return $this->fallbackDirsPsr0; 139 } 140 141 /** 142 * @return array[] 143 * @psalm-return array<string, string> 144 */ 145 public function getFallbackDirsPsr4() 146 { 147 return $this->fallbackDirsPsr4; 148 } 149 150 /** 151 * @return string[] Array of classname => path 152 * @psalm-return array<string, string> 153 */ 154 public function getClassMap() 155 { 156 return $this->classMap; 157 } 158 159 /** 160 * @param string[] $classMap Class to filename map 161 * @psalm-param array<string, string> $classMap 162 * 163 * @return void 164 */ 165 public function addClassMap(array $classMap) 166 { 167 if ($this->classMap) { 168 $this->classMap = array_merge($this->classMap, $classMap); 169 } else { 170 $this->classMap = $classMap; 171 } 172 } 173 174 /** 175 * Registers a set of PSR-0 directories for a given prefix, either 176 * appending or prepending to the ones previously set for this prefix. 177 * 178 * @param string $prefix The prefix 179 * @param string[]|string $paths The PSR-0 root directories 180 * @param bool $prepend Whether to prepend the directories 181 * 182 * @return void 183 */ 184 public function add($prefix, $paths, $prepend = false) 185 { 186 if (!$prefix) { 187 if ($prepend) { 188 $this->fallbackDirsPsr0 = array_merge( 189 (array) $paths, 190 $this->fallbackDirsPsr0 191 ); 192 } else { 193 $this->fallbackDirsPsr0 = array_merge( 194 $this->fallbackDirsPsr0, 195 (array) $paths 196 ); 197 } 198 199 return; 200 } 201 202 $first = $prefix[0]; 203 if (!isset($this->prefixesPsr0[$first][$prefix])) { 204 $this->prefixesPsr0[$first][$prefix] = (array) $paths; 205 206 return; 207 } 208 if ($prepend) { 209 $this->prefixesPsr0[$first][$prefix] = array_merge( 210 (array) $paths, 211 $this->prefixesPsr0[$first][$prefix] 212 ); 213 } else { 214 $this->prefixesPsr0[$first][$prefix] = array_merge( 215 $this->prefixesPsr0[$first][$prefix], 216 (array) $paths 217 ); 218 } 219 } 220 221 /** 222 * Registers a set of PSR-4 directories for a given namespace, either 223 * appending or prepending to the ones previously set for this namespace. 224 * 225 * @param string $prefix The prefix/namespace, with trailing '\\' 226 * @param string[]|string $paths The PSR-4 base directories 227 * @param bool $prepend Whether to prepend the directories 228 * 229 * @throws \InvalidArgumentException 230 * 231 * @return void 232 */ 233 public function addPsr4($prefix, $paths, $prepend = false) 234 { 235 if (!$prefix) { 236 // Register directories for the root namespace. 237 if ($prepend) { 238 $this->fallbackDirsPsr4 = array_merge( 239 (array) $paths, 240 $this->fallbackDirsPsr4 241 ); 242 } else { 243 $this->fallbackDirsPsr4 = array_merge( 244 $this->fallbackDirsPsr4, 245 (array) $paths 246 ); 247 } 248 } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 249 // Register directories for a new namespace. 250 $length = strlen($prefix); 251 if ('\\' !== $prefix[$length - 1]) { 252 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 253 } 254 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 255 $this->prefixDirsPsr4[$prefix] = (array) $paths; 256 } elseif ($prepend) { 257 // Prepend directories for an already registered namespace. 258 $this->prefixDirsPsr4[$prefix] = array_merge( 259 (array) $paths, 260 $this->prefixDirsPsr4[$prefix] 261 ); 262 } else { 263 // Append directories for an already registered namespace. 264 $this->prefixDirsPsr4[$prefix] = array_merge( 265 $this->prefixDirsPsr4[$prefix], 266 (array) $paths 267 ); 268 } 269 } 270 271 /** 272 * Registers a set of PSR-0 directories for a given prefix, 273 * replacing any others previously set for this prefix. 274 * 275 * @param string $prefix The prefix 276 * @param string[]|string $paths The PSR-0 base directories 277 * 278 * @return void 279 */ 280 public function set($prefix, $paths) 281 { 282 if (!$prefix) { 283 $this->fallbackDirsPsr0 = (array) $paths; 284 } else { 285 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 286 } 287 } 288 289 /** 290 * Registers a set of PSR-4 directories for a given namespace, 291 * replacing any others previously set for this namespace. 292 * 293 * @param string $prefix The prefix/namespace, with trailing '\\' 294 * @param string[]|string $paths The PSR-4 base directories 295 * 296 * @throws \InvalidArgumentException 297 * 298 * @return void 299 */ 300 public function setPsr4($prefix, $paths) 301 { 302 if (!$prefix) { 303 $this->fallbackDirsPsr4 = (array) $paths; 304 } else { 305 $length = strlen($prefix); 306 if ('\\' !== $prefix[$length - 1]) { 307 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 308 } 309 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 310 $this->prefixDirsPsr4[$prefix] = (array) $paths; 311 } 312 } 313 314 /** 315 * Turns on searching the include path for class files. 316 * 317 * @param bool $useIncludePath 318 * 319 * @return void 320 */ 321 public function setUseIncludePath($useIncludePath) 322 { 323 $this->useIncludePath = $useIncludePath; 324 } 325 326 /** 327 * Can be used to check if the autoloader uses the include path to check 328 * for classes. 329 * 330 * @return bool 331 */ 332 public function getUseIncludePath() 333 { 334 return $this->useIncludePath; 335 } 336 337 /** 338 * Turns off searching the prefix and fallback directories for classes 339 * that have not been registered with the class map. 340 * 341 * @param bool $classMapAuthoritative 342 * 343 * @return void 344 */ 345 public function setClassMapAuthoritative($classMapAuthoritative) 346 { 347 $this->classMapAuthoritative = $classMapAuthoritative; 348 } 349 350 /** 351 * Should class lookup fail if not found in the current class map? 352 * 353 * @return bool 354 */ 355 public function isClassMapAuthoritative() 356 { 357 return $this->classMapAuthoritative; 358 } 359 360 /** 361 * APCu prefix to use to cache found/not-found classes, if the extension is enabled. 362 * 363 * @param string|null $apcuPrefix 364 * 365 * @return void 366 */ 367 public function setApcuPrefix($apcuPrefix) 368 { 369 $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; 370 } 371 372 /** 373 * The APCu prefix in use, or null if APCu caching is not enabled. 374 * 375 * @return string|null 376 */ 377 public function getApcuPrefix() 378 { 379 return $this->apcuPrefix; 380 } 381 382 /** 383 * Registers this instance as an autoloader. 384 * 385 * @param bool $prepend Whether to prepend the autoloader or not 386 * 387 * @return void 388 */ 389 public function register($prepend = false) 390 { 391 spl_autoload_register(array($this, 'loadClass'), true, $prepend); 392 393 if (null === $this->vendorDir) { 394 return; 395 } 396 397 if ($prepend) { 398 self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; 399 } else { 400 unset(self::$registeredLoaders[$this->vendorDir]); 401 self::$registeredLoaders[$this->vendorDir] = $this; 402 } 403 } 404 405 /** 406 * Unregisters this instance as an autoloader. 407 * 408 * @return void 409 */ 410 public function unregister() 411 { 412 spl_autoload_unregister(array($this, 'loadClass')); 413 414 if (null !== $this->vendorDir) { 415 unset(self::$registeredLoaders[$this->vendorDir]); 416 } 417 } 418 419 /** 420 * Loads the given class or interface. 421 * 422 * @param string $class The name of the class 423 * @return true|null True if loaded, null otherwise 424 */ 425 public function loadClass($class) 426 { 427 if ($file = $this->findFile($class)) { 428 includeFile($file); 429 430 return true; 431 } 432 433 return null; 434 } 435 436 /** 437 * Finds the path to the file where the class is defined. 438 * 439 * @param string $class The name of the class 440 * 441 * @return string|false The path if found, false otherwise 442 */ 443 public function findFile($class) 444 { 445 // class map lookup 446 if (isset($this->classMap[$class])) { 447 return $this->classMap[$class]; 448 } 449 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { 450 return false; 451 } 452 if (null !== $this->apcuPrefix) { 453 $file = apcu_fetch($this->apcuPrefix.$class, $hit); 454 if ($hit) { 455 return $file; 456 } 457 } 458 459 $file = $this->findFileWithExtension($class, '.php'); 460 461 // Search for Hack files if we are running on HHVM 462 if (false === $file && defined('HHVM_VERSION')) { 463 $file = $this->findFileWithExtension($class, '.hh'); 464 } 465 466 if (null !== $this->apcuPrefix) { 467 apcu_add($this->apcuPrefix.$class, $file); 468 } 469 470 if (false === $file) { 471 // Remember that this class does not exist. 472 $this->missingClasses[$class] = true; 473 } 474 475 return $file; 476 } 477 478 /** 479 * Returns the currently registered loaders indexed by their corresponding vendor directories. 480 * 481 * @return self[] 482 */ 483 public static function getRegisteredLoaders() 484 { 485 return self::$registeredLoaders; 486 } 487 488 /** 489 * @param string $class 490 * @param string $ext 491 * @return string|false 492 */ 493 private function findFileWithExtension($class, $ext) 494 { 495 // PSR-4 lookup 496 $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 497 498 $first = $class[0]; 499 if (isset($this->prefixLengthsPsr4[$first])) { 500 $subPath = $class; 501 while (false !== $lastPos = strrpos($subPath, '\\')) { 502 $subPath = substr($subPath, 0, $lastPos); 503 $search = $subPath . '\\'; 504 if (isset($this->prefixDirsPsr4[$search])) { 505 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); 506 foreach ($this->prefixDirsPsr4[$search] as $dir) { 507 if (file_exists($file = $dir . $pathEnd)) { 508 return $file; 509 } 510 } 511 } 512 } 513 } 514 515 // PSR-4 fallback dirs 516 foreach ($this->fallbackDirsPsr4 as $dir) { 517 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 518 return $file; 519 } 520 } 521 522 // PSR-0 lookup 523 if (false !== $pos = strrpos($class, '\\')) { 524 // namespaced class name 525 $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 526 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 527 } else { 528 // PEAR-like class name 529 $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 530 } 531 532 if (isset($this->prefixesPsr0[$first])) { 533 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 534 if (0 === strpos($class, $prefix)) { 535 foreach ($dirs as $dir) { 536 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 537 return $file; 538 } 539 } 540 } 541 } 542 } 543 544 // PSR-0 fallback dirs 545 foreach ($this->fallbackDirsPsr0 as $dir) { 546 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 547 return $file; 548 } 549 } 550 551 // PSR-0 include paths. 552 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 553 return $file; 554 } 555 556 return false; 557 } 43 class ClassLoader { 44 45 /** @var ?string */ 46 private $vendorDir; 47 48 // PSR-4 49 /** 50 * @var array[] 51 * @psalm-var array<string, array<string, int>> 52 */ 53 private $prefixLengthsPsr4 = array(); 54 /** 55 * @var array[] 56 * @psalm-var array<string, array<int, string>> 57 */ 58 private $prefixDirsPsr4 = array(); 59 /** 60 * @var array[] 61 * @psalm-var array<string, string> 62 */ 63 private $fallbackDirsPsr4 = array(); 64 65 // PSR-0 66 /** 67 * @var array[] 68 * @psalm-var array<string, array<string, string[]>> 69 */ 70 private $prefixesPsr0 = array(); 71 /** 72 * @var array[] 73 * @psalm-var array<string, string> 74 */ 75 private $fallbackDirsPsr0 = array(); 76 77 /** @var bool */ 78 private $useIncludePath = false; 79 80 /** 81 * @var string[] 82 * @psalm-var array<string, string> 83 */ 84 private $classMap = array(); 85 86 /** @var bool */ 87 private $classMapAuthoritative = false; 88 89 /** 90 * @var bool[] 91 * @psalm-var array<string, bool> 92 */ 93 private $missingClasses = array(); 94 95 /** @var ?string */ 96 private $apcuPrefix; 97 98 /** 99 * @var self[] 100 */ 101 private static $registeredLoaders = array(); 102 103 /** 104 * @param ?string $vendorDir 105 */ 106 public function __construct( $vendorDir = null ) { 107 $this->vendorDir = $vendorDir; 108 } 109 110 /** 111 * @return string[] 112 */ 113 public function getPrefixes() { 114 if ( ! empty( $this->prefixesPsr0 ) ) { 115 return call_user_func_array( 'array_merge', array_values( $this->prefixesPsr0 ) ); 116 } 117 118 return array(); 119 } 120 121 /** 122 * @return array[] 123 * @psalm-return array<string, array<int, string>> 124 */ 125 public function getPrefixesPsr4() { 126 return $this->prefixDirsPsr4; 127 } 128 129 /** 130 * @return array[] 131 * @psalm-return array<string, string> 132 */ 133 public function getFallbackDirs() { 134 return $this->fallbackDirsPsr0; 135 } 136 137 /** 138 * @return array[] 139 * @psalm-return array<string, string> 140 */ 141 public function getFallbackDirsPsr4() { 142 return $this->fallbackDirsPsr4; 143 } 144 145 /** 146 * @return string[] Array of classname => path 147 * @psalm-return array<string, string> 148 */ 149 public function getClassMap() { 150 return $this->classMap; 151 } 152 153 /** 154 * @param string[] $classMap Class to filename map 155 * @psalm-param array<string, string> $classMap 156 * 157 * @return void 158 */ 159 public function addClassMap( array $classMap ) { 160 if ( $this->classMap ) { 161 $this->classMap = array_merge( $this->classMap, $classMap ); 162 } else { 163 $this->classMap = $classMap; 164 } 165 } 166 167 /** 168 * Registers a set of PSR-0 directories for a given prefix, either 169 * appending or prepending to the ones previously set for this prefix. 170 * 171 * @param string $prefix The prefix 172 * @param string[]|string $paths The PSR-0 root directories 173 * @param bool $prepend Whether to prepend the directories 174 * 175 * @return void 176 */ 177 public function add( $prefix, $paths, $prepend = false ) { 178 if ( ! $prefix ) { 179 if ( $prepend ) { 180 $this->fallbackDirsPsr0 = array_merge( 181 (array) $paths, 182 $this->fallbackDirsPsr0 183 ); 184 } else { 185 $this->fallbackDirsPsr0 = array_merge( 186 $this->fallbackDirsPsr0, 187 (array) $paths 188 ); 189 } 190 191 return; 192 } 193 194 $first = $prefix[0]; 195 if ( ! isset( $this->prefixesPsr0[ $first ][ $prefix ] ) ) { 196 $this->prefixesPsr0[ $first ][ $prefix ] = (array) $paths; 197 198 return; 199 } 200 if ( $prepend ) { 201 $this->prefixesPsr0[ $first ][ $prefix ] = array_merge( 202 (array) $paths, 203 $this->prefixesPsr0[ $first ][ $prefix ] 204 ); 205 } else { 206 $this->prefixesPsr0[ $first ][ $prefix ] = array_merge( 207 $this->prefixesPsr0[ $first ][ $prefix ], 208 (array) $paths 209 ); 210 } 211 } 212 213 /** 214 * Registers a set of PSR-4 directories for a given namespace, either 215 * appending or prepending to the ones previously set for this namespace. 216 * 217 * @param string $prefix The prefix/namespace, with trailing '\\' 218 * @param string[]|string $paths The PSR-4 base directories 219 * @param bool $prepend Whether to prepend the directories 220 * 221 * @throws \InvalidArgumentException 222 * 223 * @return void 224 */ 225 public function addPsr4( $prefix, $paths, $prepend = false ) { 226 if ( ! $prefix ) { 227 // Register directories for the root namespace. 228 if ( $prepend ) { 229 $this->fallbackDirsPsr4 = array_merge( 230 (array) $paths, 231 $this->fallbackDirsPsr4 232 ); 233 } else { 234 $this->fallbackDirsPsr4 = array_merge( 235 $this->fallbackDirsPsr4, 236 (array) $paths 237 ); 238 } 239 } elseif ( ! isset( $this->prefixDirsPsr4[ $prefix ] ) ) { 240 // Register directories for a new namespace. 241 $length = strlen( $prefix ); 242 if ( '\\' !== $prefix[ $length - 1 ] ) { 243 throw new \InvalidArgumentException( 'A non-empty PSR-4 prefix must end with a namespace separator.' ); 244 } 245 $this->prefixLengthsPsr4[ $prefix[0] ][ $prefix ] = $length; 246 $this->prefixDirsPsr4[ $prefix ] = (array) $paths; 247 } elseif ( $prepend ) { 248 // Prepend directories for an already registered namespace. 249 $this->prefixDirsPsr4[ $prefix ] = array_merge( 250 (array) $paths, 251 $this->prefixDirsPsr4[ $prefix ] 252 ); 253 } else { 254 // Append directories for an already registered namespace. 255 $this->prefixDirsPsr4[ $prefix ] = array_merge( 256 $this->prefixDirsPsr4[ $prefix ], 257 (array) $paths 258 ); 259 } 260 } 261 262 /** 263 * Registers a set of PSR-0 directories for a given prefix, 264 * replacing any others previously set for this prefix. 265 * 266 * @param string $prefix The prefix 267 * @param string[]|string $paths The PSR-0 base directories 268 * 269 * @return void 270 */ 271 public function set( $prefix, $paths ) { 272 if ( ! $prefix ) { 273 $this->fallbackDirsPsr0 = (array) $paths; 274 } else { 275 $this->prefixesPsr0[ $prefix[0] ][ $prefix ] = (array) $paths; 276 } 277 } 278 279 /** 280 * Registers a set of PSR-4 directories for a given namespace, 281 * replacing any others previously set for this namespace. 282 * 283 * @param string $prefix The prefix/namespace, with trailing '\\' 284 * @param string[]|string $paths The PSR-4 base directories 285 * 286 * @throws \InvalidArgumentException 287 * 288 * @return void 289 */ 290 public function setPsr4( $prefix, $paths ) { 291 if ( ! $prefix ) { 292 $this->fallbackDirsPsr4 = (array) $paths; 293 } else { 294 $length = strlen( $prefix ); 295 if ( '\\' !== $prefix[ $length - 1 ] ) { 296 throw new \InvalidArgumentException( 'A non-empty PSR-4 prefix must end with a namespace separator.' ); 297 } 298 $this->prefixLengthsPsr4[ $prefix[0] ][ $prefix ] = $length; 299 $this->prefixDirsPsr4[ $prefix ] = (array) $paths; 300 } 301 } 302 303 /** 304 * Turns on searching the include path for class files. 305 * 306 * @param bool $useIncludePath 307 * 308 * @return void 309 */ 310 public function setUseIncludePath( $useIncludePath ) { 311 $this->useIncludePath = $useIncludePath; 312 } 313 314 /** 315 * Can be used to check if the autoloader uses the include path to check 316 * for classes. 317 * 318 * @return bool 319 */ 320 public function getUseIncludePath() { 321 return $this->useIncludePath; 322 } 323 324 /** 325 * Turns off searching the prefix and fallback directories for classes 326 * that have not been registered with the class map. 327 * 328 * @param bool $classMapAuthoritative 329 * 330 * @return void 331 */ 332 public function setClassMapAuthoritative( $classMapAuthoritative ) { 333 $this->classMapAuthoritative = $classMapAuthoritative; 334 } 335 336 /** 337 * Should class lookup fail if not found in the current class map? 338 * 339 * @return bool 340 */ 341 public function isClassMapAuthoritative() { 342 return $this->classMapAuthoritative; 343 } 344 345 /** 346 * APCu prefix to use to cache found/not-found classes, if the extension is enabled. 347 * 348 * @param string|null $apcuPrefix 349 * 350 * @return void 351 */ 352 public function setApcuPrefix( $apcuPrefix ) { 353 $this->apcuPrefix = function_exists( 'apcu_fetch' ) && filter_var( ini_get( 'apc.enabled' ), FILTER_VALIDATE_BOOLEAN ) ? $apcuPrefix : null; 354 } 355 356 /** 357 * The APCu prefix in use, or null if APCu caching is not enabled. 358 * 359 * @return string|null 360 */ 361 public function getApcuPrefix() { 362 return $this->apcuPrefix; 363 } 364 365 /** 366 * Registers this instance as an autoloader. 367 * 368 * @param bool $prepend Whether to prepend the autoloader or not 369 * 370 * @return void 371 */ 372 public function register( $prepend = false ) { 373 spl_autoload_register( array( $this, 'loadClass' ), true, $prepend ); 374 375 if ( null === $this->vendorDir ) { 376 return; 377 } 378 379 if ( $prepend ) { 380 self::$registeredLoaders = array( $this->vendorDir => $this ) + self::$registeredLoaders; 381 } else { 382 unset( self::$registeredLoaders[ $this->vendorDir ] ); 383 self::$registeredLoaders[ $this->vendorDir ] = $this; 384 } 385 } 386 387 /** 388 * Unregisters this instance as an autoloader. 389 * 390 * @return void 391 */ 392 public function unregister() { 393 spl_autoload_unregister( array( $this, 'loadClass' ) ); 394 395 if ( null !== $this->vendorDir ) { 396 unset( self::$registeredLoaders[ $this->vendorDir ] ); 397 } 398 } 399 400 /** 401 * Loads the given class or interface. 402 * 403 * @param string $class The name of the class 404 * @return true|null True if loaded, null otherwise 405 */ 406 public function loadClass( $class ) { 407 if ( $file = $this->findFile( $class ) ) { 408 includeFile( $file ); 409 410 return true; 411 } 412 413 return null; 414 } 415 416 /** 417 * Finds the path to the file where the class is defined. 418 * 419 * @param string $class The name of the class 420 * 421 * @return string|false The path if found, false otherwise 422 */ 423 public function findFile( $class ) { 424 // class map lookup 425 if ( isset( $this->classMap[ $class ] ) ) { 426 return $this->classMap[ $class ]; 427 } 428 if ( $this->classMapAuthoritative || isset( $this->missingClasses[ $class ] ) ) { 429 return false; 430 } 431 if ( null !== $this->apcuPrefix ) { 432 $file = apcu_fetch( $this->apcuPrefix . $class, $hit ); 433 if ( $hit ) { 434 return $file; 435 } 436 } 437 438 $file = $this->findFileWithExtension( $class, '.php' ); 439 440 // Search for Hack files if we are running on HHVM 441 if ( false === $file && defined( 'HHVM_VERSION' ) ) { 442 $file = $this->findFileWithExtension( $class, '.hh' ); 443 } 444 445 if ( null !== $this->apcuPrefix ) { 446 apcu_add( $this->apcuPrefix . $class, $file ); 447 } 448 449 if ( false === $file ) { 450 // Remember that this class does not exist. 451 $this->missingClasses[ $class ] = true; 452 } 453 454 return $file; 455 } 456 457 /** 458 * Returns the currently registered loaders indexed by their corresponding vendor directories. 459 * 460 * @return self[] 461 */ 462 public static function getRegisteredLoaders() { 463 return self::$registeredLoaders; 464 } 465 466 /** 467 * @param string $class 468 * @param string $ext 469 * @return string|false 470 */ 471 private function findFileWithExtension( $class, $ext ) { 472 // PSR-4 lookup 473 $logicalPathPsr4 = strtr( $class, '\\', DIRECTORY_SEPARATOR ) . $ext; 474 475 $first = $class[0]; 476 if ( isset( $this->prefixLengthsPsr4[ $first ] ) ) { 477 $subPath = $class; 478 while ( false !== $lastPos = strrpos( $subPath, '\\' ) ) { 479 $subPath = substr( $subPath, 0, $lastPos ); 480 $search = $subPath . '\\'; 481 if ( isset( $this->prefixDirsPsr4[ $search ] ) ) { 482 $pathEnd = DIRECTORY_SEPARATOR . substr( $logicalPathPsr4, $lastPos + 1 ); 483 foreach ( $this->prefixDirsPsr4[ $search ] as $dir ) { 484 if ( file_exists( $file = $dir . $pathEnd ) ) { 485 return $file; 486 } 487 } 488 } 489 } 490 } 491 492 // PSR-4 fallback dirs 493 foreach ( $this->fallbackDirsPsr4 as $dir ) { 494 if ( file_exists( $file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4 ) ) { 495 return $file; 496 } 497 } 498 499 // PSR-0 lookup 500 if ( false !== $pos = strrpos( $class, '\\' ) ) { 501 // namespaced class name 502 $logicalPathPsr0 = substr( $logicalPathPsr4, 0, $pos + 1 ) 503 . strtr( substr( $logicalPathPsr4, $pos + 1 ), '_', DIRECTORY_SEPARATOR ); 504 } else { 505 // PEAR-like class name 506 $logicalPathPsr0 = strtr( $class, '_', DIRECTORY_SEPARATOR ) . $ext; 507 } 508 509 if ( isset( $this->prefixesPsr0[ $first ] ) ) { 510 foreach ( $this->prefixesPsr0[ $first ] as $prefix => $dirs ) { 511 if ( 0 === strpos( $class, $prefix ) ) { 512 foreach ( $dirs as $dir ) { 513 if ( file_exists( $file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0 ) ) { 514 return $file; 515 } 516 } 517 } 518 } 519 } 520 521 // PSR-0 fallback dirs 522 foreach ( $this->fallbackDirsPsr0 as $dir ) { 523 if ( file_exists( $file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0 ) ) { 524 return $file; 525 } 526 } 527 528 // PSR-0 include paths. 529 if ( $this->useIncludePath && $file = stream_resolve_include_path( $logicalPathPsr0 ) ) { 530 return $file; 531 } 532 533 return false; 534 } 558 535 } 559 536 … … 567 544 * @private 568 545 */ 569 function includeFile($file) 570 { 571 include $file; 546 function includeFile( $file ) { 547 include $file; 572 548 } -
termageddon-usercentrics/trunk/vendor/composer/InstalledVersions.php
r2976730 r3160131 25 25 * @final 26 26 */ 27 class InstalledVersions 28 { 29 /** 30 * @var mixed[]|null 31 * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null 32 */ 33 private static $installed; 34 35 /** 36 * @var bool|null 37 */ 38 private static $canGetVendors; 39 40 /** 41 * @var array[] 42 * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 43 */ 44 private static $installedByVendor = array(); 45 46 /** 47 * Returns a list of all package names which are present, either by being installed, replaced or provided 48 * 49 * @return string[] 50 * @psalm-return list<string> 51 */ 52 public static function getInstalledPackages() 53 { 54 $packages = array(); 55 foreach (self::getInstalled() as $installed) { 56 $packages[] = array_keys($installed['versions']); 57 } 58 59 if (1 === \count($packages)) { 60 return $packages[0]; 61 } 62 63 return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); 64 } 65 66 /** 67 * Returns a list of all package names with a specific type e.g. 'library' 68 * 69 * @param string $type 70 * @return string[] 71 * @psalm-return list<string> 72 */ 73 public static function getInstalledPackagesByType($type) 74 { 75 $packagesByType = array(); 76 77 foreach (self::getInstalled() as $installed) { 78 foreach ($installed['versions'] as $name => $package) { 79 if (isset($package['type']) && $package['type'] === $type) { 80 $packagesByType[] = $name; 81 } 82 } 83 } 84 85 return $packagesByType; 86 } 87 88 /** 89 * Checks whether the given package is installed 90 * 91 * This also returns true if the package name is provided or replaced by another package 92 * 93 * @param string $packageName 94 * @param bool $includeDevRequirements 95 * @return bool 96 */ 97 public static function isInstalled($packageName, $includeDevRequirements = true) 98 { 99 foreach (self::getInstalled() as $installed) { 100 if (isset($installed['versions'][$packageName])) { 101 return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); 102 } 103 } 104 105 return false; 106 } 107 108 /** 109 * Checks whether the given package satisfies a version constraint 110 * 111 * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: 112 * 113 * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') 114 * 115 * @param VersionParser $parser Install composer/semver to have access to this class and functionality 116 * @param string $packageName 117 * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package 118 * @return bool 119 */ 120 public static function satisfies(VersionParser $parser, $packageName, $constraint) 121 { 122 $constraint = $parser->parseConstraints($constraint); 123 $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); 124 125 return $provided->matches($constraint); 126 } 127 128 /** 129 * Returns a version constraint representing all the range(s) which are installed for a given package 130 * 131 * It is easier to use this via isInstalled() with the $constraint argument if you need to check 132 * whether a given version of a package is installed, and not just whether it exists 133 * 134 * @param string $packageName 135 * @return string Version constraint usable with composer/semver 136 */ 137 public static function getVersionRanges($packageName) 138 { 139 foreach (self::getInstalled() as $installed) { 140 if (!isset($installed['versions'][$packageName])) { 141 continue; 142 } 143 144 $ranges = array(); 145 if (isset($installed['versions'][$packageName]['pretty_version'])) { 146 $ranges[] = $installed['versions'][$packageName]['pretty_version']; 147 } 148 if (array_key_exists('aliases', $installed['versions'][$packageName])) { 149 $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); 150 } 151 if (array_key_exists('replaced', $installed['versions'][$packageName])) { 152 $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); 153 } 154 if (array_key_exists('provided', $installed['versions'][$packageName])) { 155 $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); 156 } 157 158 return implode(' || ', $ranges); 159 } 160 161 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 162 } 163 164 /** 165 * @param string $packageName 166 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 167 */ 168 public static function getVersion($packageName) 169 { 170 foreach (self::getInstalled() as $installed) { 171 if (!isset($installed['versions'][$packageName])) { 172 continue; 173 } 174 175 if (!isset($installed['versions'][$packageName]['version'])) { 176 return null; 177 } 178 179 return $installed['versions'][$packageName]['version']; 180 } 181 182 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 183 } 184 185 /** 186 * @param string $packageName 187 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 188 */ 189 public static function getPrettyVersion($packageName) 190 { 191 foreach (self::getInstalled() as $installed) { 192 if (!isset($installed['versions'][$packageName])) { 193 continue; 194 } 195 196 if (!isset($installed['versions'][$packageName]['pretty_version'])) { 197 return null; 198 } 199 200 return $installed['versions'][$packageName]['pretty_version']; 201 } 202 203 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 204 } 205 206 /** 207 * @param string $packageName 208 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference 209 */ 210 public static function getReference($packageName) 211 { 212 foreach (self::getInstalled() as $installed) { 213 if (!isset($installed['versions'][$packageName])) { 214 continue; 215 } 216 217 if (!isset($installed['versions'][$packageName]['reference'])) { 218 return null; 219 } 220 221 return $installed['versions'][$packageName]['reference']; 222 } 223 224 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 225 } 226 227 /** 228 * @param string $packageName 229 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. 230 */ 231 public static function getInstallPath($packageName) 232 { 233 foreach (self::getInstalled() as $installed) { 234 if (!isset($installed['versions'][$packageName])) { 235 continue; 236 } 237 238 return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; 239 } 240 241 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 242 } 243 244 /** 245 * @return array 246 * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} 247 */ 248 public static function getRootPackage() 249 { 250 $installed = self::getInstalled(); 251 252 return $installed[0]['root']; 253 } 254 255 /** 256 * Returns the raw installed.php data for custom implementations 257 * 258 * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. 259 * @return array[] 260 * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} 261 */ 262 public static function getRawData() 263 { 264 @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); 265 266 if (null === self::$installed) { 267 // only require the installed.php file if this file is loaded from its dumped location, 268 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 269 if (substr(__DIR__, -8, 1) !== 'C') { 270 self::$installed = include __DIR__ . '/installed.php'; 271 } else { 272 self::$installed = array(); 273 } 274 } 275 276 return self::$installed; 277 } 278 279 /** 280 * Returns the raw data of all installed.php which are currently loaded for custom implementations 281 * 282 * @return array[] 283 * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 284 */ 285 public static function getAllRawData() 286 { 287 return self::getInstalled(); 288 } 289 290 /** 291 * Lets you reload the static array from another file 292 * 293 * This is only useful for complex integrations in which a project needs to use 294 * this class but then also needs to execute another project's autoloader in process, 295 * and wants to ensure both projects have access to their version of installed.php. 296 * 297 * A typical case would be PHPUnit, where it would need to make sure it reads all 298 * the data it needs from this class, then call reload() with 299 * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure 300 * the project in which it runs can then also use this class safely, without 301 * interference between PHPUnit's dependencies and the project's dependencies. 302 * 303 * @param array[] $data A vendor/composer/installed.php data set 304 * @return void 305 * 306 * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data 307 */ 308 public static function reload($data) 309 { 310 self::$installed = $data; 311 self::$installedByVendor = array(); 312 } 313 314 /** 315 * @return array[] 316 * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 317 */ 318 private static function getInstalled() 319 { 320 if (null === self::$canGetVendors) { 321 self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); 322 } 323 324 $installed = array(); 325 326 if (self::$canGetVendors) { 327 foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { 328 if (isset(self::$installedByVendor[$vendorDir])) { 329 $installed[] = self::$installedByVendor[$vendorDir]; 330 } elseif (is_file($vendorDir.'/composer/installed.php')) { 331 $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; 332 if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { 333 self::$installed = $installed[count($installed) - 1]; 334 } 335 } 336 } 337 } 338 339 if (null === self::$installed) { 340 // only require the installed.php file if this file is loaded from its dumped location, 341 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 342 if (substr(__DIR__, -8, 1) !== 'C') { 343 self::$installed = require __DIR__ . '/installed.php'; 344 } else { 345 self::$installed = array(); 346 } 347 } 348 $installed[] = self::$installed; 349 350 return $installed; 351 } 27 class InstalledVersions { 28 29 /** 30 * @var mixed[]|null 31 * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null 32 */ 33 private static $installed; 34 35 /** 36 * @var bool|null 37 */ 38 private static $canGetVendors; 39 40 /** 41 * @var array[] 42 * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 43 */ 44 private static $installedByVendor = array(); 45 46 /** 47 * Returns a list of all package names which are present, either by being installed, replaced or provided 48 * 49 * @return string[] 50 * @psalm-return list<string> 51 */ 52 public static function getInstalledPackages() { 53 $packages = array(); 54 foreach ( self::getInstalled() as $installed ) { 55 $packages[] = array_keys( $installed['versions'] ); 56 } 57 58 if ( 1 === \count( $packages ) ) { 59 return $packages[0]; 60 } 61 62 return array_keys( array_flip( \call_user_func_array( 'array_merge', $packages ) ) ); 63 } 64 65 /** 66 * Returns a list of all package names with a specific type e.g. 'library' 67 * 68 * @param string $type 69 * @return string[] 70 * @psalm-return list<string> 71 */ 72 public static function getInstalledPackagesByType( $type ) { 73 $packagesByType = array(); 74 75 foreach ( self::getInstalled() as $installed ) { 76 foreach ( $installed['versions'] as $name => $package ) { 77 if ( isset( $package['type'] ) && $package['type'] === $type ) { 78 $packagesByType[] = $name; 79 } 80 } 81 } 82 83 return $packagesByType; 84 } 85 86 /** 87 * Checks whether the given package is installed 88 * 89 * This also returns true if the package name is provided or replaced by another package 90 * 91 * @param string $packageName 92 * @param bool $includeDevRequirements 93 * @return bool 94 */ 95 public static function isInstalled( $packageName, $includeDevRequirements = true ) { 96 foreach ( self::getInstalled() as $installed ) { 97 if ( isset( $installed['versions'][ $packageName ] ) ) { 98 return $includeDevRequirements || empty( $installed['versions'][ $packageName ]['dev_requirement'] ); 99 } 100 } 101 102 return false; 103 } 104 105 /** 106 * Checks whether the given package satisfies a version constraint 107 * 108 * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: 109 * 110 * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') 111 * 112 * @param VersionParser $parser Install composer/semver to have access to this class and functionality 113 * @param string $packageName 114 * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package 115 * @return bool 116 */ 117 public static function satisfies( VersionParser $parser, $packageName, $constraint ) { 118 $constraint = $parser->parseConstraints( $constraint ); 119 $provided = $parser->parseConstraints( self::getVersionRanges( $packageName ) ); 120 121 return $provided->matches( $constraint ); 122 } 123 124 /** 125 * Returns a version constraint representing all the range(s) which are installed for a given package 126 * 127 * It is easier to use this via isInstalled() with the $constraint argument if you need to check 128 * whether a given version of a package is installed, and not just whether it exists 129 * 130 * @param string $packageName 131 * @return string Version constraint usable with composer/semver 132 */ 133 public static function getVersionRanges( $packageName ) { 134 foreach ( self::getInstalled() as $installed ) { 135 if ( ! isset( $installed['versions'][ $packageName ] ) ) { 136 continue; 137 } 138 139 $ranges = array(); 140 if ( isset( $installed['versions'][ $packageName ]['pretty_version'] ) ) { 141 $ranges[] = $installed['versions'][ $packageName ]['pretty_version']; 142 } 143 if ( array_key_exists( 'aliases', $installed['versions'][ $packageName ] ) ) { 144 $ranges = array_merge( $ranges, $installed['versions'][ $packageName ]['aliases'] ); 145 } 146 if ( array_key_exists( 'replaced', $installed['versions'][ $packageName ] ) ) { 147 $ranges = array_merge( $ranges, $installed['versions'][ $packageName ]['replaced'] ); 148 } 149 if ( array_key_exists( 'provided', $installed['versions'][ $packageName ] ) ) { 150 $ranges = array_merge( $ranges, $installed['versions'][ $packageName ]['provided'] ); 151 } 152 153 return implode( ' || ', $ranges ); 154 } 155 156 throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' ); 157 } 158 159 /** 160 * @param string $packageName 161 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 162 */ 163 public static function getVersion( $packageName ) { 164 foreach ( self::getInstalled() as $installed ) { 165 if ( ! isset( $installed['versions'][ $packageName ] ) ) { 166 continue; 167 } 168 169 if ( ! isset( $installed['versions'][ $packageName ]['version'] ) ) { 170 return null; 171 } 172 173 return $installed['versions'][ $packageName ]['version']; 174 } 175 176 throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' ); 177 } 178 179 /** 180 * @param string $packageName 181 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 182 */ 183 public static function getPrettyVersion( $packageName ) { 184 foreach ( self::getInstalled() as $installed ) { 185 if ( ! isset( $installed['versions'][ $packageName ] ) ) { 186 continue; 187 } 188 189 if ( ! isset( $installed['versions'][ $packageName ]['pretty_version'] ) ) { 190 return null; 191 } 192 193 return $installed['versions'][ $packageName ]['pretty_version']; 194 } 195 196 throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' ); 197 } 198 199 /** 200 * @param string $packageName 201 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference 202 */ 203 public static function getReference( $packageName ) { 204 foreach ( self::getInstalled() as $installed ) { 205 if ( ! isset( $installed['versions'][ $packageName ] ) ) { 206 continue; 207 } 208 209 if ( ! isset( $installed['versions'][ $packageName ]['reference'] ) ) { 210 return null; 211 } 212 213 return $installed['versions'][ $packageName ]['reference']; 214 } 215 216 throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' ); 217 } 218 219 /** 220 * @param string $packageName 221 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. 222 */ 223 public static function getInstallPath( $packageName ) { 224 foreach ( self::getInstalled() as $installed ) { 225 if ( ! isset( $installed['versions'][ $packageName ] ) ) { 226 continue; 227 } 228 229 return isset( $installed['versions'][ $packageName ]['install_path'] ) ? $installed['versions'][ $packageName ]['install_path'] : null; 230 } 231 232 throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' ); 233 } 234 235 /** 236 * @return array 237 * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} 238 */ 239 public static function getRootPackage() { 240 $installed = self::getInstalled(); 241 242 return $installed[0]['root']; 243 } 244 245 /** 246 * Returns the raw installed.php data for custom implementations 247 * 248 * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. 249 * @return array[] 250 * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} 251 */ 252 public static function getRawData() { 253 @trigger_error( 'getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED ); 254 255 if ( null === self::$installed ) { 256 // only require the installed.php file if this file is loaded from its dumped location, 257 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 258 if ( substr( __DIR__, -8, 1 ) !== 'C' ) { 259 self::$installed = include __DIR__ . '/installed.php'; 260 } else { 261 self::$installed = array(); 262 } 263 } 264 265 return self::$installed; 266 } 267 268 /** 269 * Returns the raw data of all installed.php which are currently loaded for custom implementations 270 * 271 * @return array[] 272 * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 273 */ 274 public static function getAllRawData() { 275 return self::getInstalled(); 276 } 277 278 /** 279 * Lets you reload the static array from another file 280 * 281 * This is only useful for complex integrations in which a project needs to use 282 * this class but then also needs to execute another project's autoloader in process, 283 * and wants to ensure both projects have access to their version of installed.php. 284 * 285 * A typical case would be PHPUnit, where it would need to make sure it reads all 286 * the data it needs from this class, then call reload() with 287 * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure 288 * the project in which it runs can then also use this class safely, without 289 * interference between PHPUnit's dependencies and the project's dependencies. 290 * 291 * @param array[] $data A vendor/composer/installed.php data set 292 * @return void 293 * 294 * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data 295 */ 296 public static function reload( $data ) { 297 self::$installed = $data; 298 self::$installedByVendor = array(); 299 } 300 301 /** 302 * @return array[] 303 * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> 304 */ 305 private static function getInstalled() { 306 if ( null === self::$canGetVendors ) { 307 self::$canGetVendors = method_exists( 'Composer\Autoload\ClassLoader', 'getRegisteredLoaders' ); 308 } 309 310 $installed = array(); 311 312 if ( self::$canGetVendors ) { 313 foreach ( ClassLoader::getRegisteredLoaders() as $vendorDir => $loader ) { 314 if ( isset( self::$installedByVendor[ $vendorDir ] ) ) { 315 $installed[] = self::$installedByVendor[ $vendorDir ]; 316 } elseif ( is_file( $vendorDir . '/composer/installed.php' ) ) { 317 $installed[] = self::$installedByVendor[ $vendorDir ] = require $vendorDir . '/composer/installed.php'; 318 if ( null === self::$installed && strtr( $vendorDir . '/composer', '\\', '/' ) === strtr( __DIR__, '\\', '/' ) ) { 319 self::$installed = $installed[ count( $installed ) - 1 ]; 320 } 321 } 322 } 323 } 324 325 if ( null === self::$installed ) { 326 // only require the installed.php file if this file is loaded from its dumped location, 327 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 328 if ( substr( __DIR__, -8, 1 ) !== 'C' ) { 329 self::$installed = require __DIR__ . '/installed.php'; 330 } else { 331 self::$installed = array(); 332 } 333 } 334 $installed[] = self::$installed; 335 336 return $installed; 337 } 352 338 } -
termageddon-usercentrics/trunk/vendor/composer/autoload_classmap.php
r2771752 r3160131 3 3 // autoload_classmap.php @generated by Composer 4 4 5 $vendorDir = dirname( __DIR__);6 $baseDir = dirname($vendorDir);5 $vendorDir = dirname( __DIR__ ); 6 $baseDir = dirname( $vendorDir ); 7 7 8 8 return array( 9 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',9 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 10 10 ); -
termageddon-usercentrics/trunk/vendor/composer/autoload_namespaces.php
r2771752 r3160131 3 3 // autoload_namespaces.php @generated by Composer 4 4 5 $vendorDir = dirname( __DIR__);6 $baseDir = dirname($vendorDir);5 $vendorDir = dirname( __DIR__ ); 6 $baseDir = dirname( $vendorDir ); 7 7 8 return array( 9 ); 8 return array(); -
termageddon-usercentrics/trunk/vendor/composer/autoload_psr4.php
r2771752 r3160131 3 3 // autoload_psr4.php @generated by Composer 4 4 5 $vendorDir = dirname( __DIR__);6 $baseDir = dirname($vendorDir);5 $vendorDir = dirname( __DIR__ ); 6 $baseDir = dirname( $vendorDir ); 7 7 8 8 return array( 9 'MaxMind\\WebService\\' => array($vendorDir . '/maxmind/web-service-common/src/WebService'),10 'MaxMind\\Exception\\' => array($vendorDir . '/maxmind/web-service-common/src/Exception'),11 'MaxMind\\Db\\' => array($vendorDir . '/maxmind-db/reader/src/MaxMind/Db'),12 'GeoIp2\\' => array($vendorDir . '/geoip2/geoip2/src'),13 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),9 'MaxMind\\WebService\\' => array( $vendorDir . '/maxmind/web-service-common/src/WebService' ), 10 'MaxMind\\Exception\\' => array( $vendorDir . '/maxmind/web-service-common/src/Exception' ), 11 'MaxMind\\Db\\' => array( $vendorDir . '/maxmind-db/reader/src/MaxMind/Db' ), 12 'GeoIp2\\' => array( $vendorDir . '/geoip2/geoip2/src' ), 13 'Composer\\CaBundle\\' => array( $vendorDir . '/composer/ca-bundle/src' ), 14 14 ); -
termageddon-usercentrics/trunk/vendor/composer/autoload_real.php
r2976730 r3160131 3 3 // autoload_real.php @generated by Composer 4 4 5 class ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e 6 { 7 private static $loader; 5 class ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e { 8 6 9 public static function loadClassLoader($class) 10 { 11 if ('Composer\Autoload\ClassLoader' === $class) { 12 require __DIR__ . '/ClassLoader.php'; 13 } 14 } 7 private static $loader; 15 8 16 /** 17 * @return \Composer\Autoload\ClassLoader 18 */ 19 public static function getLoader() 20 { 21 if (null !== self::$loader) { 22 return self::$loader; 23 } 9 public static function loadClassLoader( $class ) { 10 if ( 'Composer\Autoload\ClassLoader' === $class ) { 11 require __DIR__ . '/ClassLoader.php'; 12 } 13 } 24 14 25 require __DIR__ . '/platform_check.php'; 15 /** 16 * @return \Composer\Autoload\ClassLoader 17 */ 18 public static function getLoader() { 19 if ( null !== self::$loader ) { 20 return self::$loader; 21 } 26 22 27 spl_autoload_register(array('ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader'), true, true); 28 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); 29 spl_autoload_unregister(array('ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader')); 23 require __DIR__ . '/platform_check.php'; 30 24 31 require __DIR__ . '/autoload_static.php'; 32 call_user_func(\Composer\Autoload\ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::getInitializer($loader)); 25 spl_autoload_register( array( 'ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader' ), true, true ); 26 self::$loader = $loader = new \Composer\Autoload\ClassLoader( \dirname( __DIR__ ) ); 27 spl_autoload_unregister( array( 'ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader' ) ); 33 28 34 $loader->register(true); 29 require __DIR__ . '/autoload_static.php'; 30 call_user_func( \Composer\Autoload\ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::getInitializer( $loader ) ); 35 31 36 return $loader; 37 } 32 $loader->register( true ); 33 34 return $loader; 35 } 38 36 } -
termageddon-usercentrics/trunk/vendor/composer/autoload_static.php
r2976730 r3160131 5 5 namespace Composer\Autoload; 6 6 7 class ComposerStaticInit68df2c2b623d60a4301d3d70719d751e 8 { 9 public static $prefixLengthsPsr4 = array ( 10 'M' => 11 array ( 12 'MaxMind\\WebService\\' => 19, 13 'MaxMind\\Exception\\' => 18, 14 'MaxMind\\Db\\' => 11, 15 ), 16 'G' => 17 array ( 18 'GeoIp2\\' => 7, 19 ), 20 'C' => 21 array ( 22 'Composer\\CaBundle\\' => 18, 23 ), 24 ); 7 class ComposerStaticInit68df2c2b623d60a4301d3d70719d751e { 25 8 26 public static $prefixDirsPsr4 = array ( 27 'MaxMind\\WebService\\' => 28 array ( 29 0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService', 30 ), 31 'MaxMind\\Exception\\' => 32 array ( 33 0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception', 34 ), 35 'MaxMind\\Db\\' => 36 array ( 37 0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db', 38 ), 39 'GeoIp2\\' => 40 array ( 41 0 => __DIR__ . '/..' . '/geoip2/geoip2/src', 42 ), 43 'Composer\\CaBundle\\' => 44 array ( 45 0 => __DIR__ . '/..' . '/composer/ca-bundle/src', 46 ), 47 ); 9 public static $prefixLengthsPsr4 = array( 10 'M' => 11 array( 12 'MaxMind\\WebService\\' => 19, 13 'MaxMind\\Exception\\' => 18, 14 'MaxMind\\Db\\' => 11, 15 ), 16 'G' => 17 array( 18 'GeoIp2\\' => 7, 19 ), 20 'C' => 21 array( 22 'Composer\\CaBundle\\' => 18, 23 ), 24 ); 48 25 49 public static $classMap = array ( 50 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 51 ); 26 public static $prefixDirsPsr4 = array( 27 'MaxMind\\WebService\\' => 28 array( 29 0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService', 30 ), 31 'MaxMind\\Exception\\' => 32 array( 33 0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception', 34 ), 35 'MaxMind\\Db\\' => 36 array( 37 0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db', 38 ), 39 'GeoIp2\\' => 40 array( 41 0 => __DIR__ . '/..' . '/geoip2/geoip2/src', 42 ), 43 'Composer\\CaBundle\\' => 44 array( 45 0 => __DIR__ . '/..' . '/composer/ca-bundle/src', 46 ), 47 ); 52 48 53 public static function getInitializer(ClassLoader $loader) 54 { 55 return \Closure::bind(function () use ($loader) { 56 $loader->prefixLengthsPsr4 = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixLengthsPsr4; 57 $loader->prefixDirsPsr4 = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixDirsPsr4; 58 $loader->classMap = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$classMap; 49 public static $classMap = array( 50 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 51 ); 59 52 60 }, null, ClassLoader::class); 61 } 53 public static function getInitializer( ClassLoader $loader ) { 54 return \Closure::bind( 55 function () use ( $loader ) { 56 $loader->prefixLengthsPsr4 = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixLengthsPsr4; 57 $loader->prefixDirsPsr4 = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixDirsPsr4; 58 $loader->classMap = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$classMap; 59 60 }, 61 null, 62 ClassLoader::class 63 ); 64 } 62 65 } -
termageddon-usercentrics/trunk/vendor/composer/ca-bundle/src/CaBundle.php
r2976730 r3160131 19 19 * @author Jordi Boggiano <j.boggiano@seld.be> 20 20 */ 21 class CaBundle 22 { 23 /** @var string|null */24 private static $caPath;25 /** @var array<string, bool> */26 private static $caFileValidity = array();27 /** @var bool|null */28 private static $useOpensslParse;29 30 /**31 * Returns the system CA bundle path, or a path to the bundled one32 *33 * This method was adapted from Sslurp.34 * https://github.com/EvanDotPro/Sslurp35 *36 * (c) Evan Coury <me@evancoury.com>37 *38 * For the full copyright and license information, please see below:39 *40 * Copyright (c) 2013, Evan Coury41 * All rights reserved.42 *43 * Redistribution and use in source and binary forms, with or without modification,44 * are permitted provided that the following conditions are met:45 *46 * * Redistributions of source code must retain the above copyright notice,47 * this list of conditions and the following disclaimer.48 *49 * * Redistributions in binary form must reproduce the above copyright notice,50 * this list of conditions and the following disclaimer in the documentation51 * and/or other materials provided with the distribution.52 *53 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED55 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE56 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR57 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES58 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;59 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON60 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS62 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.63 *64 * @param LoggerInterface $logger optional logger for information about which CA files were loaded65 * @return string path to a CA bundle file or directory66 */67 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null) 68 {69 if (self::$caPath !== null) { 70 return self::$caPath; 71 } 72 $caBundlePaths = array(); 73 74 // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.75 // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. 76 $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE'); 77 78 // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.79 // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. 80 $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR'); 81 82 $caBundlePaths[] = ini_get('openssl.cafile');83 $caBundlePaths[] = ini_get('openssl.capath'); 84 85 $otherLocations = array( 86 '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS(ca-certificates package)87 '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux(ca-certificates package)88 '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificatespackage)89 '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package) 90 '/usr/ssl/certs/ca-bundle.crt', // Cygwin 91 '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package 92 '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option) 93 '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat? 94 '/etc/ssl/cert.pem', // OpenBSD 95 '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x 96 '/usr/local/etc/openssl/cert.pem', // OS X homebrew, opensslpackage97 '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package 98 ); 99 100 foreach($otherLocations as $location) { 101 $otherLocations[] = dirname($location); 102 } 103 104 $caBundlePaths = array_merge($caBundlePaths, $otherLocations); 105 106 foreach ($caBundlePaths as $caBundle) {107 if ($caBundle && self::caFileUsable($caBundle, $logger)) { 108 return self::$caPath = $caBundle; 109 } 110 111 if ($caBundle && self::caDirUsable($caBundle, $logger)) { 112 return self::$caPath = $caBundle; 113 }114 } 115 116 return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort 117 } 118 119 /** 120 * Returns the path to the bundled CA file 121 * 122 * In case you don't want to trust the user or the system, you can use this directly 123 * 124 * @return string path to a CA bundle file 125 */ 126 public static function getBundledCaBundlePath() 127 { 128 $caBundleFile = __DIR__.'/../res/cacert.pem'; 129 130 // cURL does not understand 'phar://' paths 131 // see https://github.com/composer/ca-bundle/issues/10 132 if (0 === strpos($caBundleFile, 'phar://')) {133 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-');134 if (false === $tempCaBundleFile) { 135 throw new \RuntimeException('Could not create a temporary file to store the bundled CA file'); 136 } 137 138 file_put_contents( 139 $tempCaBundleFile, 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 use155 *156 * @param string $filename157 * @param LoggerInterface $logger optional logger for information about which CA files were loaded158 *159 * @return bool160 */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_VERSION178 )); 179 $warned = true;180 } 181 182 $isValid = !empty($contents); 183 } elseif (is_string($contents) && strlen($contents) > 0) { 184 $contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents); 185 if (null === $contents) { 186 // regex extraction failed 187 $isValid = false; 188 } else { 189 $isValid = (bool) openssl_x509_parse($contents); 190 } 191 } else { 192 $isValid = false; 193 } 194 195 if ($logger) { 196 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid')); 197 } 198 199 return self::$caFileValidity[$filename] = $isValid; 200 } 201 202 /** 203 * Test if it is safe to use the PHP function openssl_x509_parse(). 204 * 205 * This checks if OpenSSL extensions is vulnerable to remote code execution 206 * via the exploit documented as CVE-2013-6420. 207 * 208 * @return bool 209 */ 210 public static function isOpensslParseSafe() 211 {212 if (null !== self::$useOpensslParse) {213 return self::$useOpensslParse;214 }215 216 if (PHP_VERSION_ID >= 50600) {217 return self::$useOpensslParse = true;218 }219 220 // Vulnerable:221 // PHP 5.3.0 - PHP 5.3.27222 // PHP 5.4.0 - PHP 5.4.22223 // PHP 5.5.0 - PHP 5.5.6224 if (225 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)226 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)227 || PHP_VERSION_ID >= 50507228 ) {229 // This version of PHP has the fix for CVE-2013-6420 applied.230 return self::$useOpensslParse = true;231 }232 233 if (defined('PHP_WINDOWS_VERSION_BUILD')) {234 // Windows is probably insecure in this case.235 return self::$useOpensslParse = false;236 }237 238 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {239 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';240 241 if (preg_match($regex, PHP_VERSION, $m)) {242 return ((int) $m[1]) >= $fixedVersion;243 }244 245 return false;246 };247 248 // Hard coded list of PHP distributions with the fix backported.249 if (250 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)251 || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)252 || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)253 ) {254 return self::$useOpensslParse = true;255 }256 257 // Symfony Process component is missing so we assume it is unsafe at this point258 if (!class_exists('Symfony\Component\Process\PhpProcess')) {259 return self::$useOpensslParse = false;260 }261 262 // This is where things get crazy, because distros backport security263 // fixes the chances are on NIX systems the fix has been applied but264 // it's not possible to verify that from the PHP version.265 //266 // To verify exec a new PHP process and run the issue testcase with267 // known safe input that replicates the bug.268 269 // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415270 // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593271 $cert= 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';272 $script = <<<'EOT'21 class CaBundle { 22 23 /** @var string|null */ 24 private static $caPath; 25 /** @var array<string, bool> */ 26 private static $caFileValidity = array(); 27 /** @var bool|null */ 28 private static $useOpensslParse; 29 30 /** 31 * Returns the system CA bundle path, or a path to the bundled one 32 * 33 * This method was adapted from Sslurp. 34 * https://github.com/EvanDotPro/Sslurp 35 * 36 * (c) Evan Coury <me@evancoury.com> 37 * 38 * For the full copyright and license information, please see below: 39 * 40 * Copyright (c) 2013, Evan Coury 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without modification, 44 * are permitted provided that the following conditions are met: 45 * 46 * * Redistributions of source code must retain the above copyright notice, 47 * this list of conditions and the following disclaimer. 48 * 49 * * Redistributions in binary form must reproduce the above copyright notice, 50 * this list of conditions and the following disclaimer in the documentation 51 * and/or other materials provided with the distribution. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 55 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 56 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 57 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 58 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 59 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 60 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 62 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 63 * 64 * @param LoggerInterface $logger optional logger for information about which CA files were loaded 65 * @return string path to a CA bundle file or directory 66 */ 67 public static function getSystemCaRootBundlePath( LoggerInterface $logger = null ) { 68 if ( self::$caPath !== null ) { 69 return self::$caPath; 70 } 71 $caBundlePaths = array(); 72 73 // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that. 74 // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. 75 $caBundlePaths[] = self::getEnvVariable( 'SSL_CERT_FILE' ); 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 $caBundlePaths[] = self::getEnvVariable( 'SSL_CERT_DIR' ); 80 81 $caBundlePaths[] = ini_get( 'openssl.cafile' ); 82 $caBundlePaths[] = ini_get( 'openssl.capath' ); 83 84 $otherLocations = array( 85 '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) 86 '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package) 87 '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package) 88 '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package) 89 '/usr/ssl/certs/ca-bundle.crt', // Cygwin 90 '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package 91 '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option) 92 '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat? 93 '/etc/ssl/cert.pem', // OpenBSD 94 '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x 95 '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package 96 '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package 97 ); 98 99 foreach ( $otherLocations as $location ) { 100 $otherLocations[] = dirname( $location ); 101 } 102 103 $caBundlePaths = array_merge( $caBundlePaths, $otherLocations ); 104 105 foreach ( $caBundlePaths as $caBundle ) { 106 if ( $caBundle && self::caFileUsable( $caBundle, $logger ) ) { 107 return self::$caPath = $caBundle; 108 } 109 110 if ( $caBundle && self::caDirUsable( $caBundle, $logger ) ) { 111 return self::$caPath = $caBundle; 112 } 113 } 114 115 return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort 116 } 117 118 /** 119 * Returns the path to the bundled CA file 120 * 121 * In case you don't want to trust the user or the system, you can use this directly 122 * 123 * @return string path to a CA bundle file 124 */ 125 public static function getBundledCaBundlePath() { 126 $caBundleFile = __DIR__ . '/../res/cacert.pem'; 127 128 // cURL does not understand 'phar://' paths 129 // see https://github.com/composer/ca-bundle/issues/10 130 if ( 0 === strpos( $caBundleFile, 'phar://' ) ) { 131 $tempCaBundleFile = tempnam( sys_get_temp_dir(), 'openssl-ca-bundle-' ); 132 if ( false === $tempCaBundleFile ) { 133 throw new \RuntimeException( 'Could not create a temporary file to store the bundled CA file' ); 134 } 135 136 file_put_contents( 137 $tempCaBundleFile, 138 file_get_contents( $caBundleFile ) 139 ); 140 141 register_shutdown_function( 142 function() use ( $tempCaBundleFile ) { 143 @unlink( $tempCaBundleFile ); 144 } 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 static $warned = false; 163 164 if ( isset( self::$caFileValidity[ $filename ] ) ) { 165 return self::$caFileValidity[ $filename ]; 166 } 167 168 $contents = file_get_contents( $filename ); 169 170 // assume the CA is valid if php is vulnerable to 171 // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html 172 if ( ! static::isOpensslParseSafe() ) { 173 if ( ! $warned && $logger ) { 174 $logger->warning( 175 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 ); 180 $warned = true; 181 } 182 183 $isValid = ! empty( $contents ); 184 } elseif ( is_string( $contents ) && strlen( $contents ) > 0 ) { 185 $contents = preg_replace( '/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)$/m', '$1 $2', $contents ); 186 if ( null === $contents ) { 187 // regex extraction failed 188 $isValid = false; 189 } else { 190 $isValid = (bool) openssl_x509_parse( $contents ); 191 } 192 } else { 193 $isValid = false; 194 } 195 196 if ( $logger ) { 197 $logger->debug( 'Checked CA file ' . realpath( $filename ) . ': ' . ( $isValid ? 'valid' : 'invalid' ) ); 198 } 199 200 return self::$caFileValidity[ $filename ] = $isValid; 201 } 202 203 /** 204 * Test if it is safe to use the PHP function openssl_x509_parse(). 205 * 206 * This checks if OpenSSL extensions is vulnerable to remote code execution 207 * via the exploit documented as CVE-2013-6420. 208 * 209 * @return bool 210 */ 211 public static function isOpensslParseSafe() { 212 if ( null !== self::$useOpensslParse ) { 213 return self::$useOpensslParse; 214 } 215 216 if ( PHP_VERSION_ID >= 50600 ) { 217 return self::$useOpensslParse = true; 218 } 219 220 // Vulnerable: 221 // PHP 5.3.0 - PHP 5.3.27 222 // PHP 5.4.0 - PHP 5.4.22 223 // PHP 5.5.0 - PHP 5.5.6 224 if ( 225 ( PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328 ) 226 || ( PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423 ) 227 || PHP_VERSION_ID >= 50507 228 ) { 229 // This version of PHP has the fix for CVE-2013-6420 applied. 230 return self::$useOpensslParse = true; 231 } 232 233 if ( defined( 'PHP_WINDOWS_VERSION_BUILD' ) ) { 234 // Windows is probably insecure in this case. 235 return self::$useOpensslParse = false; 236 } 237 238 $compareDistroVersionPrefix = function ( $prefix, $fixedVersion ) { 239 $regex = '{^' . preg_quote( $prefix ) . '([0-9]+)$}'; 240 241 if ( preg_match( $regex, PHP_VERSION, $m ) ) { 242 return ( (int) $m[1] ) >= $fixedVersion; 243 } 244 245 return false; 246 }; 247 248 // Hard coded list of PHP distributions with the fix backported. 249 if ( 250 $compareDistroVersionPrefix( '5.3.3-7+squeeze', 18 ) // Debian 6 (Squeeze) 251 || $compareDistroVersionPrefix( '5.4.4-14+deb7u', 7 ) // Debian 7 (Wheezy) 252 || $compareDistroVersionPrefix( '5.3.10-1ubuntu3.', 9 ) // Ubuntu 12.04 (Precise) 253 ) { 254 return self::$useOpensslParse = true; 255 } 256 257 // Symfony Process component is missing so we assume it is unsafe at this point 258 if ( ! class_exists( 'Symfony\Component\Process\PhpProcess' ) ) { 259 return self::$useOpensslParse = false; 260 } 261 262 // This is where things get crazy, because distros backport security 263 // fixes the chances are on NIX systems the fix has been applied but 264 // it's not possible to verify that from the PHP version. 265 // 266 // To verify exec a new PHP process and run the issue testcase with 267 // known safe input that replicates the bug. 268 269 // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415 270 // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593 271 $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K'; 272 $script = <<<'EOT' 273 273 274 274 error_reporting(-1); … … 277 277 278 278 EOT; 279 $script = '<'."?php\n".sprintf($script, $cert); 280 281 try { 282 $process = new PhpProcess($script); 283 $process->mustRun(); 284 } catch (\Exception $e) { 285 // In the case of any exceptions just accept it is not possible to 286 // determine the safety of openssl_x509_parse and bail out. 287 return self::$useOpensslParse = false; 288 } 289 290 $output = preg_split('{\r?\n}', trim($process->getOutput())); 291 $errorOutput = trim($process->getErrorOutput()); 292 293 if ( 294 is_array($output) 295 && count($output) === 3 296 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION) 297 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"' 298 && $output[2] === 'int(-1)' 299 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput) 300 ) { 301 // This PHP has the fix backported probably by a distro security team. 302 return self::$useOpensslParse = true; 303 } 304 305 return self::$useOpensslParse = false; 306 } 307 308 /** 309 * Resets the static caches 310 * @return void 311 */ 312 public static function reset() 313 { 314 self::$caFileValidity = array(); 315 self::$caPath = null; 316 self::$useOpensslParse = null; 317 } 318 319 /** 320 * @param string $name 321 * @return string|false 322 */ 323 private static function getEnvVariable($name) 324 { 325 if (isset($_SERVER[$name])) { 326 return (string) $_SERVER[$name]; 327 } 328 329 if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) { 330 return (string) $value; 331 } 332 333 return false; 334 } 335 336 /** 337 * @param string|false $certFile 338 * @param LoggerInterface|null $logger 339 * @return bool 340 */ 341 private static function caFileUsable($certFile, LoggerInterface $logger = null) 342 { 343 return $certFile 344 && static::isFile($certFile, $logger) 345 && static::isReadable($certFile, $logger) 346 && static::validateCaFile($certFile, $logger); 347 } 348 349 /** 350 * @param string|false $certDir 351 * @param LoggerInterface|null $logger 352 * @return bool 353 */ 354 private static function caDirUsable($certDir, LoggerInterface $logger = null) 355 { 356 return $certDir 357 && static::isDir($certDir, $logger) 358 && static::isReadable($certDir, $logger) 359 && static::glob($certDir . '/*', $logger); 360 } 361 362 /** 363 * @param string $certFile 364 * @param LoggerInterface|null $logger 365 * @return bool 366 */ 367 private static function isFile($certFile, LoggerInterface $logger = null) 368 { 369 $isFile = @is_file($certFile); 370 if (!$isFile && $logger) { 371 $logger->debug(sprintf('Checked CA file %s does not exist or it is not a file.', $certFile)); 372 } 373 374 return $isFile; 375 } 376 377 /** 378 * @param string $certDir 379 * @param LoggerInterface|null $logger 380 * @return bool 381 */ 382 private static function isDir($certDir, LoggerInterface $logger = null) 383 { 384 $isDir = @is_dir($certDir); 385 if (!$isDir && $logger) { 386 $logger->debug(sprintf('Checked directory %s does not exist or it is not a directory.', $certDir)); 387 } 388 389 return $isDir; 390 } 391 392 /** 393 * @param string $certFileOrDir 394 * @param LoggerInterface|null $logger 395 * @return bool 396 */ 397 private static function isReadable($certFileOrDir, LoggerInterface $logger = null) 398 { 399 $isReadable = @is_readable($certFileOrDir); 400 if (!$isReadable && $logger) { 401 $logger->debug(sprintf('Checked file or directory %s is not readable.', $certFileOrDir)); 402 } 403 404 return $isReadable; 405 } 406 407 /** 408 * @param string $pattern 409 * @param LoggerInterface|null $logger 410 * @return bool 411 */ 412 private static function glob($pattern, LoggerInterface $logger = null) 413 { 414 $certs = glob($pattern); 415 if ($certs === false) { 416 if ($logger) { 417 $logger->debug(sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern)); 418 } 419 return false; 420 } 421 422 if (count($certs) === 0) { 423 if ($logger) { 424 $logger->debug(sprintf("No CA files found for pattern: %s", $pattern)); 425 } 426 return false; 427 } 428 429 return true; 430 } 279 $script = '<' . "?php\n" . sprintf( $script, $cert ); 280 281 try { 282 $process = new PhpProcess( $script ); 283 $process->mustRun(); 284 } catch ( \Exception $e ) { 285 // In the case of any exceptions just accept it is not possible to 286 // determine the safety of openssl_x509_parse and bail out. 287 return self::$useOpensslParse = false; 288 } 289 290 $output = preg_split( '{\r?\n}', trim( $process->getOutput() ) ); 291 $errorOutput = trim( $process->getErrorOutput() ); 292 293 if ( 294 is_array( $output ) 295 && count( $output ) === 3 296 && $output[0] === sprintf( 'string(%d) "%s"', strlen( PHP_VERSION ), PHP_VERSION ) 297 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"' 298 && $output[2] === 'int(-1)' 299 && preg_match( '{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput ) 300 ) { 301 // This PHP has the fix backported probably by a distro security team. 302 return self::$useOpensslParse = true; 303 } 304 305 return self::$useOpensslParse = false; 306 } 307 308 /** 309 * Resets the static caches 310 * 311 * @return void 312 */ 313 public static function reset() { 314 self::$caFileValidity = array(); 315 self::$caPath = null; 316 self::$useOpensslParse = null; 317 } 318 319 /** 320 * @param string $name 321 * @return string|false 322 */ 323 private static function getEnvVariable( $name ) { 324 if ( isset( $_SERVER[ $name ] ) ) { 325 return (string) $_SERVER[ $name ]; 326 } 327 328 if ( PHP_SAPI === 'cli' && ( $value = getenv( $name ) ) !== false && $value !== null ) { 329 return (string) $value; 330 } 331 332 return false; 333 } 334 335 /** 336 * @param string|false $certFile 337 * @param LoggerInterface|null $logger 338 * @return bool 339 */ 340 private static function caFileUsable( $certFile, LoggerInterface $logger = null ) { 341 return $certFile 342 && static::isFile( $certFile, $logger ) 343 && static::isReadable( $certFile, $logger ) 344 && static::validateCaFile( $certFile, $logger ); 345 } 346 347 /** 348 * @param string|false $certDir 349 * @param LoggerInterface|null $logger 350 * @return bool 351 */ 352 private static function caDirUsable( $certDir, LoggerInterface $logger = null ) { 353 return $certDir 354 && static::isDir( $certDir, $logger ) 355 && static::isReadable( $certDir, $logger ) 356 && static::glob( $certDir . '/*', $logger ); 357 } 358 359 /** 360 * @param string $certFile 361 * @param LoggerInterface|null $logger 362 * @return bool 363 */ 364 private static function isFile( $certFile, LoggerInterface $logger = null ) { 365 $isFile = @is_file( $certFile ); 366 if ( ! $isFile && $logger ) { 367 $logger->debug( sprintf( 'Checked CA file %s does not exist or it is not a file.', $certFile ) ); 368 } 369 370 return $isFile; 371 } 372 373 /** 374 * @param string $certDir 375 * @param LoggerInterface|null $logger 376 * @return bool 377 */ 378 private static function isDir( $certDir, LoggerInterface $logger = null ) { 379 $isDir = @is_dir( $certDir ); 380 if ( ! $isDir && $logger ) { 381 $logger->debug( sprintf( 'Checked directory %s does not exist or it is not a directory.', $certDir ) ); 382 } 383 384 return $isDir; 385 } 386 387 /** 388 * @param string $certFileOrDir 389 * @param LoggerInterface|null $logger 390 * @return bool 391 */ 392 private static function isReadable( $certFileOrDir, LoggerInterface $logger = null ) { 393 $isReadable = @is_readable( $certFileOrDir ); 394 if ( ! $isReadable && $logger ) { 395 $logger->debug( sprintf( 'Checked file or directory %s is not readable.', $certFileOrDir ) ); 396 } 397 398 return $isReadable; 399 } 400 401 /** 402 * @param string $pattern 403 * @param LoggerInterface|null $logger 404 * @return bool 405 */ 406 private static function glob( $pattern, LoggerInterface $logger = null ) { 407 $certs = glob( $pattern ); 408 if ( $certs === false ) { 409 if ( $logger ) { 410 $logger->debug( sprintf( 'An error occurred while trying to find certificates for pattern: %s', $pattern ) ); 411 } 412 return false; 413 } 414 415 if ( count( $certs ) === 0 ) { 416 if ( $logger ) { 417 $logger->debug( sprintf( 'No CA files found for pattern: %s', $pattern ) ); 418 } 419 return false; 420 } 421 422 return true; 423 } 431 424 } -
termageddon-usercentrics/trunk/vendor/composer/installed.php
r2976730 r3160131 1 1 <?php return array( 2 'root'=> array(3 'name'=> 'termageddon/termageddon-usercentrics',4 'pretty_version' => 'dev-main',5 'version'=> 'dev-main',6 'reference'=> '88511e7dd7de711d12c6d12147b0bb96908a84c5',7 'type'=> 'library',8 'install_path'=> __DIR__ . '/../../',9 'aliases'=> array(),10 'dev'=> true,11 ),12 'versions' => array(13 'composer/ca-bundle'=> array(14 'pretty_version'=> '1.3.7',15 'version'=> '1.3.7.0',16 'reference'=> '76e46335014860eec1aa5a724799a00a2e47cc85',17 'type'=> 'library',18 'install_path'=> __DIR__ . '/./ca-bundle',19 'aliases'=> array(),20 'dev_requirement' => false,21 ),22 'geoip2/geoip2'=> array(23 'pretty_version'=> 'v2.10.0',24 'version'=> '2.10.0.0',25 'reference'=> '419557cd21d9fe039721a83490701a58c8ce784a',26 'type'=> 'library',27 'install_path'=> __DIR__ . '/../geoip2/geoip2',28 'aliases'=> array(),29 'dev_requirement' => false,30 ),31 'maxmind-db/reader'=> array(32 'pretty_version'=> 'v1.11.0',33 'version'=> '1.11.0.0',34 'reference'=> 'b1f3c0699525336d09cc5161a2861268d9f2ae5b',35 'type'=> 'library',36 'install_path'=> __DIR__ . '/../maxmind-db/reader',37 'aliases'=> array(),38 'dev_requirement' => false,39 ),40 'maxmind/web-service-common'=> array(41 'pretty_version'=> 'v0.9.0',42 'version'=> '0.9.0.0',43 'reference'=> '4dc5a3e8df38aea4ca3b1096cee3a038094e9b53',44 'type'=> 'library',45 'install_path'=> __DIR__ . '/../maxmind/web-service-common',46 'aliases'=> array(),47 'dev_requirement' => false,48 ),49 'termageddon/termageddon-usercentrics' => array(50 'pretty_version'=> 'dev-main',51 'version'=> 'dev-main',52 'reference'=> '88511e7dd7de711d12c6d12147b0bb96908a84c5',53 'type'=> 'library',54 'install_path'=> __DIR__ . '/../../',55 'aliases'=> array(),56 'dev_requirement' => false,57 ),58 ),2 'root' => array( 3 'name' => 'termageddon/termageddon-usercentrics', 4 'pretty_version' => 'dev-main', 5 'version' => 'dev-main', 6 'reference' => '88511e7dd7de711d12c6d12147b0bb96908a84c5', 7 'type' => 'library', 8 'install_path' => __DIR__ . '/../../', 9 'aliases' => array(), 10 'dev' => true, 11 ), 12 'versions' => array( 13 'composer/ca-bundle' => array( 14 'pretty_version' => '1.3.7', 15 'version' => '1.3.7.0', 16 'reference' => '76e46335014860eec1aa5a724799a00a2e47cc85', 17 'type' => 'library', 18 'install_path' => __DIR__ . '/./ca-bundle', 19 'aliases' => array(), 20 'dev_requirement' => false, 21 ), 22 'geoip2/geoip2' => array( 23 'pretty_version' => 'v2.10.0', 24 'version' => '2.10.0.0', 25 'reference' => '419557cd21d9fe039721a83490701a58c8ce784a', 26 'type' => 'library', 27 'install_path' => __DIR__ . '/../geoip2/geoip2', 28 'aliases' => array(), 29 'dev_requirement' => false, 30 ), 31 'maxmind-db/reader' => array( 32 'pretty_version' => 'v1.11.0', 33 'version' => '1.11.0.0', 34 'reference' => 'b1f3c0699525336d09cc5161a2861268d9f2ae5b', 35 'type' => 'library', 36 'install_path' => __DIR__ . '/../maxmind-db/reader', 37 'aliases' => array(), 38 'dev_requirement' => false, 39 ), 40 'maxmind/web-service-common' => array( 41 'pretty_version' => 'v0.9.0', 42 'version' => '0.9.0.0', 43 'reference' => '4dc5a3e8df38aea4ca3b1096cee3a038094e9b53', 44 'type' => 'library', 45 'install_path' => __DIR__ . '/../maxmind/web-service-common', 46 'aliases' => array(), 47 'dev_requirement' => false, 48 ), 49 'termageddon/termageddon-usercentrics' => array( 50 'pretty_version' => 'dev-main', 51 'version' => 'dev-main', 52 'reference' => '88511e7dd7de711d12c6d12147b0bb96908a84c5', 53 'type' => 'library', 54 'install_path' => __DIR__ . '/../../', 55 'aliases' => array(), 56 'dev_requirement' => false, 57 ), 58 ), 59 59 ); -
termageddon-usercentrics/trunk/vendor/composer/platform_check.php
r2771752 r3160131 5 5 $issues = array(); 6 6 7 if ( !(PHP_VERSION_ID >= 70200)) {8 $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';7 if ( ! ( PHP_VERSION_ID >= 70200 ) ) { 8 $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.'; 9 9 } 10 10 11 if ( $issues) {12 if (!headers_sent()) {13 header('HTTP/1.1 500 Internal Server Error');14 }15 if (!ini_get('display_errors')) {16 if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {17 fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);18 } elseif (!headers_sent()) {19 echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;20 }21 }22 trigger_error(23 'Composer detected issues in your platform: ' . implode(' ', $issues),24 E_USER_ERROR25 );11 if ( $issues ) { 12 if ( ! headers_sent() ) { 13 header( 'HTTP/1.1 500 Internal Server Error' ); 14 } 15 if ( ! ini_get( 'display_errors' ) ) { 16 if ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ) { 17 fwrite( STDERR, 'Composer detected issues in your platform:' . PHP_EOL . PHP_EOL . implode( PHP_EOL, $issues ) . PHP_EOL . PHP_EOL ); 18 } elseif ( ! headers_sent() ) { 19 echo 'Composer detected issues in your platform:' . PHP_EOL . PHP_EOL . str_replace( 'You are running ' . PHP_VERSION . '.', '', implode( PHP_EOL, $issues ) ) . PHP_EOL . PHP_EOL; 20 } 21 } 22 trigger_error( 23 'Composer detected issues in your platform: ' . implode( ' ', $issues ), 24 E_USER_ERROR 25 ); 26 26 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/examples/benchmark.php
r2976730 r3160131 5 5 use GeoIp2\Database\Reader; 6 6 7 srand( 0);7 srand( 0 ); 8 8 9 $reader = new Reader('GeoIP2-City.mmdb');10 $count = 500000;11 $startTime = microtime( true);12 for ( $i = 0; $i < $count; ++$i) {13 $ip = long2ip(rand(0, pow(2, 32) - 1));14 try {15 $t = $reader->city($ip);16 } catch (\GeoIp2\Exception\AddressNotFoundException $e) {17 }18 if ($i % 10000 === 0) {19 echo $i . ' ' . $ip . "\n";20 }9 $reader = new Reader( 'GeoIP2-City.mmdb' ); 10 $count = 500000; 11 $startTime = microtime( true ); 12 for ( $i = 0; $i < $count; ++$i ) { 13 $ip = long2ip( rand( 0, pow( 2, 32 ) - 1 ) ); 14 try { 15 $t = $reader->city( $ip ); 16 } catch ( \GeoIp2\Exception\AddressNotFoundException $e ) { 17 } 18 if ( $i % 10000 === 0 ) { 19 echo $i . ' ' . $ip . "\n"; 20 } 21 21 } 22 $endTime = microtime( true);22 $endTime = microtime( true ); 23 23 24 24 $duration = $endTime - $startTime; -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Database/Reader.php
r2976730 r3160131 32 32 * will be thrown. 33 33 */ 34 class Reader implements ProviderInterface 35 { 36 private $dbReader; 37 private $dbType; 38 private $locales; 39 40 /** 41 * Constructor. 42 * 43 * @param string $filename the path to the GeoIP2 database file 44 * @param array $locales list of locale codes to use in name property 45 * from most preferred to least preferred 46 * 47 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 48 * is corrupt or invalid 49 */ 50 public function __construct( 51 $filename, 52 $locales = ['en'] 53 ) { 54 $this->dbReader = new DbReader($filename); 55 $this->dbType = $this->dbReader->metadata()->databaseType; 56 $this->locales = $locales; 57 } 58 59 /** 60 * This method returns a GeoIP2 City model. 61 * 62 * @param string $ipAddress an IPv4 or IPv6 address as a string 63 * 64 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 65 * not in the database 66 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 67 * is corrupt or invalid 68 * 69 * @return \GeoIp2\Model\City 70 */ 71 public function city($ipAddress) 72 { 73 return $this->modelFor('City', 'City', $ipAddress); 74 } 75 76 /** 77 * This method returns a GeoIP2 Country model. 78 * 79 * @param string $ipAddress an IPv4 or IPv6 address as a string 80 * 81 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 82 * not in the database 83 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 84 * is corrupt or invalid 85 * 86 * @return \GeoIp2\Model\Country 87 */ 88 public function country($ipAddress) 89 { 90 return $this->modelFor('Country', 'Country', $ipAddress); 91 } 92 93 /** 94 * This method returns a GeoIP2 Anonymous IP model. 95 * 96 * @param string $ipAddress an IPv4 or IPv6 address as a string 97 * 98 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 99 * not in the database 100 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 101 * is corrupt or invalid 102 * 103 * @return \GeoIp2\Model\AnonymousIp 104 */ 105 public function anonymousIp($ipAddress) 106 { 107 return $this->flatModelFor( 108 'AnonymousIp', 109 'GeoIP2-Anonymous-IP', 110 $ipAddress 111 ); 112 } 113 114 /** 115 * This method returns a GeoLite2 ASN model. 116 * 117 * @param string $ipAddress an IPv4 or IPv6 address as a string 118 * 119 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 120 * not in the database 121 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 122 * is corrupt or invalid 123 * 124 * @return \GeoIp2\Model\Asn 125 */ 126 public function asn($ipAddress) 127 { 128 return $this->flatModelFor( 129 'Asn', 130 'GeoLite2-ASN', 131 $ipAddress 132 ); 133 } 134 135 /** 136 * This method returns a GeoIP2 Connection Type model. 137 * 138 * @param string $ipAddress an IPv4 or IPv6 address as a string 139 * 140 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 141 * not in the database 142 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 143 * is corrupt or invalid 144 * 145 * @return \GeoIp2\Model\ConnectionType 146 */ 147 public function connectionType($ipAddress) 148 { 149 return $this->flatModelFor( 150 'ConnectionType', 151 'GeoIP2-Connection-Type', 152 $ipAddress 153 ); 154 } 155 156 /** 157 * This method returns a GeoIP2 Domain model. 158 * 159 * @param string $ipAddress an IPv4 or IPv6 address as a string 160 * 161 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 162 * not in the database 163 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 164 * is corrupt or invalid 165 * 166 * @return \GeoIp2\Model\Domain 167 */ 168 public function domain($ipAddress) 169 { 170 return $this->flatModelFor( 171 'Domain', 172 'GeoIP2-Domain', 173 $ipAddress 174 ); 175 } 176 177 /** 178 * This method returns a GeoIP2 Enterprise model. 179 * 180 * @param string $ipAddress an IPv4 or IPv6 address as a string 181 * 182 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 183 * not in the database 184 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 185 * is corrupt or invalid 186 * 187 * @return \GeoIp2\Model\Enterprise 188 */ 189 public function enterprise($ipAddress) 190 { 191 return $this->modelFor('Enterprise', 'Enterprise', $ipAddress); 192 } 193 194 /** 195 * This method returns a GeoIP2 ISP model. 196 * 197 * @param string $ipAddress an IPv4 or IPv6 address as a string 198 * 199 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 200 * not in the database 201 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 202 * is corrupt or invalid 203 * 204 * @return \GeoIp2\Model\Isp 205 */ 206 public function isp($ipAddress) 207 { 208 return $this->flatModelFor( 209 'Isp', 210 'GeoIP2-ISP', 211 $ipAddress 212 ); 213 } 214 215 private function modelFor($class, $type, $ipAddress) 216 { 217 list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress); 218 219 $record['traits']['ip_address'] = $ipAddress; 220 $record['traits']['prefix_len'] = $prefixLen; 221 222 $class = 'GeoIp2\\Model\\' . $class; 223 224 return new $class($record, $this->locales); 225 } 226 227 private function flatModelFor($class, $type, $ipAddress) 228 { 229 list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress); 230 231 $record['ip_address'] = $ipAddress; 232 $record['prefix_len'] = $prefixLen; 233 $class = 'GeoIp2\\Model\\' . $class; 234 235 return new $class($record); 236 } 237 238 private function getRecord($class, $type, $ipAddress) 239 { 240 if (strpos($this->dbType, $type) === false) { 241 $method = lcfirst($class); 242 throw new \BadMethodCallException( 243 "The $method method cannot be used to open a {$this->dbType} database" 244 ); 245 } 246 list($record, $prefixLen) = $this->dbReader->getWithPrefixLen($ipAddress); 247 if ($record === null) { 248 throw new AddressNotFoundException( 249 "The address $ipAddress is not in the database." 250 ); 251 } 252 if (!\is_array($record)) { 253 // This can happen on corrupt databases. Generally, 254 // MaxMind\Db\Reader will throw a 255 // MaxMind\Db\Reader\InvalidDatabaseException, but occasionally 256 // the lookup may result in a record that looks valid but is not 257 // an array. This mostly happens when the user is ignoring all 258 // exceptions and the more frequent InvalidDatabaseException 259 // exceptions go unnoticed. 260 throw new InvalidDatabaseException( 261 "Expected an array when looking up $ipAddress but received: " 262 . \gettype($record) 263 ); 264 } 265 266 return [$record, $prefixLen]; 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 \MaxMind\Db\Reader\Metadata object for the database 274 */ 275 public function metadata() 276 { 277 return $this->dbReader->metadata(); 278 } 279 280 /** 281 * Closes the GeoIP2 database and returns the resources to the system. 282 */ 283 public function close() 284 { 285 $this->dbReader->close(); 286 } 34 class Reader implements ProviderInterface { 35 36 private $dbReader; 37 private $dbType; 38 private $locales; 39 40 /** 41 * Constructor. 42 * 43 * @param string $filename the path to the GeoIP2 database file 44 * @param array $locales list of locale codes to use in name property 45 * from most preferred to least preferred 46 * 47 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 48 * is corrupt or invalid 49 */ 50 public function __construct( 51 $filename, 52 $locales = array( 'en' ) 53 ) { 54 $this->dbReader = new DbReader( $filename ); 55 $this->dbType = $this->dbReader->metadata()->databaseType; 56 $this->locales = $locales; 57 } 58 59 /** 60 * This method returns a GeoIP2 City model. 61 * 62 * @param string $ipAddress an IPv4 or IPv6 address as a string 63 * 64 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 65 * not in the database 66 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 67 * is corrupt or invalid 68 * 69 * @return \GeoIp2\Model\City 70 */ 71 public function city( $ipAddress ) { 72 return $this->modelFor( 'City', 'City', $ipAddress ); 73 } 74 75 /** 76 * This method returns a GeoIP2 Country model. 77 * 78 * @param string $ipAddress an IPv4 or IPv6 address as a string 79 * 80 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 81 * not in the database 82 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 83 * is corrupt or invalid 84 * 85 * @return \GeoIp2\Model\Country 86 */ 87 public function country( $ipAddress ) { 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 return $this->flatModelFor( 105 'AnonymousIp', 106 'GeoIP2-Anonymous-IP', 107 $ipAddress 108 ); 109 } 110 111 /** 112 * This method returns a GeoLite2 ASN model. 113 * 114 * @param string $ipAddress an IPv4 or IPv6 address as a string 115 * 116 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 117 * not in the database 118 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 119 * is corrupt or invalid 120 * 121 * @return \GeoIp2\Model\Asn 122 */ 123 public function asn( $ipAddress ) { 124 return $this->flatModelFor( 125 'Asn', 126 'GeoLite2-ASN', 127 $ipAddress 128 ); 129 } 130 131 /** 132 * This method returns a GeoIP2 Connection Type model. 133 * 134 * @param string $ipAddress an IPv4 or IPv6 address as a string 135 * 136 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 137 * not in the database 138 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 139 * is corrupt or invalid 140 * 141 * @return \GeoIp2\Model\ConnectionType 142 */ 143 public function connectionType( $ipAddress ) { 144 return $this->flatModelFor( 145 'ConnectionType', 146 'GeoIP2-Connection-Type', 147 $ipAddress 148 ); 149 } 150 151 /** 152 * This method returns a GeoIP2 Domain model. 153 * 154 * @param string $ipAddress an IPv4 or IPv6 address as a string 155 * 156 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 157 * not in the database 158 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 159 * is corrupt or invalid 160 * 161 * @return \GeoIp2\Model\Domain 162 */ 163 public function domain( $ipAddress ) { 164 return $this->flatModelFor( 165 'Domain', 166 'GeoIP2-Domain', 167 $ipAddress 168 ); 169 } 170 171 /** 172 * This method returns a GeoIP2 Enterprise model. 173 * 174 * @param string $ipAddress an IPv4 or IPv6 address as a string 175 * 176 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 177 * not in the database 178 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 179 * is corrupt or invalid 180 * 181 * @return \GeoIp2\Model\Enterprise 182 */ 183 public function enterprise( $ipAddress ) { 184 return $this->modelFor( 'Enterprise', 'Enterprise', $ipAddress ); 185 } 186 187 /** 188 * This method returns a GeoIP2 ISP model. 189 * 190 * @param string $ipAddress an IPv4 or IPv6 address as a string 191 * 192 * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 193 * not in the database 194 * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 195 * is corrupt or invalid 196 * 197 * @return \GeoIp2\Model\Isp 198 */ 199 public function isp( $ipAddress ) { 200 return $this->flatModelFor( 201 'Isp', 202 'GeoIP2-ISP', 203 $ipAddress 204 ); 205 } 206 207 private function modelFor( $class, $type, $ipAddress ) { 208 list($record, $prefixLen) = $this->getRecord( $class, $type, $ipAddress ); 209 210 $record['traits']['ip_address'] = $ipAddress; 211 $record['traits']['prefix_len'] = $prefixLen; 212 213 $class = 'GeoIp2\\Model\\' . $class; 214 215 return new $class( $record, $this->locales ); 216 } 217 218 private function flatModelFor( $class, $type, $ipAddress ) { 219 list($record, $prefixLen) = $this->getRecord( $class, $type, $ipAddress ); 220 221 $record['ip_address'] = $ipAddress; 222 $record['prefix_len'] = $prefixLen; 223 $class = 'GeoIp2\\Model\\' . $class; 224 225 return new $class( $record ); 226 } 227 228 private function getRecord( $class, $type, $ipAddress ) { 229 if ( strpos( $this->dbType, $type ) === false ) { 230 $method = lcfirst( $class ); 231 throw new \BadMethodCallException( 232 "The $method method cannot be used to open a {$this->dbType} database" 233 ); 234 } 235 list($record, $prefixLen) = $this->dbReader->getWithPrefixLen( $ipAddress ); 236 if ( $record === null ) { 237 throw new AddressNotFoundException( 238 "The address $ipAddress is not in the database." 239 ); 240 } 241 if ( ! \is_array( $record ) ) { 242 // This can happen on corrupt databases. Generally, 243 // MaxMind\Db\Reader will throw a 244 // MaxMind\Db\Reader\InvalidDatabaseException, but occasionally 245 // the lookup may result in a record that looks valid but is not 246 // an array. This mostly happens when the user is ignoring all 247 // exceptions and the more frequent InvalidDatabaseException 248 // exceptions go unnoticed. 249 throw new InvalidDatabaseException( 250 "Expected an array when looking up $ipAddress but received: " 251 . \gettype( $record ) 252 ); 253 } 254 255 return array( $record, $prefixLen ); 256 } 257 258 /** 259 * @throws \InvalidArgumentException if arguments are passed to the method 260 * @throws \BadMethodCallException if the database has been closed 261 * 262 * @return \MaxMind\Db\Reader\Metadata object for the database 263 */ 264 public function metadata() { 265 return $this->dbReader->metadata(); 266 } 267 268 /** 269 * Closes the GeoIP2 database and returns the resources to the system. 270 */ 271 public function close() { 272 $this->dbReader->close(); 273 } 287 274 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php
r2976730 r3160131 6 6 * This class represents a generic error. 7 7 */ 8 class AddressNotFoundException extends GeoIp2Exception 9 { 8 class AddressNotFoundException extends GeoIp2Exception { 9 10 10 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php
r2976730 r3160131 6 6 * This class represents a generic error. 7 7 */ 8 class AuthenticationException extends GeoIp2Exception 9 { 8 class AuthenticationException extends GeoIp2Exception { 9 10 10 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php
r2976730 r3160131 6 6 * This class represents a generic error. 7 7 */ 8 class GeoIp2Exception extends \Exception 9 { 8 class GeoIp2Exception extends \Exception { 9 10 10 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/HttpException.php
r2976730 r3160131 6 6 * This class represents an HTTP transport error. 7 7 */ 8 class HttpException extends GeoIp2Exception 9 { 10 /** 11 * The URI queried. 12 */ 13 public $uri; 8 class HttpException extends GeoIp2Exception { 14 9 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 } 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 24 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php
r2976730 r3160131 7 7 * web service. 8 8 */ 9 class InvalidRequestException extends HttpException 10 { 11 /** 12 * The code returned by the MaxMind web service. 13 */ 14 public $error; 9 class InvalidRequestException extends HttpException { 15 10 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 } 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 26 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php
r2976730 r3160131 6 6 * This class represents a generic error. 7 7 */ 8 class OutOfQueriesException extends GeoIp2Exception 9 { 8 class OutOfQueriesException extends GeoIp2Exception { 9 10 10 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/AbstractModel.php
r2976730 r3160131 6 6 * @ignore 7 7 */ 8 abstract class AbstractModel implements \JsonSerializable 9 { 10 protected $raw; 8 abstract class AbstractModel implements \JsonSerializable { 11 9 12 /** 13 * @ignore 14 * 15 * @param mixed $raw 16 */ 17 public function __construct($raw) 18 { 19 $this->raw = $raw; 20 } 10 protected $raw; 21 11 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 } 12 /** 13 * @ignore 14 * 15 * @param mixed $raw 16 */ 17 public function __construct( $raw ) { 18 $this->raw = $raw; 19 } 35 20 36 return null; 37 } 21 /** 22 * @ignore 23 * 24 * @param mixed $field 25 */ 26 protected function get( $field ) { 27 if ( isset( $this->raw[ $field ] ) ) { 28 return $this->raw[ $field ]; 29 } 30 if ( preg_match( '/^is_/', $field ) ) { 31 return false; 32 } 38 33 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 } 34 return null; 35 } 49 36 50 throw new \RuntimeException("Unknown attribute: $attr"); 51 } 37 /** 38 * @ignore 39 * 40 * @param mixed $attr 41 */ 42 public function __get( $attr ) { 43 if ( $attr !== 'instance' && property_exists( $this, $attr ) ) { 44 return $this->$attr; 45 } 52 46 53 /** 54 * @ignore 55 * 56 * @param mixed $attr 57 */ 58 public function __isset($attr) 59 { 60 return $attr !== 'instance' && isset($this->$attr); 61 } 47 throw new \RuntimeException( "Unknown attribute: $attr" ); 48 } 62 49 63 public function jsonSerialize() 64 { 65 return $this->raw; 66 } 50 /** 51 * @ignore 52 * 53 * @param mixed $attr 54 */ 55 public function __isset( $attr ) { 56 return $attr !== 'instance' && isset( $this->$attr ); 57 } 58 59 public function jsonSerialize() { 60 return $this->raw; 61 } 67 62 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/AnonymousIp.php
r2976730 r3160131 26 26 * fields besides $ipAddress have the same value. 27 27 */ 28 class AnonymousIp extends AbstractModel 29 { 30 protected $isAnonymous; 31 protected $isAnonymousVpn; 32 protected $isHostingProvider; 33 protected $isPublicProxy; 34 protected $isTorExitNode; 35 protected $ipAddress; 36 protected $network; 28 class AnonymousIp extends AbstractModel { 37 29 38 /** 39 * @ignore 40 * 41 * @param mixed $raw 42 */ 43 public function __construct($raw) 44 { 45 parent::__construct($raw); 30 protected $isAnonymous; 31 protected $isAnonymousVpn; 32 protected $isHostingProvider; 33 protected $isPublicProxy; 34 protected $isTorExitNode; 35 protected $ipAddress; 36 protected $network; 46 37 47 $this->isAnonymous = $this->get('is_anonymous'); 48 $this->isAnonymousVpn = $this->get('is_anonymous_vpn'); 49 $this->isHostingProvider = $this->get('is_hosting_provider'); 50 $this->isPublicProxy = $this->get('is_public_proxy'); 51 $this->isTorExitNode = $this->get('is_tor_exit_node'); 52 $ipAddress = $this->get('ip_address'); 53 $this->ipAddress = $ipAddress; 54 $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); 55 } 38 /** 39 * @ignore 40 * 41 * @param mixed $raw 42 */ 43 public function __construct( $raw ) { 44 parent::__construct( $raw ); 45 46 $this->isAnonymous = $this->get( 'is_anonymous' ); 47 $this->isAnonymousVpn = $this->get( 'is_anonymous_vpn' ); 48 $this->isHostingProvider = $this->get( 'is_hosting_provider' ); 49 $this->isPublicProxy = $this->get( 'is_public_proxy' ); 50 $this->isTorExitNode = $this->get( 'is_tor_exit_node' ); 51 $ipAddress = $this->get( 'ip_address' ); 52 $this->ipAddress = $ipAddress; 53 $this->network = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) ); 54 } 56 55 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Asn.php
r2976730 r3160131 19 19 * fields besides $ipAddress have the same value. 20 20 */ 21 class Asn extends AbstractModel 22 { 23 protected $autonomousSystemNumber; 24 protected $autonomousSystemOrganization; 25 protected $ipAddress; 26 protected $network; 21 class Asn extends AbstractModel { 27 22 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 $ipAddress = $this->get('ip_address'); 40 $this->ipAddress = $ipAddress; 41 $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); 42 } 23 protected $autonomousSystemNumber; 24 protected $autonomousSystemOrganization; 25 protected $ipAddress; 26 protected $network; 27 28 /** 29 * @ignore 30 * 31 * @param mixed $raw 32 */ 33 public function __construct( $raw ) { 34 parent::__construct( $raw ); 35 $this->autonomousSystemNumber = $this->get( 'autonomous_system_number' ); 36 $this->autonomousSystemOrganization = 37 $this->get( 'autonomous_system_organization' ); 38 $ipAddress = $this->get( 'ip_address' ); 39 $this->ipAddress = $ipAddress; 40 $this->network = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) ); 41 } 43 42 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/City.php
r2976730 r3160131 28 28 * \GeoIp2\Record\Subdivision object. 29 29 */ 30 class City extends Country 31 { 32 /** 33 * @ignore 34 */ 35 protected $city; 36 /** 37 * @ignore 38 */ 39 protected $location; 40 /** 41 * @ignore 42 */ 43 protected $postal; 44 /** 45 * @ignore 46 */ 47 protected $subdivisions = []; 30 class City extends Country { 48 31 49 /** 50 * @ignore 51 * 52 * @param mixed $raw 53 * @param mixed $locales 54 */ 55 public function __construct($raw, $locales = ['en']) 56 { 57 parent::__construct($raw, $locales); 32 /** 33 * @ignore 34 */ 35 protected $city; 36 /** 37 * @ignore 38 */ 39 protected $location; 40 /** 41 * @ignore 42 */ 43 protected $postal; 44 /** 45 * @ignore 46 */ 47 protected $subdivisions = array(); 58 48 59 $this->city = new \GeoIp2\Record\City($this->get('city'), $locales); 60 $this->location = new \GeoIp2\Record\Location($this->get('location')); 61 $this->postal = new \GeoIp2\Record\Postal($this->get('postal')); 49 /** 50 * @ignore 51 * 52 * @param mixed $raw 53 * @param mixed $locales 54 */ 55 public function __construct( $raw, $locales = array( 'en' ) ) { 56 parent::__construct( $raw, $locales ); 62 57 63 $this->createSubdivisions($raw, $locales); 64 } 58 $this->city = new \GeoIp2\Record\City( $this->get( 'city' ), $locales ); 59 $this->location = new \GeoIp2\Record\Location( $this->get( 'location' ) ); 60 $this->postal = new \GeoIp2\Record\Postal( $this->get( 'postal' ) ); 65 61 66 private function createSubdivisions($raw, $locales) 67 { 68 if (!isset($raw['subdivisions'])) { 69 return; 70 } 62 $this->createSubdivisions( $raw, $locales ); 63 } 71 64 72 foreach ($raw['subdivisions'] as $sub) { 73 array_push( 74 $this->subdivisions, 75 new \GeoIp2\Record\Subdivision($sub, $locales) 76 ); 77 } 78 } 65 private function createSubdivisions( $raw, $locales ) { 66 if ( ! isset( $raw['subdivisions'] ) ) { 67 return; 68 } 79 69 80 /** 81 * @ignore 82 * 83 * @param mixed $attr 84 */ 85 public function __get($attr) 86 { 87 if ($attr === 'mostSpecificSubdivision') { 88 return $this->$attr(); 89 } 70 foreach ( $raw['subdivisions'] as $sub ) { 71 array_push( 72 $this->subdivisions, 73 new \GeoIp2\Record\Subdivision( $sub, $locales ) 74 ); 75 } 76 } 90 77 91 return parent::__get($attr); 92 } 78 /** 79 * @ignore 80 * 81 * @param mixed $attr 82 */ 83 public function __get( $attr ) { 84 if ( $attr === 'mostSpecificSubdivision' ) { 85 return $this->$attr(); 86 } 93 87 94 /** 95 * @ignore 96 * 97 * @param mixed $attr 98 */ 99 public function __isset($attr) 100 { 101 if ($attr === 'mostSpecificSubdivision') { 102 // We always return a mostSpecificSubdivision, even if it is the 103 // empty subdivision 104 return true; 105 } 88 return parent::__get( $attr ); 89 } 106 90 107 return parent::__isset($attr); 108 } 91 /** 92 * @ignore 93 * 94 * @param mixed $attr 95 */ 96 public function __isset( $attr ) { 97 if ( $attr === 'mostSpecificSubdivision' ) { 98 // We always return a mostSpecificSubdivision, even if it is the 99 // empty subdivision 100 return true; 101 } 109 102 110 private function mostSpecificSubdivision() 111 { 112 return empty($this->subdivisions) ? 113 new \GeoIp2\Record\Subdivision([], $this->locales) : 114 end($this->subdivisions); 115 } 103 return parent::__isset( $attr ); 104 } 105 106 private function mostSpecificSubdivision() { 107 return empty( $this->subdivisions ) ? 108 new \GeoIp2\Record\Subdivision( array(), $this->locales ) : 109 end( $this->subdivisions ); 110 } 116 111 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/ConnectionType.php
r2976730 r3160131 17 17 * fields besides $ipAddress have the same value. 18 18 */ 19 class ConnectionType extends AbstractModel 20 { 21 protected $connectionType; 22 protected $ipAddress; 23 protected $network; 19 class ConnectionType extends AbstractModel { 24 20 25 /** 26 * @ignore 27 * 28 * @param mixed $raw 29 */ 30 public function __construct($raw) 31 { 32 parent::__construct($raw); 21 protected $connectionType; 22 protected $ipAddress; 23 protected $network; 33 24 34 $this->connectionType = $this->get('connection_type'); 35 $ipAddress = $this->get('ip_address'); 36 $this->ipAddress = $ipAddress; 37 $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); 38 } 25 /** 26 * @ignore 27 * 28 * @param mixed $raw 29 */ 30 public function __construct( $raw ) { 31 parent::__construct( $raw ); 32 33 $this->connectionType = $this->get( 'connection_type' ); 34 $ipAddress = $this->get( 'ip_address' ); 35 $this->ipAddress = $ipAddress; 36 $this->network = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) ); 37 } 39 38 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Country.php
r2976730 r3160131 28 28 * requested IP address. 29 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; 30 class Country extends AbstractModel { 39 31 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); 32 protected $continent; 33 protected $country; 34 protected $locales; 35 protected $maxmind; 36 protected $registeredCountry; 37 protected $representedCountry; 38 protected $traits; 49 39 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')); 40 /** 41 * @ignore 42 * 43 * @param mixed $raw 44 * @param mixed $locales 45 */ 46 public function __construct( $raw, $locales = array( 'en' ) ) { 47 parent::__construct( $raw ); 68 48 69 $this->locales = $locales; 70 } 49 $this->continent = new \GeoIp2\Record\Continent( 50 $this->get( 'continent' ), 51 $locales 52 ); 53 $this->country = new \GeoIp2\Record\Country( 54 $this->get( 'country' ), 55 $locales 56 ); 57 $this->maxmind = new \GeoIp2\Record\MaxMind( $this->get( 'maxmind' ) ); 58 $this->registeredCountry = new \GeoIp2\Record\Country( 59 $this->get( 'registered_country' ), 60 $locales 61 ); 62 $this->representedCountry = new \GeoIp2\Record\RepresentedCountry( 63 $this->get( 'represented_country' ), 64 $locales 65 ); 66 $this->traits = new \GeoIp2\Record\Traits( $this->get( 'traits' ) ); 67 68 $this->locales = $locales; 69 } 71 70 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Domain.php
r2976730 r3160131 17 17 * fields besides $ipAddress have the same value. 18 18 */ 19 class Domain extends AbstractModel 20 { 21 protected $domain; 22 protected $ipAddress; 23 protected $network; 19 class Domain extends AbstractModel { 24 20 25 /** 26 * @ignore 27 * 28 * @param mixed $raw 29 */ 30 public function __construct($raw) 31 { 32 parent::__construct($raw); 21 protected $domain; 22 protected $ipAddress; 23 protected $network; 33 24 34 $this->domain = $this->get('domain'); 35 $ipAddress = $this->get('ip_address'); 36 $this->ipAddress = $ipAddress; 37 $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); 38 } 25 /** 26 * @ignore 27 * 28 * @param mixed $raw 29 */ 30 public function __construct( $raw ) { 31 parent::__construct( $raw ); 32 33 $this->domain = $this->get( 'domain' ); 34 $ipAddress = $this->get( 'ip_address' ); 35 $this->ipAddress = $ipAddress; 36 $this->network = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) ); 37 } 39 38 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Enterprise.php
r2976730 r3160131 10 10 * https://dev.maxmind.com/geoip/geoip2/web-services for more details. 11 11 */ 12 class Enterprise extends City 13 { 12 class Enterprise extends City { 13 14 14 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Insights.php
r2976730 r3160131 10 10 * https://dev.maxmind.com/geoip/geoip2/web-services for more details. 11 11 */ 12 class Insights extends City 13 { 12 class Insights extends City { 13 14 14 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Isp.php
r2976730 r3160131 23 23 * fields besides $ipAddress have the same value. 24 24 */ 25 class Isp extends AbstractModel 26 { 27 protected $autonomousSystemNumber; 28 protected $autonomousSystemOrganization; 29 protected $isp; 30 protected $organization; 31 protected $ipAddress; 32 protected $network; 25 class Isp extends AbstractModel { 33 26 34 /** 35 * @ignore 36 * 37 * @param mixed $raw 38 */ 39 public function __construct($raw) 40 { 41 parent::__construct($raw); 42 $this->autonomousSystemNumber = $this->get('autonomous_system_number'); 43 $this->autonomousSystemOrganization = 44 $this->get('autonomous_system_organization'); 45 $this->isp = $this->get('isp'); 46 $this->organization = $this->get('organization'); 27 protected $autonomousSystemNumber; 28 protected $autonomousSystemOrganization; 29 protected $isp; 30 protected $organization; 31 protected $ipAddress; 32 protected $network; 47 33 48 $ipAddress = $this->get('ip_address'); 49 $this->ipAddress = $ipAddress; 50 $this->network = Util::cidr($ipAddress, $this->get('prefix_len')); 51 } 34 /** 35 * @ignore 36 * 37 * @param mixed $raw 38 */ 39 public function __construct( $raw ) { 40 parent::__construct( $raw ); 41 $this->autonomousSystemNumber = $this->get( 'autonomous_system_number' ); 42 $this->autonomousSystemOrganization = 43 $this->get( 'autonomous_system_organization' ); 44 $this->isp = $this->get( 'isp' ); 45 $this->organization = $this->get( 'organization' ); 46 47 $ipAddress = $this->get( 'ip_address' ); 48 $this->ipAddress = $ipAddress; 49 $this->network = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) ); 50 } 52 51 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/ProviderInterface.php
r2976730 r3160131 3 3 namespace GeoIp2; 4 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); 5 interface ProviderInterface { 13 6 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); 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 20 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php
r2976730 r3160131 3 3 namespace GeoIp2\Record; 4 4 5 abstract class AbstractPlaceRecord extends AbstractRecord 6 { 7 private $locales; 5 abstract class AbstractPlaceRecord extends AbstractRecord { 8 6 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 } 7 private $locales; 20 8 21 /**22 * @ignore23 *24 * @param mixed $attr 25 */ 26 public function __get($attr) 27 {28 if ($attr === 'name') { 29 return $this->name();30 }9 /** 10 * @ignore 11 * 12 * @param mixed $record 13 * @param mixed $locales 14 */ 15 public function __construct( $record, $locales = array( 'en' ) ) { 16 $this->locales = $locales; 17 parent::__construct( $record ); 18 } 31 19 32 return parent::__get($attr); 33 } 20 /** 21 * @ignore 22 * 23 * @param mixed $attr 24 */ 25 public function __get( $attr ) { 26 if ( $attr === 'name' ) { 27 return $this->name(); 28 } 34 29 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 } 30 return parent::__get( $attr ); 31 } 45 32 46 return parent::__isset($attr); 47 } 33 /** 34 * @ignore 35 * 36 * @param mixed $attr 37 */ 38 public function __isset( $attr ) { 39 if ( $attr === 'name' ) { 40 return $this->firstSetNameLocale() === null ? false : true; 41 } 48 42 49 private function name() 50 { 51 $locale = $this->firstSetNameLocale(); 43 return parent::__isset( $attr ); 44 } 52 45 53 return $locale === null ? null : $this->names[$locale]; 54 } 46 private function name() { 47 $locale = $this->firstSetNameLocale(); 55 48 56 private function firstSetNameLocale() 57 { 58 foreach ($this->locales as $locale) { 59 if (isset($this->names[$locale])) { 60 return $locale; 61 } 62 } 49 return $locale === null ? null : $this->names[ $locale ]; 50 } 63 51 64 return null; 65 } 52 private function firstSetNameLocale() { 53 foreach ( $this->locales as $locale ) { 54 if ( isset( $this->names[ $locale ] ) ) { 55 return $locale; 56 } 57 } 58 59 return null; 60 } 66 61 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/AbstractRecord.php
r2976730 r3160131 3 3 namespace GeoIp2\Record; 4 4 5 abstract class AbstractRecord implements \JsonSerializable 6 { 7 private $record; 5 abstract class AbstractRecord implements \JsonSerializable { 8 6 9 /** 10 * @ignore 11 * 12 * @param mixed $record 13 */ 14 public function __construct($record) 15 { 16 $this->record = isset($record) ? $record : []; 17 } 7 private $record; 18 8 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); 9 /** 10 * @ignore 11 * 12 * @param mixed $record 13 */ 14 public function __construct( $record ) { 15 $this->record = isset( $record ) ? $record : array(); 16 } 28 17 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 } 18 /** 19 * @ignore 20 * 21 * @param mixed $attr 22 */ 23 public function __get( $attr ) { 24 // XXX - kind of ugly but greatly reduces boilerplate code 25 $key = $this->attributeToKey( $attr ); 35 26 36 return null; 37 } 38 throw new \RuntimeException("Unknown attribute: $attr"); 39 } 27 if ( $this->__isset( $attr ) ) { 28 return $this->record[ $key ]; 29 } elseif ( $this->validAttribute( $attr ) ) { 30 if ( preg_match( '/^is_/', $key ) ) { 31 return false; 32 } 40 33 41 public function __isset($attr) 42 { 43 return $this->validAttribute($attr) && 44 isset($this->record[$this->attributeToKey($attr)]); 45 } 34 return null; 35 } 36 throw new \RuntimeException( "Unknown attribute: $attr" ); 37 } 46 38 47 private function attributeToKey($attr) 48 { 49 return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));50 }39 public function __isset( $attr ) { 40 return $this->validAttribute( $attr ) && 41 isset( $this->record[ $this->attributeToKey( $attr ) ] ); 42 } 51 43 52 private function validAttribute($attr) 53 { 54 return \in_array($attr, $this->validAttributes, true); 55 } 44 private function attributeToKey( $attr ) { 45 return strtolower( preg_replace( '/([A-Z])/', '_\1', $attr ) ); 46 } 56 47 57 public function jsonSerialize() 58 { 59 return $this->record; 60 } 48 private function validAttribute( $attr ) { 49 return \in_array( $attr, $this->validAttributes, true ); 50 } 51 52 public function jsonSerialize() { 53 return $this->record; 54 } 61 55 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/City.php
r2976730 r3160131 21 21 * services and databases. 22 22 */ 23 class City extends AbstractPlaceRecord 24 { 25 /**26 * @ignore27 */28 protected $validAttributes = ['confidence', 'geonameId', 'names'];23 class City extends AbstractPlaceRecord { 24 25 /** 26 * @ignore 27 */ 28 protected $validAttributes = array( 'confidence', 'geonameId', 'names' ); 29 29 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Continent.php
r2976730 r3160131 20 20 * services and databases. 21 21 */ 22 class Continent extends AbstractPlaceRecord 23 { 24 /**25 * @ignore26 */27 protected $validAttributes = [ 28 'code',29 'geonameId',30 'names',31 ];22 class Continent extends AbstractPlaceRecord { 23 24 /** 25 * @ignore 26 */ 27 protected $validAttributes = array( 28 'code', 29 'geonameId', 30 'names', 31 ); 32 32 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Country.php
r2976730 r3160131 26 26 * services and databases. 27 27 */ 28 class Country extends AbstractPlaceRecord 29 { 30 /**31 * @ignore32 */33 protected $validAttributes = [ 34 'confidence',35 'geonameId',36 'isInEuropeanUnion',37 'isoCode',38 'names',39 ];28 class Country extends AbstractPlaceRecord { 29 30 /** 31 * @ignore 32 */ 33 protected $validAttributes = array( 34 'confidence', 35 'geonameId', 36 'isInEuropeanUnion', 37 'isoCode', 38 'names', 39 ); 40 40 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Location.php
r2976730 r3160131 34 34 * https://www.iana.org/time-zones. 35 35 */ 36 class Location extends AbstractRecord 37 { 38 /**39 * @ignore40 */41 protected $validAttributes = [ 42 'averageIncome',43 'accuracyRadius',44 'latitude',45 'longitude',46 'metroCode',47 'populationDensity',48 'postalCode',49 'postalConfidence',50 'timeZone',51 ];36 class Location extends AbstractRecord { 37 38 /** 39 * @ignore 40 */ 41 protected $validAttributes = array( 42 'averageIncome', 43 'accuracyRadius', 44 'latitude', 45 'longitude', 46 'metroCode', 47 'populationDensity', 48 'postalCode', 49 'postalConfidence', 50 'timeZone', 51 ); 52 52 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/MaxMind.php
r2976730 r3160131 11 11 * have for the service you are calling. 12 12 */ 13 class MaxMind extends AbstractRecord 14 { 15 /**16 * @ignore17 */18 protected $validAttributes = ['queriesRemaining'];13 class MaxMind extends AbstractRecord { 14 15 /** 16 * @ignore 17 */ 18 protected $validAttributes = array( 'queriesRemaining' ); 19 19 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Postal.php
r2976730 r3160131 18 18 * database. 19 19 */ 20 class Postal extends AbstractRecord 21 { 22 /**23 * @ignore24 */25 protected $validAttributes = ['code', 'confidence'];20 class Postal extends AbstractRecord { 21 22 /** 23 * @ignore 24 */ 25 protected $validAttributes = array( 'code', 'confidence' ); 26 26 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php
r2976730 r3160131 14 14 * but this could expand to include other types in the future. 15 15 */ 16 class RepresentedCountry extends Country 17 { 18 protected $validAttributes = [ 19 'confidence',20 'geonameId',21 'isInEuropeanUnion',22 'isoCode',23 'names',24 'type',25 ];16 class RepresentedCountry extends Country { 17 18 protected $validAttributes = array( 19 'confidence', 20 'geonameId', 21 'isInEuropeanUnion', 22 'isoCode', 23 'names', 24 'type', 25 ); 26 26 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Subdivision.php
r2976730 r3160131 27 27 * databases and services besides Country. 28 28 */ 29 class Subdivision extends AbstractPlaceRecord 30 { 31 /**32 * @ignore33 */34 protected $validAttributes = [ 35 'confidence',36 'geonameId',37 'isoCode',38 'names',39 ];29 class Subdivision extends AbstractPlaceRecord { 30 31 /** 32 * @ignore 33 */ 34 protected $validAttributes = array( 35 'confidence', 36 'geonameId', 37 'isoCode', 38 'names', 39 ); 40 40 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Traits.php
r2976730 r3160131 103 103 * </p> 104 104 */ 105 class Traits extends AbstractRecord 106 { 107 /** 108 * @ignore 109 */ 110 protected $validAttributes = [ 111 'autonomousSystemNumber', 112 'autonomousSystemOrganization', 113 'connectionType', 114 'domain', 115 'ipAddress', 116 'isAnonymous', 117 'isAnonymousProxy', 118 'isAnonymousVpn', 119 'isHostingProvider', 120 'isLegitimateProxy', 121 'isp', 122 'isPublicProxy', 123 'isSatelliteProvider', 124 'isTorExitNode', 125 'network', 126 'organization', 127 'staticIpScore', 128 'userCount', 129 'userType', 130 ]; 105 class Traits extends AbstractRecord { 131 106 132 public function __construct($record) 133 { 134 if (!isset($record['network']) && isset($record['ip_address']) && isset($record['prefix_len'])) { 135 $record['network'] = Util::cidr($record['ip_address'], $record['prefix_len']); 136 } 107 /** 108 * @ignore 109 */ 110 protected $validAttributes = array( 111 'autonomousSystemNumber', 112 'autonomousSystemOrganization', 113 'connectionType', 114 'domain', 115 'ipAddress', 116 'isAnonymous', 117 'isAnonymousProxy', 118 'isAnonymousVpn', 119 'isHostingProvider', 120 'isLegitimateProxy', 121 'isp', 122 'isPublicProxy', 123 'isSatelliteProvider', 124 'isTorExitNode', 125 'network', 126 'organization', 127 'staticIpScore', 128 'userCount', 129 'userType', 130 ); 137 131 138 parent::__construct($record); 139 } 132 public function __construct( $record ) { 133 if ( ! isset( $record['network'] ) && isset( $record['ip_address'] ) && isset( $record['prefix_len'] ) ) { 134 $record['network'] = Util::cidr( $record['ip_address'], $record['prefix_len'] ); 135 } 136 137 parent::__construct( $record ); 138 } 140 139 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Util.php
r2976730 r3160131 3 3 namespace GeoIp2; 4 4 5 class Util 6 { 7 /** 8 * This returns the network in CIDR notation for the given IP and prefix 9 * length. This is for internal use only. 10 * 11 * @internal 12 * @ignore 13 * 14 * @param mixed $ipAddress 15 * @param mixed $prefixLen 16 */ 17 public static function cidr($ipAddress, $prefixLen) 18 { 19 $ipBytes = inet_pton($ipAddress); 20 $networkBytes = str_repeat("\0", \strlen($ipBytes)); 5 class Util { 21 6 22 $curPrefix = $prefixLen; 23 for ($i = 0; $i < \strlen($ipBytes) && $curPrefix > 0; $i++) { 24 $b = $ipBytes[$i]; 25 if ($curPrefix < 8) { 26 $shiftN = 8 - $curPrefix; 27 $b = \chr(0xFF & (\ord($b) >> $shiftN) << $shiftN); 28 } 29 $networkBytes[$i] = $b; 30 $curPrefix -= 8; 31 } 7 /** 8 * This returns the network in CIDR notation for the given IP and prefix 9 * length. This is for internal use only. 10 * 11 * @internal 12 * @ignore 13 * 14 * @param mixed $ipAddress 15 * @param mixed $prefixLen 16 */ 17 public static function cidr( $ipAddress, $prefixLen ) { 18 $ipBytes = inet_pton( $ipAddress ); 19 $networkBytes = str_repeat( "\0", \strlen( $ipBytes ) ); 32 20 33 $network = inet_ntop($networkBytes); 21 $curPrefix = $prefixLen; 22 for ( $i = 0; $i < \strlen( $ipBytes ) && $curPrefix > 0; $i++ ) { 23 $b = $ipBytes[ $i ]; 24 if ( $curPrefix < 8 ) { 25 $shiftN = 8 - $curPrefix; 26 $b = \chr( 0xFF & ( \ord( $b ) >> $shiftN ) << $shiftN ); 27 } 28 $networkBytes[ $i ] = $b; 29 $curPrefix -= 8; 30 } 34 31 35 return "$network/$prefixLen"; 36 } 32 $network = inet_ntop( $networkBytes ); 33 34 return "$network/$prefixLen"; 35 } 37 36 } -
termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/WebService/Client.php
r2976730 r3160131 42 42 * If the request fails, the client class throws an exception. 43 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.10.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 } 44 class Client implements ProviderInterface { 45 46 private $locales; 47 private $client; 48 private static $basePath = '/geoip/v2.1'; 49 50 const VERSION = 'v2.10.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 = array( 'en' ), 71 $options = array() 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 = array( '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 return 'GeoIP2-API/' . self::VERSION; 92 } 93 94 /** 95 * This method calls the GeoIP2 Precision: City service. 96 * 97 * @param string $ipAddress IPv4 or IPv6 address as a string. If no 98 * address is provided, the address that the web service is called 99 * from will be used. 100 * 101 * @throws \GeoIp2\Exception\AddressNotFoundException if the address you 102 * provided is not in our database (e.g., a private address). 103 * @throws \GeoIp2\Exception\AuthenticationException if there is a problem 104 * with the account ID or license key that you provided 105 * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out 106 * of queries 107 * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is 108 * invalid for some other reason. This may indicate an issue 109 * with this API. Please report the error to MaxMind. 110 * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned. 111 * This could indicate a problem with the connection between 112 * your server and the web service or that the web service 113 * returned an invalid document or 500 error code 114 * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent 115 * class to the above exceptions. It will be thrown directly 116 * if a 200 status code is returned but the body is invalid. 117 * 118 * @return \GeoIp2\Model\City 119 */ 120 public function city( $ipAddress = 'me' ) { 121 return $this->responseFor( 'city', 'City', $ipAddress ); 122 } 123 124 /** 125 * This method calls the GeoIP2 Precision: Country service. 126 * 127 * @param string $ipAddress IPv4 or IPv6 address as a string. If no 128 * address is provided, the address that the web service is called 129 * from will be used. 130 * 131 * @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g., 132 * a private address). 133 * @throws \GeoIp2\Exception\AuthenticationException if there is a problem 134 * with the account ID or license key that you provided 135 * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out of queries 136 * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is 137 * invalid for some other reason. This may indicate an 138 * issue with this API. Please report the error to MaxMind. 139 * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error 140 * code or message was returned. This could indicate a problem 141 * with the connection between your server and the web service 142 * or that the web service returned an invalid document or 500 143 * error code. 144 * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent class to the above exceptions. It 145 * will be thrown directly if a 200 status code is returned but 146 * the body is invalid. 147 * 148 * @return \GeoIp2\Model\Country 149 */ 150 public function country( $ipAddress = 'me' ) { 151 return $this->responseFor( 'country', 'Country', $ipAddress ); 152 } 153 154 /** 155 * This method calls the GeoIP2 Precision: Insights service. 156 * 157 * @param string $ipAddress IPv4 or IPv6 address as a string. If no 158 * address is provided, the address that the web service is called 159 * from will be used. 160 * 161 * @throws \GeoIp2\Exception\AddressNotFoundException if the address you 162 * provided is not in our database (e.g., a private address). 163 * @throws \GeoIp2\Exception\AuthenticationException if there is a problem 164 * with the account ID or license key that you provided 165 * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out 166 * of queries 167 * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is 168 * invalid for some other reason. This may indicate an 169 * issue with this API. Please report the error to MaxMind. 170 * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned. 171 * This could indicate a problem with the connection between 172 * your server and the web service or that the web service 173 * returned an invalid document or 500 error code 174 * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent 175 * class to the above exceptions. It will be thrown directly 176 * if a 200 status code is returned but the body is invalid. 177 * 178 * @return \GeoIp2\Model\Insights 179 */ 180 public function insights( $ipAddress = 'me' ) { 181 return $this->responseFor( 'insights', 'Insights', $ipAddress ); 182 } 183 184 private function responseFor( $endpoint, $class, $ipAddress ) { 185 $path = implode( '/', array( self::$basePath, $endpoint, $ipAddress ) ); 186 187 try { 188 $body = $this->client->get( 'GeoIP2 ' . $class, $path ); 189 } catch ( \MaxMind\Exception\IpAddressNotFoundException $ex ) { 190 throw new AddressNotFoundException( 191 $ex->getMessage(), 192 $ex->getStatusCode(), 193 $ex 194 ); 195 } catch ( \MaxMind\Exception\AuthenticationException $ex ) { 196 throw new AuthenticationException( 197 $ex->getMessage(), 198 $ex->getStatusCode(), 199 $ex 200 ); 201 } catch ( \MaxMind\Exception\InsufficientFundsException $ex ) { 202 throw new OutOfQueriesException( 203 $ex->getMessage(), 204 $ex->getStatusCode(), 205 $ex 206 ); 207 } catch ( \MaxMind\Exception\InvalidRequestException $ex ) { 208 throw new InvalidRequestException( 209 $ex->getMessage(), 210 $ex->getErrorCode(), 211 $ex->getStatusCode(), 212 $ex->getUri(), 213 $ex 214 ); 215 } catch ( \MaxMind\Exception\HttpException $ex ) { 216 throw new HttpException( 217 $ex->getMessage(), 218 $ex->getStatusCode(), 219 $ex->getUri(), 220 $ex 221 ); 222 } catch ( \MaxMind\Exception\WebServiceException $ex ) { 223 throw new GeoIp2Exception( 224 $ex->getMessage(), 225 $ex->getCode(), 226 $ex 227 ); 228 } 229 230 $class = 'GeoIp2\\Model\\' . $class; 231 232 return new $class( $body, $this->locales ); 233 } 239 234 } -
termageddon-usercentrics/trunk/vendor/maxmind-db/reader/autoload.php
r2771752 r3160131 17 17 * the name of the class to load 18 18 */ 19 function mmdb_autoload($class): void 20 { 21 /* 22 * A project-specific mapping between the namespaces and where 23 * they're located. By convention, we include the trailing 24 * slashes. The one-element array here simply makes things easy 25 * to extend in the future if (for example) the test classes 26 * begin to use one another. 27 */ 28 $namespace_map = ['MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/']; 19 function mmdb_autoload( $class ): void { 20 /* 21 * A project-specific mapping between the namespaces and where 22 * they're located. By convention, we include the trailing 23 * slashes. The one-element array here simply makes things easy 24 * to extend in the future if (for example) the test classes 25 * begin to use one another. 26 */ 27 $namespace_map = array( 'MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/' ); 29 28 30 foreach ($namespace_map as $prefix => $dir) {31 // First swap out the namespace prefix with a directory...32 $path = str_replace($prefix, $dir, $class);29 foreach ( $namespace_map as $prefix => $dir ) { 30 // First swap out the namespace prefix with a directory... 31 $path = str_replace( $prefix, $dir, $class ); 33 32 34 // replace the namespace separator with a directory separator...35 $path = str_replace('\\', '/', $path);33 // replace the namespace separator with a directory separator... 34 $path = str_replace( '\\', '/', $path ); 36 35 37 // and finally, add the PHP file extension to the result.38 $path = $path . '.php';36 // and finally, add the PHP file extension to the result. 37 $path = $path . '.php'; 39 38 40 // $path should now contain the path to a PHP file defining $class41 if (file_exists($path)) {42 include $path;43 }44 }39 // $path should now contain the path to a PHP file defining $class 40 if ( file_exists( $path ) ) { 41 include $path; 42 } 43 } 45 44 } 46 45 47 spl_autoload_register( 'mmdb_autoload');46 spl_autoload_register( 'mmdb_autoload' ); -
termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php
r2771752 r3160131 19 19 * addresses can be looked up using the get method. 20 20 */ 21 class Reader 22 { 23 /** 24 * @var int 25 */ 26 private static $DATA_SECTION_SEPARATOR_SIZE = 16; 27 /** 28 * @var string 29 */ 30 private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com"; 31 /** 32 * @var int 33 */ 34 private static $METADATA_START_MARKER_LENGTH = 14; 35 /** 36 * @var int 37 */ 38 private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KiB 39 40 /** 41 * @var Decoder 42 */ 43 private $decoder; 44 /** 45 * @var resource 46 */ 47 private $fileHandle; 48 /** 49 * @var int 50 */ 51 private $fileSize; 52 /** 53 * @var int 54 */ 55 private $ipV4Start; 56 /** 57 * @var Metadata 58 */ 59 private $metadata; 60 61 /** 62 * Constructs a Reader for the MaxMind DB format. The file passed to it must 63 * be a valid MaxMind DB file such as a GeoIp2 database file. 64 * 65 * @param string $database 66 * the MaxMind DB file to use 67 * 68 * @throws InvalidArgumentException for invalid database path or unknown arguments 69 * @throws InvalidDatabaseException 70 * if the database is invalid or there is an error reading 71 * from it 72 */ 73 public function __construct(string $database) 74 { 75 if (\func_num_args() !== 1) { 76 throw new ArgumentCountError( 77 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args()) 78 ); 79 } 80 81 $fileHandle = @fopen($database, 'rb'); 82 if ($fileHandle === false) { 83 throw new InvalidArgumentException( 84 "The file \"$database\" does not exist or is not readable." 85 ); 86 } 87 $this->fileHandle = $fileHandle; 88 89 $fileSize = @filesize($database); 90 if ($fileSize === false) { 91 throw new UnexpectedValueException( 92 "Error determining the size of \"$database\"." 93 ); 94 } 95 $this->fileSize = $fileSize; 96 97 $start = $this->findMetadataStart($database); 98 $metadataDecoder = new Decoder($this->fileHandle, $start); 99 [$metadataArray] = $metadataDecoder->decode($start); 100 $this->metadata = new Metadata($metadataArray); 101 $this->decoder = new Decoder( 102 $this->fileHandle, 103 $this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE 104 ); 105 $this->ipV4Start = $this->ipV4StartNode(); 106 } 107 108 /** 109 * Retrieves the record for the IP address. 110 * 111 * @param string $ipAddress 112 * the IP address to look up 113 * 114 * @throws BadMethodCallException if this method is called on a closed database 115 * @throws InvalidArgumentException if something other than a single IP address is passed to the method 116 * @throws InvalidDatabaseException 117 * if the database is invalid or there is an error reading 118 * from it 119 * 120 * @return mixed the record for the IP address 121 */ 122 public function get(string $ipAddress) 123 { 124 if (\func_num_args() !== 1) { 125 throw new ArgumentCountError( 126 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args()) 127 ); 128 } 129 [$record] = $this->getWithPrefixLen($ipAddress); 130 131 return $record; 132 } 133 134 /** 135 * Retrieves the record for the IP address and its associated network prefix length. 136 * 137 * @param string $ipAddress 138 * the IP address to look up 139 * 140 * @throws BadMethodCallException if this method is called on a closed database 141 * @throws InvalidArgumentException if something other than a single IP address is passed to the method 142 * @throws InvalidDatabaseException 143 * if the database is invalid or there is an error reading 144 * from it 145 * 146 * @return array an array where the first element is the record and the 147 * second the network prefix length for the record 148 */ 149 public function getWithPrefixLen(string $ipAddress): array 150 { 151 if (\func_num_args() !== 1) { 152 throw new ArgumentCountError( 153 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args()) 154 ); 155 } 156 157 if (!\is_resource($this->fileHandle)) { 158 throw new BadMethodCallException( 159 'Attempt to read from a closed MaxMind DB.' 160 ); 161 } 162 163 [$pointer, $prefixLen] = $this->findAddressInTree($ipAddress); 164 if ($pointer === 0) { 165 return [null, $prefixLen]; 166 } 167 168 return [$this->resolveDataPointer($pointer), $prefixLen]; 169 } 170 171 private function findAddressInTree(string $ipAddress): array 172 { 173 $packedAddr = @inet_pton($ipAddress); 174 if ($packedAddr === false) { 175 throw new InvalidArgumentException( 176 "The value \"$ipAddress\" is not a valid IP address." 177 ); 178 } 179 180 $rawAddress = unpack('C*', $packedAddr); 181 182 $bitCount = \count($rawAddress) * 8; 183 184 // The first node of the tree is always node 0, at the beginning of the 185 // value 186 $node = 0; 187 188 $metadata = $this->metadata; 189 190 // Check if we are looking up an IPv4 address in an IPv6 tree. If this 191 // is the case, we can skip over the first 96 nodes. 192 if ($metadata->ipVersion === 6) { 193 if ($bitCount === 32) { 194 $node = $this->ipV4Start; 195 } 196 } elseif ($metadata->ipVersion === 4 && $bitCount === 128) { 197 throw new InvalidArgumentException( 198 "Error looking up $ipAddress. You attempted to look up an" 199 . ' IPv6 address in an IPv4-only database.' 200 ); 201 } 202 203 $nodeCount = $metadata->nodeCount; 204 205 for ($i = 0; $i < $bitCount && $node < $nodeCount; ++$i) { 206 $tempBit = 0xFF & $rawAddress[($i >> 3) + 1]; 207 $bit = 1 & ($tempBit >> 7 - ($i % 8)); 208 209 $node = $this->readNode($node, $bit); 210 } 211 if ($node === $nodeCount) { 212 // Record is empty 213 return [0, $i]; 214 } 215 if ($node > $nodeCount) { 216 // Record is a data pointer 217 return [$node, $i]; 218 } 219 220 throw new InvalidDatabaseException( 221 'Invalid or corrupt database. Maximum search depth reached without finding a leaf node' 222 ); 223 } 224 225 private function ipV4StartNode(): int 226 { 227 // If we have an IPv4 database, the start node is the first node 228 if ($this->metadata->ipVersion === 4) { 229 return 0; 230 } 231 232 $node = 0; 233 234 for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; ++$i) { 235 $node = $this->readNode($node, 0); 236 } 237 238 return $node; 239 } 240 241 private function readNode(int $nodeNumber, int $index): int 242 { 243 $baseOffset = $nodeNumber * $this->metadata->nodeByteSize; 244 245 switch ($this->metadata->recordSize) { 246 case 24: 247 $bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3); 248 [, $node] = unpack('N', "\x00" . $bytes); 249 250 return $node; 251 252 case 28: 253 $bytes = Util::read($this->fileHandle, $baseOffset + 3 * $index, 4); 254 if ($index === 0) { 255 $middle = (0xF0 & \ord($bytes[3])) >> 4; 256 } else { 257 $middle = 0x0F & \ord($bytes[0]); 258 } 259 [, $node] = unpack('N', \chr($middle) . substr($bytes, $index, 3)); 260 261 return $node; 262 263 case 32: 264 $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4); 265 [, $node] = unpack('N', $bytes); 266 267 return $node; 268 269 default: 270 throw new InvalidDatabaseException( 271 'Unknown record size: ' 272 . $this->metadata->recordSize 273 ); 274 } 275 } 276 277 /** 278 * @return mixed 279 */ 280 private function resolveDataPointer(int $pointer) 281 { 282 $resolved = $pointer - $this->metadata->nodeCount 283 + $this->metadata->searchTreeSize; 284 if ($resolved >= $this->fileSize) { 285 throw new InvalidDatabaseException( 286 "The MaxMind DB file's search tree is corrupt" 287 ); 288 } 289 290 [$data] = $this->decoder->decode($resolved); 291 292 return $data; 293 } 294 295 /* 296 * This is an extremely naive but reasonably readable implementation. There 297 * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever 298 * an issue, but I suspect it won't be. 299 */ 300 private function findMetadataStart(string $filename): int 301 { 302 $handle = $this->fileHandle; 303 $fstat = fstat($handle); 304 $fileSize = $fstat['size']; 305 $marker = self::$METADATA_START_MARKER; 306 $markerLength = self::$METADATA_START_MARKER_LENGTH; 307 308 $minStart = $fileSize - min(self::$METADATA_MAX_SIZE, $fileSize); 309 310 for ($offset = $fileSize - $markerLength; $offset >= $minStart; --$offset) { 311 if (fseek($handle, $offset) !== 0) { 312 break; 313 } 314 315 $value = fread($handle, $markerLength); 316 if ($value === $marker) { 317 return $offset + $markerLength; 318 } 319 } 320 321 throw new InvalidDatabaseException( 322 "Error opening database file ($filename). " . 323 'Is this a valid MaxMind DB file?' 324 ); 325 } 326 327 /** 328 * @throws InvalidArgumentException if arguments are passed to the method 329 * @throws BadMethodCallException if the database has been closed 330 * 331 * @return Metadata object for the database 332 */ 333 public function metadata(): Metadata 334 { 335 if (\func_num_args()) { 336 throw new ArgumentCountError( 337 sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args()) 338 ); 339 } 340 341 // Not technically required, but this makes it consistent with 342 // C extension and it allows us to change our implementation later. 343 if (!\is_resource($this->fileHandle)) { 344 throw new BadMethodCallException( 345 'Attempt to read from a closed MaxMind DB.' 346 ); 347 } 348 349 return clone $this->metadata; 350 } 351 352 /** 353 * Closes the MaxMind DB and returns resources to the system. 354 * 355 * @throws Exception 356 * if an I/O error occurs 357 */ 358 public function close(): void 359 { 360 if (\func_num_args()) { 361 throw new ArgumentCountError( 362 sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args()) 363 ); 364 } 365 366 if (!\is_resource($this->fileHandle)) { 367 throw new BadMethodCallException( 368 'Attempt to close a closed MaxMind DB.' 369 ); 370 } 371 fclose($this->fileHandle); 372 } 21 class Reader { 22 23 /** 24 * @var int 25 */ 26 private static $DATA_SECTION_SEPARATOR_SIZE = 16; 27 /** 28 * @var string 29 */ 30 private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com"; 31 /** 32 * @var int 33 */ 34 private static $METADATA_START_MARKER_LENGTH = 14; 35 /** 36 * @var int 37 */ 38 private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KiB 39 40 /** 41 * @var Decoder 42 */ 43 private $decoder; 44 /** 45 * @var resource 46 */ 47 private $fileHandle; 48 /** 49 * @var int 50 */ 51 private $fileSize; 52 /** 53 * @var int 54 */ 55 private $ipV4Start; 56 /** 57 * @var Metadata 58 */ 59 private $metadata; 60 61 /** 62 * Constructs a Reader for the MaxMind DB format. The file passed to it must 63 * be a valid MaxMind DB file such as a GeoIp2 database file. 64 * 65 * @param string $database 66 * the MaxMind DB file to use 67 * 68 * @throws InvalidArgumentException for invalid database path or unknown arguments 69 * @throws InvalidDatabaseException 70 * if the database is invalid or there is an error reading 71 * from it 72 */ 73 public function __construct( string $database ) { 74 if ( \func_num_args() !== 1 ) { 75 throw new ArgumentCountError( 76 sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() ) 77 ); 78 } 79 80 $fileHandle = @fopen( $database, 'rb' ); 81 if ( $fileHandle === false ) { 82 throw new InvalidArgumentException( 83 "The file \"$database\" does not exist or is not readable." 84 ); 85 } 86 $this->fileHandle = $fileHandle; 87 88 $fileSize = @filesize( $database ); 89 if ( $fileSize === false ) { 90 throw new UnexpectedValueException( 91 "Error determining the size of \"$database\"." 92 ); 93 } 94 $this->fileSize = $fileSize; 95 96 $start = $this->findMetadataStart( $database ); 97 $metadataDecoder = new Decoder( $this->fileHandle, $start ); 98 [$metadataArray] = $metadataDecoder->decode( $start ); 99 $this->metadata = new Metadata( $metadataArray ); 100 $this->decoder = new Decoder( 101 $this->fileHandle, 102 $this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE 103 ); 104 $this->ipV4Start = $this->ipV4StartNode(); 105 } 106 107 /** 108 * Retrieves the record for the IP address. 109 * 110 * @param string $ipAddress 111 * the IP address to look up 112 * 113 * @throws BadMethodCallException if this method is called on a closed database 114 * @throws InvalidArgumentException if something other than a single IP address is passed to the method 115 * @throws InvalidDatabaseException 116 * if the database is invalid or there is an error reading 117 * from it 118 * 119 * @return mixed the record for the IP address 120 */ 121 public function get( string $ipAddress ) { 122 if ( \func_num_args() !== 1 ) { 123 throw new ArgumentCountError( 124 sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() ) 125 ); 126 } 127 [$record] = $this->getWithPrefixLen( $ipAddress ); 128 129 return $record; 130 } 131 132 /** 133 * Retrieves the record for the IP address and its associated network prefix length. 134 * 135 * @param string $ipAddress 136 * the IP address to look up 137 * 138 * @throws BadMethodCallException if this method is called on a closed database 139 * @throws InvalidArgumentException if something other than a single IP address is passed to the method 140 * @throws InvalidDatabaseException 141 * if the database is invalid or there is an error reading 142 * from it 143 * 144 * @return array an array where the first element is the record and the 145 * second the network prefix length for the record 146 */ 147 public function getWithPrefixLen( string $ipAddress ): array { 148 if ( \func_num_args() !== 1 ) { 149 throw new ArgumentCountError( 150 sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() ) 151 ); 152 } 153 154 if ( ! \is_resource( $this->fileHandle ) ) { 155 throw new BadMethodCallException( 156 'Attempt to read from a closed MaxMind DB.' 157 ); 158 } 159 160 [$pointer, $prefixLen] = $this->findAddressInTree( $ipAddress ); 161 if ( $pointer === 0 ) { 162 return array( null, $prefixLen ); 163 } 164 165 return array( $this->resolveDataPointer( $pointer ), $prefixLen ); 166 } 167 168 private function findAddressInTree( string $ipAddress ): array { 169 $packedAddr = @inet_pton( $ipAddress ); 170 if ( $packedAddr === false ) { 171 throw new InvalidArgumentException( 172 "The value \"$ipAddress\" is not a valid IP address." 173 ); 174 } 175 176 $rawAddress = unpack( 'C*', $packedAddr ); 177 178 $bitCount = \count( $rawAddress ) * 8; 179 180 // The first node of the tree is always node 0, at the beginning of the 181 // value 182 $node = 0; 183 184 $metadata = $this->metadata; 185 186 // Check if we are looking up an IPv4 address in an IPv6 tree. If this 187 // is the case, we can skip over the first 96 nodes. 188 if ( $metadata->ipVersion === 6 ) { 189 if ( $bitCount === 32 ) { 190 $node = $this->ipV4Start; 191 } 192 } elseif ( $metadata->ipVersion === 4 && $bitCount === 128 ) { 193 throw new InvalidArgumentException( 194 "Error looking up $ipAddress. You attempted to look up an" 195 . ' IPv6 address in an IPv4-only database.' 196 ); 197 } 198 199 $nodeCount = $metadata->nodeCount; 200 201 for ( $i = 0; $i < $bitCount && $node < $nodeCount; ++$i ) { 202 $tempBit = 0xFF & $rawAddress[ ( $i >> 3 ) + 1 ]; 203 $bit = 1 & ( $tempBit >> 7 - ( $i % 8 ) ); 204 205 $node = $this->readNode( $node, $bit ); 206 } 207 if ( $node === $nodeCount ) { 208 // Record is empty 209 return array( 0, $i ); 210 } 211 if ( $node > $nodeCount ) { 212 // Record is a data pointer 213 return array( $node, $i ); 214 } 215 216 throw new InvalidDatabaseException( 217 'Invalid or corrupt database. Maximum search depth reached without finding a leaf node' 218 ); 219 } 220 221 private function ipV4StartNode(): int { 222 // If we have an IPv4 database, the start node is the first node 223 if ( $this->metadata->ipVersion === 4 ) { 224 return 0; 225 } 226 227 $node = 0; 228 229 for ( $i = 0; $i < 96 && $node < $this->metadata->nodeCount; ++$i ) { 230 $node = $this->readNode( $node, 0 ); 231 } 232 233 return $node; 234 } 235 236 private function readNode( int $nodeNumber, int $index ): int { 237 $baseOffset = $nodeNumber * $this->metadata->nodeByteSize; 238 239 switch ( $this->metadata->recordSize ) { 240 case 24: 241 $bytes = Util::read( $this->fileHandle, $baseOffset + $index * 3, 3 ); 242 [, $node] = unpack( 'N', "\x00" . $bytes ); 243 244 return $node; 245 246 case 28: 247 $bytes = Util::read( $this->fileHandle, $baseOffset + 3 * $index, 4 ); 248 if ( $index === 0 ) { 249 $middle = ( 0xF0 & \ord( $bytes[3] ) ) >> 4; 250 } else { 251 $middle = 0x0F & \ord( $bytes[0] ); 252 } 253 [, $node] = unpack( 'N', \chr( $middle ) . substr( $bytes, $index, 3 ) ); 254 255 return $node; 256 257 case 32: 258 $bytes = Util::read( $this->fileHandle, $baseOffset + $index * 4, 4 ); 259 [, $node] = unpack( 'N', $bytes ); 260 261 return $node; 262 263 default: 264 throw new InvalidDatabaseException( 265 'Unknown record size: ' 266 . $this->metadata->recordSize 267 ); 268 } 269 } 270 271 /** 272 * @return mixed 273 */ 274 private function resolveDataPointer( int $pointer ) { 275 $resolved = $pointer - $this->metadata->nodeCount 276 + $this->metadata->searchTreeSize; 277 if ( $resolved >= $this->fileSize ) { 278 throw new InvalidDatabaseException( 279 "The MaxMind DB file's search tree is corrupt" 280 ); 281 } 282 283 [$data] = $this->decoder->decode( $resolved ); 284 285 return $data; 286 } 287 288 /* 289 * This is an extremely naive but reasonably readable implementation. There 290 * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever 291 * an issue, but I suspect it won't be. 292 */ 293 private function findMetadataStart( string $filename ): int { 294 $handle = $this->fileHandle; 295 $fstat = fstat( $handle ); 296 $fileSize = $fstat['size']; 297 $marker = self::$METADATA_START_MARKER; 298 $markerLength = self::$METADATA_START_MARKER_LENGTH; 299 300 $minStart = $fileSize - min( self::$METADATA_MAX_SIZE, $fileSize ); 301 302 for ( $offset = $fileSize - $markerLength; $offset >= $minStart; --$offset ) { 303 if ( fseek( $handle, $offset ) !== 0 ) { 304 break; 305 } 306 307 $value = fread( $handle, $markerLength ); 308 if ( $value === $marker ) { 309 return $offset + $markerLength; 310 } 311 } 312 313 throw new InvalidDatabaseException( 314 "Error opening database file ($filename). " . 315 'Is this a valid MaxMind DB file?' 316 ); 317 } 318 319 /** 320 * @throws InvalidArgumentException if arguments are passed to the method 321 * @throws BadMethodCallException if the database has been closed 322 * 323 * @return Metadata object for the database 324 */ 325 public function metadata(): Metadata { 326 if ( \func_num_args() ) { 327 throw new ArgumentCountError( 328 sprintf( '%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args() ) 329 ); 330 } 331 332 // Not technically required, but this makes it consistent with 333 // C extension and it allows us to change our implementation later. 334 if ( ! \is_resource( $this->fileHandle ) ) { 335 throw new BadMethodCallException( 336 'Attempt to read from a closed MaxMind DB.' 337 ); 338 } 339 340 return clone $this->metadata; 341 } 342 343 /** 344 * Closes the MaxMind DB and returns resources to the system. 345 * 346 * @throws Exception 347 * if an I/O error occurs 348 */ 349 public function close(): void { 350 if ( \func_num_args() ) { 351 throw new ArgumentCountError( 352 sprintf( '%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args() ) 353 ); 354 } 355 356 if ( ! \is_resource( $this->fileHandle ) ) { 357 throw new BadMethodCallException( 358 'Attempt to close a closed MaxMind DB.' 359 ); 360 } 361 fclose( $this->fileHandle ); 362 } 373 363 } -
termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php
r2771752 r3160131 8 8 use RuntimeException; 9 9 10 class Decoder 11 { 12 /** 13 * @var resource 14 */ 15 private $fileStream; 16 /** 17 * @var int 18 */ 19 private $pointerBase; 20 /** 21 * @var float 22 */ 23 private $pointerBaseByteSize; 24 /** 25 * This is only used for unit testing. 26 * 27 * @var bool 28 */ 29 private $pointerTestHack; 30 /** 31 * @var bool 32 */ 33 private $switchByteOrder; 34 35 private const _EXTENDED = 0; 36 private const _POINTER = 1; 37 private const _UTF8_STRING = 2; 38 private const _DOUBLE = 3; 39 private const _BYTES = 4; 40 private const _UINT16 = 5; 41 private const _UINT32 = 6; 42 private const _MAP = 7; 43 private const _INT32 = 8; 44 private const _UINT64 = 9; 45 private const _UINT128 = 10; 46 private const _ARRAY = 11; 47 private const _CONTAINER = 12; 48 private const _END_MARKER = 13; 49 private const _BOOLEAN = 14; 50 private const _FLOAT = 15; 51 52 /** 53 * @param resource $fileStream 54 */ 55 public function __construct( 56 $fileStream, 57 int $pointerBase = 0, 58 bool $pointerTestHack = false 59 ) { 60 $this->fileStream = $fileStream; 61 $this->pointerBase = $pointerBase; 62 63 $this->pointerBaseByteSize = $pointerBase > 0 ? log($pointerBase, 2) / 8 : 0; 64 $this->pointerTestHack = $pointerTestHack; 65 66 $this->switchByteOrder = $this->isPlatformLittleEndian(); 67 } 68 69 public function decode(int $offset): array 70 { 71 $ctrlByte = \ord(Util::read($this->fileStream, $offset, 1)); 72 ++$offset; 73 74 $type = $ctrlByte >> 5; 75 76 // Pointers are a special case, we don't read the next $size bytes, we 77 // use the size to determine the length of the pointer and then follow 78 // it. 79 if ($type === self::_POINTER) { 80 [$pointer, $offset] = $this->decodePointer($ctrlByte, $offset); 81 82 // for unit testing 83 if ($this->pointerTestHack) { 84 return [$pointer]; 85 } 86 87 [$result] = $this->decode($pointer); 88 89 return [$result, $offset]; 90 } 91 92 if ($type === self::_EXTENDED) { 93 $nextByte = \ord(Util::read($this->fileStream, $offset, 1)); 94 95 $type = $nextByte + 7; 96 97 if ($type < 8) { 98 throw new InvalidDatabaseException( 99 'Something went horribly wrong in the decoder. An extended type ' 100 . 'resolved to a type number < 8 (' 101 . $type 102 . ')' 103 ); 104 } 105 106 ++$offset; 107 } 108 109 [$size, $offset] = $this->sizeFromCtrlByte($ctrlByte, $offset); 110 111 return $this->decodeByType($type, $offset, $size); 112 } 113 114 private function decodeByType(int $type, int $offset, int $size): array 115 { 116 switch ($type) { 117 case self::_MAP: 118 return $this->decodeMap($size, $offset); 119 120 case self::_ARRAY: 121 return $this->decodeArray($size, $offset); 122 123 case self::_BOOLEAN: 124 return [$this->decodeBoolean($size), $offset]; 125 } 126 127 $newOffset = $offset + $size; 128 $bytes = Util::read($this->fileStream, $offset, $size); 129 130 switch ($type) { 131 case self::_BYTES: 132 case self::_UTF8_STRING: 133 return [$bytes, $newOffset]; 134 135 case self::_DOUBLE: 136 $this->verifySize(8, $size); 137 138 return [$this->decodeDouble($bytes), $newOffset]; 139 140 case self::_FLOAT: 141 $this->verifySize(4, $size); 142 143 return [$this->decodeFloat($bytes), $newOffset]; 144 145 case self::_INT32: 146 return [$this->decodeInt32($bytes, $size), $newOffset]; 147 148 case self::_UINT16: 149 case self::_UINT32: 150 case self::_UINT64: 151 case self::_UINT128: 152 return [$this->decodeUint($bytes, $size), $newOffset]; 153 154 default: 155 throw new InvalidDatabaseException( 156 'Unknown or unexpected type: ' . $type 157 ); 158 } 159 } 160 161 private function verifySize(int $expected, int $actual): void 162 { 163 if ($expected !== $actual) { 164 throw new InvalidDatabaseException( 165 "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)" 166 ); 167 } 168 } 169 170 private function decodeArray(int $size, int $offset): array 171 { 172 $array = []; 173 174 for ($i = 0; $i < $size; ++$i) { 175 [$value, $offset] = $this->decode($offset); 176 $array[] = $value; 177 } 178 179 return [$array, $offset]; 180 } 181 182 private function decodeBoolean(int $size): bool 183 { 184 return $size !== 0; 185 } 186 187 private function decodeDouble(string $bytes): float 188 { 189 // This assumes IEEE 754 doubles, but most (all?) modern platforms 190 // use them. 191 [, $double] = unpack('E', $bytes); 192 193 return $double; 194 } 195 196 private function decodeFloat(string $bytes): float 197 { 198 // This assumes IEEE 754 floats, but most (all?) modern platforms 199 // use them. 200 [, $float] = unpack('G', $bytes); 201 202 return $float; 203 } 204 205 private function decodeInt32(string $bytes, int $size): int 206 { 207 switch ($size) { 208 case 0: 209 return 0; 210 211 case 1: 212 case 2: 213 case 3: 214 $bytes = str_pad($bytes, 4, "\x00", \STR_PAD_LEFT); 215 216 break; 217 218 case 4: 219 break; 220 221 default: 222 throw new InvalidDatabaseException( 223 "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)" 224 ); 225 } 226 227 [, $int] = unpack('l', $this->maybeSwitchByteOrder($bytes)); 228 229 return $int; 230 } 231 232 private function decodeMap(int $size, int $offset): array 233 { 234 $map = []; 235 236 for ($i = 0; $i < $size; ++$i) { 237 [$key, $offset] = $this->decode($offset); 238 [$value, $offset] = $this->decode($offset); 239 $map[$key] = $value; 240 } 241 242 return [$map, $offset]; 243 } 244 245 private function decodePointer(int $ctrlByte, int $offset): array 246 { 247 $pointerSize = (($ctrlByte >> 3) & 0x3) + 1; 248 249 $buffer = Util::read($this->fileStream, $offset, $pointerSize); 250 $offset = $offset + $pointerSize; 251 252 switch ($pointerSize) { 253 case 1: 254 $packed = \chr($ctrlByte & 0x7) . $buffer; 255 [, $pointer] = unpack('n', $packed); 256 $pointer += $this->pointerBase; 257 258 break; 259 260 case 2: 261 $packed = "\x00" . \chr($ctrlByte & 0x7) . $buffer; 262 [, $pointer] = unpack('N', $packed); 263 $pointer += $this->pointerBase + 2048; 264 265 break; 266 267 case 3: 268 $packed = \chr($ctrlByte & 0x7) . $buffer; 269 270 // It is safe to use 'N' here, even on 32 bit machines as the 271 // first bit is 0. 272 [, $pointer] = unpack('N', $packed); 273 $pointer += $this->pointerBase + 526336; 274 275 break; 276 277 case 4: 278 // We cannot use unpack here as we might overflow on 32 bit 279 // machines 280 $pointerOffset = $this->decodeUint($buffer, $pointerSize); 281 282 $pointerBase = $this->pointerBase; 283 284 if (\PHP_INT_MAX - $pointerBase >= $pointerOffset) { 285 $pointer = $pointerOffset + $pointerBase; 286 } else { 287 throw new RuntimeException( 288 'The database offset is too large to be represented on your platform.' 289 ); 290 } 291 292 break; 293 294 default: 295 throw new InvalidDatabaseException( 296 'Unexpected pointer size ' . $pointerSize 297 ); 298 } 299 300 return [$pointer, $offset]; 301 } 302 303 // @phpstan-ignore-next-line 304 private function decodeUint(string $bytes, int $byteLength) 305 { 306 if ($byteLength === 0) { 307 return 0; 308 } 309 310 $integer = 0; 311 312 // PHP integers are signed. PHP_INT_SIZE - 1 is the number of 313 // complete bytes that can be converted to an integer. However, 314 // we can convert another byte if the leading bit is zero. 315 $useRealInts = $byteLength <= \PHP_INT_SIZE - 1 316 || ($byteLength === \PHP_INT_SIZE && (\ord($bytes[0]) & 0x80) === 0); 317 318 for ($i = 0; $i < $byteLength; ++$i) { 319 $part = \ord($bytes[$i]); 320 321 // We only use gmp or bcmath if the final value is too big 322 if ($useRealInts) { 323 $integer = ($integer << 8) + $part; 324 } elseif (\extension_loaded('gmp')) { 325 $integer = gmp_strval(gmp_add(gmp_mul((string) $integer, '256'), $part)); 326 } elseif (\extension_loaded('bcmath')) { 327 $integer = bcadd(bcmul((string) $integer, '256'), (string) $part); 328 } else { 329 throw new RuntimeException( 330 'The gmp or bcmath extension must be installed to read this database.' 331 ); 332 } 333 } 334 335 return $integer; 336 } 337 338 private function sizeFromCtrlByte(int $ctrlByte, int $offset): array 339 { 340 $size = $ctrlByte & 0x1F; 341 342 if ($size < 29) { 343 return [$size, $offset]; 344 } 345 346 $bytesToRead = $size - 28; 347 $bytes = Util::read($this->fileStream, $offset, $bytesToRead); 348 349 if ($size === 29) { 350 $size = 29 + \ord($bytes); 351 } elseif ($size === 30) { 352 [, $adjust] = unpack('n', $bytes); 353 $size = 285 + $adjust; 354 } else { 355 [, $adjust] = unpack('N', "\x00" . $bytes); 356 $size = $adjust + 65821; 357 } 358 359 return [$size, $offset + $bytesToRead]; 360 } 361 362 private function maybeSwitchByteOrder(string $bytes): string 363 { 364 return $this->switchByteOrder ? strrev($bytes) : $bytes; 365 } 366 367 private function isPlatformLittleEndian(): bool 368 { 369 $testint = 0x00FF; 370 $packed = pack('S', $testint); 371 372 return $testint === current(unpack('v', $packed)); 373 } 10 class Decoder { 11 12 /** 13 * @var resource 14 */ 15 private $fileStream; 16 /** 17 * @var int 18 */ 19 private $pointerBase; 20 /** 21 * @var float 22 */ 23 private $pointerBaseByteSize; 24 /** 25 * This is only used for unit testing. 26 * 27 * @var bool 28 */ 29 private $pointerTestHack; 30 /** 31 * @var bool 32 */ 33 private $switchByteOrder; 34 35 private const _EXTENDED = 0; 36 private const _POINTER = 1; 37 private const _UTF8_STRING = 2; 38 private const _DOUBLE = 3; 39 private const _BYTES = 4; 40 private const _UINT16 = 5; 41 private const _UINT32 = 6; 42 private const _MAP = 7; 43 private const _INT32 = 8; 44 private const _UINT64 = 9; 45 private const _UINT128 = 10; 46 private const _ARRAY = 11; 47 private const _CONTAINER = 12; 48 private const _END_MARKER = 13; 49 private const _BOOLEAN = 14; 50 private const _FLOAT = 15; 51 52 /** 53 * @param resource $fileStream 54 */ 55 public function __construct( 56 $fileStream, 57 int $pointerBase = 0, 58 bool $pointerTestHack = false 59 ) { 60 $this->fileStream = $fileStream; 61 $this->pointerBase = $pointerBase; 62 63 $this->pointerBaseByteSize = $pointerBase > 0 ? log( $pointerBase, 2 ) / 8 : 0; 64 $this->pointerTestHack = $pointerTestHack; 65 66 $this->switchByteOrder = $this->isPlatformLittleEndian(); 67 } 68 69 public function decode( int $offset ): array { 70 $ctrlByte = \ord( Util::read( $this->fileStream, $offset, 1 ) ); 71 ++$offset; 72 73 $type = $ctrlByte >> 5; 74 75 // Pointers are a special case, we don't read the next $size bytes, we 76 // use the size to determine the length of the pointer and then follow 77 // it. 78 if ( $type === self::_POINTER ) { 79 [$pointer, $offset] = $this->decodePointer( $ctrlByte, $offset ); 80 81 // for unit testing 82 if ( $this->pointerTestHack ) { 83 return array( $pointer ); 84 } 85 86 [$result] = $this->decode( $pointer ); 87 88 return array( $result, $offset ); 89 } 90 91 if ( $type === self::_EXTENDED ) { 92 $nextByte = \ord( Util::read( $this->fileStream, $offset, 1 ) ); 93 94 $type = $nextByte + 7; 95 96 if ( $type < 8 ) { 97 throw new InvalidDatabaseException( 98 'Something went horribly wrong in the decoder. An extended type ' 99 . 'resolved to a type number < 8 (' 100 . $type 101 . ')' 102 ); 103 } 104 105 ++$offset; 106 } 107 108 [$size, $offset] = $this->sizeFromCtrlByte( $ctrlByte, $offset ); 109 110 return $this->decodeByType( $type, $offset, $size ); 111 } 112 113 private function decodeByType( int $type, int $offset, int $size ): array { 114 switch ( $type ) { 115 case self::_MAP: 116 return $this->decodeMap( $size, $offset ); 117 118 case self::_ARRAY: 119 return $this->decodeArray( $size, $offset ); 120 121 case self::_BOOLEAN: 122 return array( $this->decodeBoolean( $size ), $offset ); 123 } 124 125 $newOffset = $offset + $size; 126 $bytes = Util::read( $this->fileStream, $offset, $size ); 127 128 switch ( $type ) { 129 case self::_BYTES: 130 case self::_UTF8_STRING: 131 return array( $bytes, $newOffset ); 132 133 case self::_DOUBLE: 134 $this->verifySize( 8, $size ); 135 136 return array( $this->decodeDouble( $bytes ), $newOffset ); 137 138 case self::_FLOAT: 139 $this->verifySize( 4, $size ); 140 141 return array( $this->decodeFloat( $bytes ), $newOffset ); 142 143 case self::_INT32: 144 return array( $this->decodeInt32( $bytes, $size ), $newOffset ); 145 146 case self::_UINT16: 147 case self::_UINT32: 148 case self::_UINT64: 149 case self::_UINT128: 150 return array( $this->decodeUint( $bytes, $size ), $newOffset ); 151 152 default: 153 throw new InvalidDatabaseException( 154 'Unknown or unexpected type: ' . $type 155 ); 156 } 157 } 158 159 private function verifySize( int $expected, int $actual ): void { 160 if ( $expected !== $actual ) { 161 throw new InvalidDatabaseException( 162 "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)" 163 ); 164 } 165 } 166 167 private function decodeArray( int $size, int $offset ): array { 168 $array = array(); 169 170 for ( $i = 0; $i < $size; ++$i ) { 171 [$value, $offset] = $this->decode( $offset ); 172 $array[] = $value; 173 } 174 175 return array( $array, $offset ); 176 } 177 178 private function decodeBoolean( int $size ): bool { 179 return $size !== 0; 180 } 181 182 private function decodeDouble( string $bytes ): float { 183 // This assumes IEEE 754 doubles, but most (all?) modern platforms 184 // use them. 185 [, $double] = unpack( 'E', $bytes ); 186 187 return $double; 188 } 189 190 private function decodeFloat( string $bytes ): float { 191 // This assumes IEEE 754 floats, but most (all?) modern platforms 192 // use them. 193 [, $float] = unpack( 'G', $bytes ); 194 195 return $float; 196 } 197 198 private function decodeInt32( string $bytes, int $size ): int { 199 switch ( $size ) { 200 case 0: 201 return 0; 202 203 case 1: 204 case 2: 205 case 3: 206 $bytes = str_pad( $bytes, 4, "\x00", \STR_PAD_LEFT ); 207 208 break; 209 210 case 4: 211 break; 212 213 default: 214 throw new InvalidDatabaseException( 215 "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)" 216 ); 217 } 218 219 [, $int] = unpack( 'l', $this->maybeSwitchByteOrder( $bytes ) ); 220 221 return $int; 222 } 223 224 private function decodeMap( int $size, int $offset ): array { 225 $map = array(); 226 227 for ( $i = 0; $i < $size; ++$i ) { 228 [$key, $offset] = $this->decode( $offset ); 229 [$value, $offset] = $this->decode( $offset ); 230 $map[ $key ] = $value; 231 } 232 233 return array( $map, $offset ); 234 } 235 236 private function decodePointer( int $ctrlByte, int $offset ): array { 237 $pointerSize = ( ( $ctrlByte >> 3 ) & 0x3 ) + 1; 238 239 $buffer = Util::read( $this->fileStream, $offset, $pointerSize ); 240 $offset = $offset + $pointerSize; 241 242 switch ( $pointerSize ) { 243 case 1: 244 $packed = \chr( $ctrlByte & 0x7 ) . $buffer; 245 [, $pointer] = unpack( 'n', $packed ); 246 $pointer += $this->pointerBase; 247 248 break; 249 250 case 2: 251 $packed = "\x00" . \chr( $ctrlByte & 0x7 ) . $buffer; 252 [, $pointer] = unpack( 'N', $packed ); 253 $pointer += $this->pointerBase + 2048; 254 255 break; 256 257 case 3: 258 $packed = \chr( $ctrlByte & 0x7 ) . $buffer; 259 260 // It is safe to use 'N' here, even on 32 bit machines as the 261 // first bit is 0. 262 [, $pointer] = unpack( 'N', $packed ); 263 $pointer += $this->pointerBase + 526336; 264 265 break; 266 267 case 4: 268 // We cannot use unpack here as we might overflow on 32 bit 269 // machines 270 $pointerOffset = $this->decodeUint( $buffer, $pointerSize ); 271 272 $pointerBase = $this->pointerBase; 273 274 if ( \PHP_INT_MAX - $pointerBase >= $pointerOffset ) { 275 $pointer = $pointerOffset + $pointerBase; 276 } else { 277 throw new RuntimeException( 278 'The database offset is too large to be represented on your platform.' 279 ); 280 } 281 282 break; 283 284 default: 285 throw new InvalidDatabaseException( 286 'Unexpected pointer size ' . $pointerSize 287 ); 288 } 289 290 return array( $pointer, $offset ); 291 } 292 293 // @phpstan-ignore-next-line 294 private function decodeUint( string $bytes, int $byteLength ) { 295 if ( $byteLength === 0 ) { 296 return 0; 297 } 298 299 $integer = 0; 300 301 // PHP integers are signed. PHP_INT_SIZE - 1 is the number of 302 // complete bytes that can be converted to an integer. However, 303 // we can convert another byte if the leading bit is zero. 304 $useRealInts = $byteLength <= \PHP_INT_SIZE - 1 305 || ( $byteLength === \PHP_INT_SIZE && ( \ord( $bytes[0] ) & 0x80 ) === 0 ); 306 307 for ( $i = 0; $i < $byteLength; ++$i ) { 308 $part = \ord( $bytes[ $i ] ); 309 310 // We only use gmp or bcmath if the final value is too big 311 if ( $useRealInts ) { 312 $integer = ( $integer << 8 ) + $part; 313 } elseif ( \extension_loaded( 'gmp' ) ) { 314 $integer = gmp_strval( gmp_add( gmp_mul( (string) $integer, '256' ), $part ) ); 315 } elseif ( \extension_loaded( 'bcmath' ) ) { 316 $integer = bcadd( bcmul( (string) $integer, '256' ), (string) $part ); 317 } else { 318 throw new RuntimeException( 319 'The gmp or bcmath extension must be installed to read this database.' 320 ); 321 } 322 } 323 324 return $integer; 325 } 326 327 private function sizeFromCtrlByte( int $ctrlByte, int $offset ): array { 328 $size = $ctrlByte & 0x1F; 329 330 if ( $size < 29 ) { 331 return array( $size, $offset ); 332 } 333 334 $bytesToRead = $size - 28; 335 $bytes = Util::read( $this->fileStream, $offset, $bytesToRead ); 336 337 if ( $size === 29 ) { 338 $size = 29 + \ord( $bytes ); 339 } elseif ( $size === 30 ) { 340 [, $adjust] = unpack( 'n', $bytes ); 341 $size = 285 + $adjust; 342 } else { 343 [, $adjust] = unpack( 'N', "\x00" . $bytes ); 344 $size = $adjust + 65821; 345 } 346 347 return array( $size, $offset + $bytesToRead ); 348 } 349 350 private function maybeSwitchByteOrder( string $bytes ): string { 351 return $this->switchByteOrder ? strrev( $bytes ) : $bytes; 352 } 353 354 private function isPlatformLittleEndian(): bool { 355 $testint = 0x00FF; 356 $packed = pack( 'S', $testint ); 357 358 return $testint === current( unpack( 'v', $packed ) ); 359 } 374 360 } -
termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php
r2771752 r3160131 10 10 * This class should be thrown when unexpected data is found in the database. 11 11 */ 12 class InvalidDatabaseException extends Exception 13 { 12 class InvalidDatabaseException extends Exception { 13 14 14 } -
termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php
r2771752 r3160131 10 10 * This class provides the metadata for the MaxMind DB file. 11 11 */ 12 class Metadata 13 { 14 /** 15 * This is an unsigned 16-bit integer indicating the major version number 16 * for the database's binary format. 17 * 18 * @var int 19 */ 20 public $binaryFormatMajorVersion; 21 /** 22 * This is an unsigned 16-bit integer indicating the minor version number 23 * for the database's binary format. 24 * 25 * @var int 26 */ 27 public $binaryFormatMinorVersion; 28 /** 29 * This is an unsigned 64-bit integer that contains the database build 30 * timestamp as a Unix epoch value. 31 * 32 * @var int 33 */ 34 public $buildEpoch; 35 /** 36 * This is a string that indicates the structure of each data record 37 * associated with an IP address. The actual definition of these 38 * structures is left up to the database creator. 39 * 40 * @var string 41 */ 42 public $databaseType; 43 /** 44 * This key will always point to a map (associative array). The keys of 45 * that map will be language codes, and the values will be a description 46 * in that language as a UTF-8 string. May be undefined for some 47 * databases. 48 * 49 * @var array 50 */ 51 public $description; 52 /** 53 * This is an unsigned 16-bit integer which is always 4 or 6. It indicates 54 * whether the database contains IPv4 or IPv6 address data. 55 * 56 * @var int 57 */ 58 public $ipVersion; 59 /** 60 * An array of strings, each of which is a language code. A given record 61 * may contain data items that have been localized to some or all of 62 * these languages. This may be undefined. 63 * 64 * @var array 65 */ 66 public $languages; 67 /** 68 * @var int 69 */ 70 public $nodeByteSize; 71 /** 72 * This is an unsigned 32-bit integer indicating the number of nodes in 73 * the search tree. 74 * 75 * @var int 76 */ 77 public $nodeCount; 78 /** 79 * This is an unsigned 16-bit integer. It indicates the number of bits in a 80 * record in the search tree. Note that each node consists of two records. 81 * 82 * @var int 83 */ 84 public $recordSize; 85 /** 86 * @var int 87 */ 88 public $searchTreeSize; 12 class Metadata { 89 13 90 public function __construct(array $metadata) 91 { 92 if (\func_num_args() !== 1) { 93 throw new ArgumentCountError( 94 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args()) 95 ); 96 } 14 /** 15 * This is an unsigned 16-bit integer indicating the major version number 16 * for the database's binary format. 17 * 18 * @var int 19 */ 20 public $binaryFormatMajorVersion; 21 /** 22 * This is an unsigned 16-bit integer indicating the minor version number 23 * for the database's binary format. 24 * 25 * @var int 26 */ 27 public $binaryFormatMinorVersion; 28 /** 29 * This is an unsigned 64-bit integer that contains the database build 30 * timestamp as a Unix epoch value. 31 * 32 * @var int 33 */ 34 public $buildEpoch; 35 /** 36 * This is a string that indicates the structure of each data record 37 * associated with an IP address. The actual definition of these 38 * structures is left up to the database creator. 39 * 40 * @var string 41 */ 42 public $databaseType; 43 /** 44 * This key will always point to a map (associative array). The keys of 45 * that map will be language codes, and the values will be a description 46 * in that language as a UTF-8 string. May be undefined for some 47 * databases. 48 * 49 * @var array 50 */ 51 public $description; 52 /** 53 * This is an unsigned 16-bit integer which is always 4 or 6. It indicates 54 * whether the database contains IPv4 or IPv6 address data. 55 * 56 * @var int 57 */ 58 public $ipVersion; 59 /** 60 * An array of strings, each of which is a language code. A given record 61 * may contain data items that have been localized to some or all of 62 * these languages. This may be undefined. 63 * 64 * @var array 65 */ 66 public $languages; 67 /** 68 * @var int 69 */ 70 public $nodeByteSize; 71 /** 72 * This is an unsigned 32-bit integer indicating the number of nodes in 73 * the search tree. 74 * 75 * @var int 76 */ 77 public $nodeCount; 78 /** 79 * This is an unsigned 16-bit integer. It indicates the number of bits in a 80 * record in the search tree. Note that each node consists of two records. 81 * 82 * @var int 83 */ 84 public $recordSize; 85 /** 86 * @var int 87 */ 88 public $searchTreeSize; 97 89 98 $this->binaryFormatMajorVersion = 99 $metadata['binary_format_major_version']; 100 $this->binaryFormatMinorVersion = 101 $metadata['binary_format_minor_version']; 102 $this->buildEpoch = $metadata['build_epoch']; 103 $this->databaseType = $metadata['database_type']; 104 $this->languages = $metadata['languages']; 105 $this->description = $metadata['description']; 106 $this->ipVersion = $metadata['ip_version']; 107 $this->nodeCount = $metadata['node_count']; 108 $this->recordSize = $metadata['record_size']; 109 $this->nodeByteSize = $this->recordSize / 4; 110 $this->searchTreeSize = $this->nodeCount * $this->nodeByteSize; 111 } 90 public function __construct( array $metadata ) { 91 if ( \func_num_args() !== 1 ) { 92 throw new ArgumentCountError( 93 sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() ) 94 ); 95 } 96 97 $this->binaryFormatMajorVersion = 98 $metadata['binary_format_major_version']; 99 $this->binaryFormatMinorVersion = 100 $metadata['binary_format_minor_version']; 101 $this->buildEpoch = $metadata['build_epoch']; 102 $this->databaseType = $metadata['database_type']; 103 $this->languages = $metadata['languages']; 104 $this->description = $metadata['description']; 105 $this->ipVersion = $metadata['ip_version']; 106 $this->nodeCount = $metadata['node_count']; 107 $this->recordSize = $metadata['record_size']; 108 $this->nodeByteSize = $this->recordSize / 4; 109 $this->searchTreeSize = $this->nodeCount * $this->nodeByteSize; 110 } 112 111 } -
termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php
r2771752 r3160131 5 5 namespace MaxMind\Db\Reader; 6 6 7 class Util 8 { 9 /** 10 * @param resource $stream 11 */ 12 public static function read($stream, int $offset, int $numberOfBytes): string 13 { 14 if ($numberOfBytes === 0) { 15 return ''; 16 } 17 if (fseek($stream, $offset) === 0) { 18 $value = fread($stream, $numberOfBytes); 7 class Util { 19 8 20 // We check that the number of bytes read is equal to the number 21 // asked for. We use ftell as getting the length of $value is 22 // much slower. 23 if ($value !== false && ftell($stream) - $offset === $numberOfBytes) { 24 return $value; 25 } 26 } 9 /** 10 * @param resource $stream 11 */ 12 public static function read( $stream, int $offset, int $numberOfBytes ): string { 13 if ( $numberOfBytes === 0 ) { 14 return ''; 15 } 16 if ( fseek( $stream, $offset ) === 0 ) { 17 $value = fread( $stream, $numberOfBytes ); 27 18 28 throw new InvalidDatabaseException( 29 'The MaxMind DB file contains bad data' 30 ); 31 } 19 // We check that the number of bytes read is equal to the number 20 // asked for. We use ftell as getting the length of $value is 21 // much slower. 22 if ( $value !== false && ftell( $stream ) - $offset === $numberOfBytes ) { 23 return $value; 24 } 25 } 26 27 throw new InvalidDatabaseException( 28 'The MaxMind DB file contains bad data' 29 ); 30 } 32 31 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php
r2771752 r3160131 8 8 * This class represents an error authenticating. 9 9 */ 10 class AuthenticationException extends InvalidRequestException 11 { 10 class AuthenticationException extends InvalidRequestException { 11 12 12 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/HttpException.php
r2771752 r3160131 8 8 * This class represents an HTTP transport error. 9 9 */ 10 class HttpException extends WebServiceException 11 { 12 /** 13 * The URI queried. 14 * 15 * @var string 16 */ 17 private $uri; 10 class HttpException extends WebServiceException { 18 11 19 /** 20 * @param string $message a message describing the error 21 * @param int $httpStatus the HTTP status code of the response 22 * @param string $uri the URI used in the request 23 * @param \Exception $previous the previous exception, if any 24 */ 25 public function __construct( 26 string $message, 27 int $httpStatus, 28 string $uri, 29 \Exception $previous = null 30 ) { 31 $this->uri = $uri; 32 parent::__construct($message, $httpStatus, $previous); 33 } 12 /** 13 * The URI queried. 14 * 15 * @var string 16 */ 17 private $uri; 34 18 35 public function getUri(): string 36 { 37 return $this->uri; 38 } 19 /** 20 * @param string $message a message describing the error 21 * @param int $httpStatus the HTTP status code of the response 22 * @param string $uri the URI used in the request 23 * @param \Exception $previous the previous exception, if any 24 */ 25 public function __construct( 26 string $message, 27 int $httpStatus, 28 string $uri, 29 \Exception $previous = null 30 ) { 31 $this->uri = $uri; 32 parent::__construct( $message, $httpStatus, $previous ); 33 } 39 34 40 public function getStatusCode(): int 41 { 42 return $this->getCode(); 43 } 35 public function getUri(): string { 36 return $this->uri; 37 } 38 39 public function getStatusCode(): int { 40 return $this->getCode(); 41 } 44 42 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php
r2771752 r3160131 8 8 * Thrown when the account is out of credits. 9 9 */ 10 class InsufficientFundsException extends InvalidRequestException 11 { 10 class InsufficientFundsException extends InvalidRequestException { 11 12 12 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php
r2771752 r3160131 10 10 * is a missing or invalid field. 11 11 */ 12 class InvalidInputException extends WebServiceException 13 { 12 class InvalidInputException extends WebServiceException { 13 14 14 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php
r2771752 r3160131 8 8 * Thrown when a MaxMind web service returns an error relating to the request. 9 9 */ 10 class InvalidRequestException extends HttpException 11 { 12 /** 13 * The code returned by the MaxMind web service. 14 * 15 * @var string 16 */ 17 private $error; 10 class InvalidRequestException extends HttpException { 18 11 19 /** 20 * @param string $message the exception message 21 * @param string $error the error code returned by the MaxMind web service 22 * @param int $httpStatus the HTTP status code of the response 23 * @param string $uri the URI queries 24 * @param \Exception $previous the previous exception, if any 25 */ 26 public function __construct( 27 string $message, 28 string $error, 29 int $httpStatus, 30 string $uri, 31 \Exception $previous = null 32 ) { 33 $this->error = $error; 34 parent::__construct($message, $httpStatus, $uri, $previous); 35 } 12 /** 13 * The code returned by the MaxMind web service. 14 * 15 * @var string 16 */ 17 private $error; 36 18 37 public function getErrorCode(): string 38 { 39 return $this->error; 40 } 19 /** 20 * @param string $message the exception message 21 * @param string $error the error code returned by the MaxMind web service 22 * @param int $httpStatus the HTTP status code of the response 23 * @param string $uri the URI queries 24 * @param \Exception $previous the previous exception, if any 25 */ 26 public function __construct( 27 string $message, 28 string $error, 29 int $httpStatus, 30 string $uri, 31 \Exception $previous = null 32 ) { 33 $this->error = $error; 34 parent::__construct( $message, $httpStatus, $uri, $previous ); 35 } 36 37 public function getErrorCode(): string { 38 return $this->error; 39 } 41 40 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php
r2771752 r3160131 5 5 namespace MaxMind\Exception; 6 6 7 class IpAddressNotFoundException extends InvalidRequestException 8 { 7 class IpAddressNotFoundException extends InvalidRequestException { 8 9 9 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php
r2771752 r3160131 8 8 * This exception is thrown when the service requires permission to access. 9 9 */ 10 class PermissionRequiredException extends InvalidRequestException 11 { 10 class PermissionRequiredException extends InvalidRequestException { 11 12 12 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php
r2771752 r3160131 8 8 * This class represents a generic web service error. 9 9 */ 10 class WebServiceException extends \Exception 11 { 10 class WebServiceException extends \Exception { 11 12 12 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Client.php
r2771752 r3160131 23 23 * @internal 24 24 */ 25 class Client 26 { 27 public const VERSION = '0.2.0'; 28 29 /** 30 * @var string|null 31 */ 32 private $caBundle; 33 34 /** 35 * @var float|null 36 */ 37 private $connectTimeout; 38 39 /** 40 * @var string 41 */ 42 private $host = 'api.maxmind.com'; 43 44 /** 45 * @var bool 46 */ 47 private $useHttps = true; 48 49 /** 50 * @var RequestFactory 51 */ 52 private $httpRequestFactory; 53 54 /** 55 * @var string 56 */ 57 private $licenseKey; 58 59 /** 60 * @var string|null 61 */ 62 private $proxy; 63 64 /** 65 * @var float|null 66 */ 67 private $timeout; 68 69 /** 70 * @var string 71 */ 72 private $userAgentPrefix; 73 74 /** 75 * @var int 76 */ 77 private $accountId; 78 79 /** 80 * @param int $accountId your MaxMind account ID 81 * @param string $licenseKey your MaxMind license key 82 * @param array $options an array of options. Possible keys: 83 * * `host` - The host to use when connecting to the web service. 84 * * `useHttps` - A boolean flag for sending the request via https.(True by default) 85 * * `userAgent` - The prefix of the User-Agent to use in the request. 86 * * `caBundle` - The bundle of CA root certificates to use in the request. 87 * * `connectTimeout` - The connect timeout to use for the request. 88 * * `timeout` - The timeout to use for the request. 89 * * `proxy` - The HTTP proxy to use. May include a schema, port, 90 * username, and password, e.g., `http://username:password@127.0.0.1:10`. 91 */ 92 public function __construct( 93 int $accountId, 94 string $licenseKey, 95 array $options = [] 96 ) { 97 $this->accountId = $accountId; 98 $this->licenseKey = $licenseKey; 99 100 $this->httpRequestFactory = isset($options['httpRequestFactory']) 101 ? $options['httpRequestFactory'] 102 : new RequestFactory(); 103 104 if (isset($options['host'])) { 105 $this->host = $options['host']; 106 } 107 if (isset($options['useHttps'])) { 108 $this->useHttps = $options['useHttps']; 109 } 110 if (isset($options['userAgent'])) { 111 $this->userAgentPrefix = $options['userAgent'] . ' '; 112 } 113 114 $this->caBundle = isset($options['caBundle']) ? 115 $this->caBundle = $options['caBundle'] : $this->getCaBundle(); 116 117 if (isset($options['connectTimeout'])) { 118 $this->connectTimeout = $options['connectTimeout']; 119 } 120 if (isset($options['timeout'])) { 121 $this->timeout = $options['timeout']; 122 } 123 124 if (isset($options['proxy'])) { 125 $this->proxy = $options['proxy']; 126 } 127 } 128 129 /** 130 * @param string $service name of the service querying 131 * @param string $path the URI path to use 132 * @param array $input the data to be posted as JSON 133 * 134 * @throws InvalidInputException when the request has missing or invalid 135 * data 136 * @throws AuthenticationException when there is an issue authenticating the 137 * request 138 * @throws InsufficientFundsException when your account is out of funds 139 * @throws InvalidRequestException when the request is invalid for some 140 * other reason, e.g., invalid JSON in the POST. 141 * @throws HttpException when an unexpected HTTP error occurs 142 * @throws WebServiceException when some other error occurs. This also 143 * serves as the base class for the above exceptions. 144 * 145 * @return array|null The decoded content of a successful response 146 */ 147 public function post(string $service, string $path, array $input): ?array 148 { 149 $requestBody = json_encode($input); 150 if ($requestBody === false) { 151 throw new InvalidInputException( 152 'Error encoding input as JSON: ' 153 . $this->jsonErrorDescription() 154 ); 155 } 156 157 $request = $this->createRequest( 158 $path, 159 ['Content-Type: application/json'] 160 ); 161 162 [$statusCode, $contentType, $responseBody] = $request->post($requestBody); 163 164 return $this->handleResponse( 165 $statusCode, 166 $contentType, 167 $responseBody, 168 $service, 169 $path 170 ); 171 } 172 173 public function get(string $service, string $path): ?array 174 { 175 $request = $this->createRequest( 176 $path 177 ); 178 179 [$statusCode, $contentType, $responseBody] = $request->get(); 180 181 return $this->handleResponse( 182 $statusCode, 183 $contentType, 184 $responseBody, 185 $service, 186 $path 187 ); 188 } 189 190 private function userAgent(): string 191 { 192 $curlVersion = curl_version(); 193 194 return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . \PHP_VERSION . 195 ' curl/' . $curlVersion['version']; 196 } 197 198 private function createRequest(string $path, array $headers = []): Http\Request 199 { 200 array_push( 201 $headers, 202 'Authorization: Basic ' 203 . base64_encode($this->accountId . ':' . $this->licenseKey), 204 'Accept: application/json' 205 ); 206 207 return $this->httpRequestFactory->request( 208 $this->urlFor($path), 209 [ 210 'caBundle' => $this->caBundle, 211 'connectTimeout' => $this->connectTimeout, 212 'headers' => $headers, 213 'proxy' => $this->proxy, 214 'timeout' => $this->timeout, 215 'userAgent' => $this->userAgent(), 216 ] 217 ); 218 } 219 220 /** 221 * @param int $statusCode the HTTP status code of the response 222 * @param string|null $contentType the Content-Type of the response 223 * @param string|null $responseBody the response body 224 * @param string $service the name of the service 225 * @param string $path the path used in the request 226 * 227 * @throws AuthenticationException when there is an issue authenticating the 228 * request 229 * @throws InsufficientFundsException when your account is out of funds 230 * @throws InvalidRequestException when the request is invalid for some 231 * other reason, e.g., invalid JSON in the POST. 232 * @throws HttpException when an unexpected HTTP error occurs 233 * @throws WebServiceException when some other error occurs. This also 234 * serves as the base class for the above exceptions 235 * 236 * @return array|null The decoded content of a successful response 237 */ 238 private function handleResponse( 239 int $statusCode, 240 ?string $contentType, 241 ?string $responseBody, 242 string $service, 243 string $path 244 ): ?array { 245 if ($statusCode >= 400 && $statusCode <= 499) { 246 $this->handle4xx($statusCode, $contentType, $responseBody, $service, $path); 247 } elseif ($statusCode >= 500) { 248 $this->handle5xx($statusCode, $service, $path); 249 } elseif ($statusCode !== 200 && $statusCode !== 204) { 250 $this->handleUnexpectedStatus($statusCode, $service, $path); 251 } 252 253 return $this->handleSuccess($statusCode, $responseBody, $service); 254 } 255 256 /** 257 * @return string describing the JSON error 258 */ 259 private function jsonErrorDescription(): string 260 { 261 $errno = json_last_error(); 262 263 switch ($errno) { 264 case \JSON_ERROR_DEPTH: 265 return 'The maximum stack depth has been exceeded.'; 266 267 case \JSON_ERROR_STATE_MISMATCH: 268 return 'Invalid or malformed JSON.'; 269 270 case \JSON_ERROR_CTRL_CHAR: 271 return 'Control character error.'; 272 273 case \JSON_ERROR_SYNTAX: 274 return 'Syntax error.'; 275 276 case \JSON_ERROR_UTF8: 277 return 'Malformed UTF-8 characters.'; 278 279 default: 280 return "Other JSON error ($errno)."; 281 } 282 } 283 284 /** 285 * @param string $path the path to use in the URL 286 * 287 * @return string the constructed URL 288 */ 289 private function urlFor(string $path): string 290 { 291 return ($this->useHttps ? 'https://' : 'http://') . $this->host . $path; 292 } 293 294 /** 295 * @param int $statusCode the HTTP status code 296 * @param string|null $contentType the response content-type 297 * @param string|null $body the response body 298 * @param string $service the service name 299 * @param string $path the path used in the request 300 * 301 * @throws AuthenticationException 302 * @throws HttpException 303 * @throws InsufficientFundsException 304 * @throws InvalidRequestException 305 */ 306 private function handle4xx( 307 int $statusCode, 308 ?string $contentType, 309 ?string $body, 310 string $service, 311 string $path 312 ): void { 313 if ($body === null || $body === '') { 314 throw new HttpException( 315 "Received a $statusCode error for $service with no body", 316 $statusCode, 317 $this->urlFor($path) 318 ); 319 } 320 if ($contentType === null || !strstr($contentType, 'json')) { 321 throw new HttpException( 322 "Received a $statusCode error for $service with " . 323 'the following body: ' . $body, 324 $statusCode, 325 $this->urlFor($path) 326 ); 327 } 328 329 $message = json_decode($body, true); 330 if ($message === null) { 331 throw new HttpException( 332 "Received a $statusCode error for $service but could " . 333 'not decode the response as JSON: ' 334 . $this->jsonErrorDescription() . ' Body: ' . $body, 335 $statusCode, 336 $this->urlFor($path) 337 ); 338 } 339 340 if (!isset($message['code']) || !isset($message['error'])) { 341 throw new HttpException( 342 'Error response contains JSON but it does not ' . 343 'specify code or error keys: ' . $body, 344 $statusCode, 345 $this->urlFor($path) 346 ); 347 } 348 349 $this->handleWebServiceError( 350 $message['error'], 351 $message['code'], 352 $statusCode, 353 $path 354 ); 355 } 356 357 /** 358 * @param string $message the error message from the web service 359 * @param string $code the error code from the web service 360 * @param int $statusCode the HTTP status code 361 * @param string $path the path used in the request 362 * 363 * @throws AuthenticationException 364 * @throws InvalidRequestException 365 * @throws InsufficientFundsException 366 */ 367 private function handleWebServiceError( 368 string $message, 369 string $code, 370 int $statusCode, 371 string $path 372 ): void { 373 switch ($code) { 374 case 'IP_ADDRESS_NOT_FOUND': 375 case 'IP_ADDRESS_RESERVED': 376 throw new IpAddressNotFoundException( 377 $message, 378 $code, 379 $statusCode, 380 $this->urlFor($path) 381 ); 382 383 case 'ACCOUNT_ID_REQUIRED': 384 case 'ACCOUNT_ID_UNKNOWN': 385 case 'AUTHORIZATION_INVALID': 386 case 'LICENSE_KEY_REQUIRED': 387 case 'USER_ID_REQUIRED': 388 case 'USER_ID_UNKNOWN': 389 throw new AuthenticationException( 390 $message, 391 $code, 392 $statusCode, 393 $this->urlFor($path) 394 ); 395 396 case 'OUT_OF_QUERIES': 397 case 'INSUFFICIENT_FUNDS': 398 throw new InsufficientFundsException( 399 $message, 400 $code, 401 $statusCode, 402 $this->urlFor($path) 403 ); 404 405 case 'PERMISSION_REQUIRED': 406 throw new PermissionRequiredException( 407 $message, 408 $code, 409 $statusCode, 410 $this->urlFor($path) 411 ); 412 413 default: 414 throw new InvalidRequestException( 415 $message, 416 $code, 417 $statusCode, 418 $this->urlFor($path) 419 ); 420 } 421 } 422 423 /** 424 * @param int $statusCode the HTTP status code 425 * @param string $service the service name 426 * @param string $path the URI path used in the request 427 * 428 * @throws HttpException 429 */ 430 private function handle5xx(int $statusCode, string $service, string $path): void 431 { 432 throw new HttpException( 433 "Received a server error ($statusCode) for $service", 434 $statusCode, 435 $this->urlFor($path) 436 ); 437 } 438 439 /** 440 * @param int $statusCode the HTTP status code 441 * @param string $service the service name 442 * @param string $path the URI path used in the request 443 * 444 * @throws HttpException 445 */ 446 private function handleUnexpectedStatus(int $statusCode, string $service, string $path): void 447 { 448 throw new HttpException( 449 'Received an unexpected HTTP status ' . 450 "($statusCode) for $service", 451 $statusCode, 452 $this->urlFor($path) 453 ); 454 } 455 456 /** 457 * @param int $statusCode the HTTP status code 458 * @param string|null $body the successful request body 459 * @param string $service the service name 460 * 461 * @throws WebServiceException if a response body is included but not 462 * expected, or is not expected but not 463 * included, or is expected and included 464 * but cannot be decoded as JSON 465 * 466 * @return array|null the decoded request body 467 */ 468 private function handleSuccess(int $statusCode, ?string $body, string $service): ?array 469 { 470 // A 204 should have no response body 471 if ($statusCode === 204) { 472 if ($body !== null && $body !== '') { 473 throw new WebServiceException( 474 "Received a 204 response for $service along with an " . 475 "unexpected HTTP body: $body" 476 ); 477 } 478 479 return null; 480 } 481 482 // A 200 should have a valid JSON body 483 if ($body === null || $body === '') { 484 throw new WebServiceException( 485 "Received a 200 response for $service but did not " . 486 'receive a HTTP body.' 487 ); 488 } 489 490 $decodedContent = json_decode($body, true); 491 if ($decodedContent === null) { 492 throw new WebServiceException( 493 "Received a 200 response for $service but could " . 494 'not decode the response as JSON: ' 495 . $this->jsonErrorDescription() . ' Body: ' . $body 496 ); 497 } 498 499 return $decodedContent; 500 } 501 502 private function getCaBundle(): ?string 503 { 504 $curlVersion = curl_version(); 505 506 // On OS X, when the SSL version is "SecureTransport", the system's 507 // keychain will be used. 508 if ($curlVersion['ssl_version'] === 'SecureTransport') { 509 return null; 510 } 511 $cert = CaBundle::getSystemCaRootBundlePath(); 512 513 // Check if the cert is inside a phar. If so, we need to copy the cert 514 // to a temp file so that curl can see it. 515 if (substr($cert, 0, 7) === 'phar://') { 516 $tempDir = sys_get_temp_dir(); 517 $newCert = tempnam($tempDir, 'geoip2-'); 518 if ($newCert === false) { 519 throw new \RuntimeException( 520 "Unable to create temporary file in $tempDir" 521 ); 522 } 523 if (!copy($cert, $newCert)) { 524 throw new \RuntimeException( 525 "Could not copy $cert to $newCert: " 526 . var_export(error_get_last(), true) 527 ); 528 } 529 530 // We use a shutdown function rather than the destructor as the 531 // destructor isn't called on a fatal error such as an uncaught 532 // exception. 533 register_shutdown_function( 534 function () use ($newCert) { 535 unlink($newCert); 536 } 537 ); 538 $cert = $newCert; 539 } 540 if (!file_exists($cert)) { 541 throw new \RuntimeException("CA cert does not exist at $cert"); 542 } 543 544 return $cert; 545 } 25 class Client { 26 27 public const VERSION = '0.2.0'; 28 29 /** 30 * @var string|null 31 */ 32 private $caBundle; 33 34 /** 35 * @var float|null 36 */ 37 private $connectTimeout; 38 39 /** 40 * @var string 41 */ 42 private $host = 'api.maxmind.com'; 43 44 /** 45 * @var bool 46 */ 47 private $useHttps = true; 48 49 /** 50 * @var RequestFactory 51 */ 52 private $httpRequestFactory; 53 54 /** 55 * @var string 56 */ 57 private $licenseKey; 58 59 /** 60 * @var string|null 61 */ 62 private $proxy; 63 64 /** 65 * @var float|null 66 */ 67 private $timeout; 68 69 /** 70 * @var string 71 */ 72 private $userAgentPrefix; 73 74 /** 75 * @var int 76 */ 77 private $accountId; 78 79 /** 80 * @param int $accountId your MaxMind account ID 81 * @param string $licenseKey your MaxMind license key 82 * @param array $options an array of options. Possible keys: 83 * * `host` - The host to use when connecting to the web service. 84 * * `useHttps` - A boolean flag for sending the request via https.(True by default) 85 * * `userAgent` - The prefix of the User-Agent to use in the request. 86 * * `caBundle` - The bundle of CA root certificates to use in the request. 87 * * `connectTimeout` - The connect timeout to use for the request. 88 * * `timeout` - The timeout to use for the request. 89 * * `proxy` - The HTTP proxy to use. May include a schema, port, 90 * username, and password, e.g., `http://username:password@127.0.0.1:10`. 91 */ 92 public function __construct( 93 int $accountId, 94 string $licenseKey, 95 array $options = array() 96 ) { 97 $this->accountId = $accountId; 98 $this->licenseKey = $licenseKey; 99 100 $this->httpRequestFactory = isset( $options['httpRequestFactory'] ) 101 ? $options['httpRequestFactory'] 102 : new RequestFactory(); 103 104 if ( isset( $options['host'] ) ) { 105 $this->host = $options['host']; 106 } 107 if ( isset( $options['useHttps'] ) ) { 108 $this->useHttps = $options['useHttps']; 109 } 110 if ( isset( $options['userAgent'] ) ) { 111 $this->userAgentPrefix = $options['userAgent'] . ' '; 112 } 113 114 $this->caBundle = isset( $options['caBundle'] ) ? 115 $this->caBundle = $options['caBundle'] : $this->getCaBundle(); 116 117 if ( isset( $options['connectTimeout'] ) ) { 118 $this->connectTimeout = $options['connectTimeout']; 119 } 120 if ( isset( $options['timeout'] ) ) { 121 $this->timeout = $options['timeout']; 122 } 123 124 if ( isset( $options['proxy'] ) ) { 125 $this->proxy = $options['proxy']; 126 } 127 } 128 129 /** 130 * @param string $service name of the service querying 131 * @param string $path the URI path to use 132 * @param array $input the data to be posted as JSON 133 * 134 * @throws InvalidInputException when the request has missing or invalid 135 * data 136 * @throws AuthenticationException when there is an issue authenticating the 137 * request 138 * @throws InsufficientFundsException when your account is out of funds 139 * @throws InvalidRequestException when the request is invalid for some 140 * other reason, e.g., invalid JSON in the POST. 141 * @throws HttpException when an unexpected HTTP error occurs 142 * @throws WebServiceException when some other error occurs. This also 143 * serves as the base class for the above exceptions. 144 * 145 * @return array|null The decoded content of a successful response 146 */ 147 public function post( string $service, string $path, array $input ): ?array { 148 $requestBody = json_encode( $input ); 149 if ( $requestBody === false ) { 150 throw new InvalidInputException( 151 'Error encoding input as JSON: ' 152 . $this->jsonErrorDescription() 153 ); 154 } 155 156 $request = $this->createRequest( 157 $path, 158 array( 'Content-Type: application/json' ) 159 ); 160 161 [$statusCode, $contentType, $responseBody] = $request->post( $requestBody ); 162 163 return $this->handleResponse( 164 $statusCode, 165 $contentType, 166 $responseBody, 167 $service, 168 $path 169 ); 170 } 171 172 public function get( string $service, string $path ): ?array { 173 $request = $this->createRequest( 174 $path 175 ); 176 177 [$statusCode, $contentType, $responseBody] = $request->get(); 178 179 return $this->handleResponse( 180 $statusCode, 181 $contentType, 182 $responseBody, 183 $service, 184 $path 185 ); 186 } 187 188 private function userAgent(): string { 189 $curlVersion = curl_version(); 190 191 return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . \PHP_VERSION . 192 ' curl/' . $curlVersion['version']; 193 } 194 195 private function createRequest( string $path, array $headers = array() ): Http\Request { 196 array_push( 197 $headers, 198 'Authorization: Basic ' 199 . base64_encode( $this->accountId . ':' . $this->licenseKey ), 200 'Accept: application/json' 201 ); 202 203 return $this->httpRequestFactory->request( 204 $this->urlFor( $path ), 205 array( 206 'caBundle' => $this->caBundle, 207 'connectTimeout' => $this->connectTimeout, 208 'headers' => $headers, 209 'proxy' => $this->proxy, 210 'timeout' => $this->timeout, 211 'userAgent' => $this->userAgent(), 212 ) 213 ); 214 } 215 216 /** 217 * @param int $statusCode the HTTP status code of the response 218 * @param string|null $contentType the Content-Type of the response 219 * @param string|null $responseBody the response body 220 * @param string $service the name of the service 221 * @param string $path the path used in the request 222 * 223 * @throws AuthenticationException when there is an issue authenticating the 224 * request 225 * @throws InsufficientFundsException when your account is out of funds 226 * @throws InvalidRequestException when the request is invalid for some 227 * other reason, e.g., invalid JSON in the POST. 228 * @throws HttpException when an unexpected HTTP error occurs 229 * @throws WebServiceException when some other error occurs. This also 230 * serves as the base class for the above exceptions 231 * 232 * @return array|null The decoded content of a successful response 233 */ 234 private function handleResponse( 235 int $statusCode, 236 ?string $contentType, 237 ?string $responseBody, 238 string $service, 239 string $path 240 ): ?array { 241 if ( $statusCode >= 400 && $statusCode <= 499 ) { 242 $this->handle4xx( $statusCode, $contentType, $responseBody, $service, $path ); 243 } elseif ( $statusCode >= 500 ) { 244 $this->handle5xx( $statusCode, $service, $path ); 245 } elseif ( $statusCode !== 200 && $statusCode !== 204 ) { 246 $this->handleUnexpectedStatus( $statusCode, $service, $path ); 247 } 248 249 return $this->handleSuccess( $statusCode, $responseBody, $service ); 250 } 251 252 /** 253 * @return string describing the JSON error 254 */ 255 private function jsonErrorDescription(): string { 256 $errno = json_last_error(); 257 258 switch ( $errno ) { 259 case \JSON_ERROR_DEPTH: 260 return 'The maximum stack depth has been exceeded.'; 261 262 case \JSON_ERROR_STATE_MISMATCH: 263 return 'Invalid or malformed JSON.'; 264 265 case \JSON_ERROR_CTRL_CHAR: 266 return 'Control character error.'; 267 268 case \JSON_ERROR_SYNTAX: 269 return 'Syntax error.'; 270 271 case \JSON_ERROR_UTF8: 272 return 'Malformed UTF-8 characters.'; 273 274 default: 275 return "Other JSON error ($errno)."; 276 } 277 } 278 279 /** 280 * @param string $path the path to use in the URL 281 * 282 * @return string the constructed URL 283 */ 284 private function urlFor( string $path ): string { 285 return ( $this->useHttps ? 'https://' : 'http://' ) . $this->host . $path; 286 } 287 288 /** 289 * @param int $statusCode the HTTP status code 290 * @param string|null $contentType the response content-type 291 * @param string|null $body the response body 292 * @param string $service the service name 293 * @param string $path the path used in the request 294 * 295 * @throws AuthenticationException 296 * @throws HttpException 297 * @throws InsufficientFundsException 298 * @throws InvalidRequestException 299 */ 300 private function handle4xx( 301 int $statusCode, 302 ?string $contentType, 303 ?string $body, 304 string $service, 305 string $path 306 ): void { 307 if ( $body === null || $body === '' ) { 308 throw new HttpException( 309 "Received a $statusCode error for $service with no body", 310 $statusCode, 311 $this->urlFor( $path ) 312 ); 313 } 314 if ( $contentType === null || ! strstr( $contentType, 'json' ) ) { 315 throw new HttpException( 316 "Received a $statusCode error for $service with " . 317 'the following body: ' . $body, 318 $statusCode, 319 $this->urlFor( $path ) 320 ); 321 } 322 323 $message = json_decode( $body, true ); 324 if ( $message === null ) { 325 throw new HttpException( 326 "Received a $statusCode error for $service but could " . 327 'not decode the response as JSON: ' 328 . $this->jsonErrorDescription() . ' Body: ' . $body, 329 $statusCode, 330 $this->urlFor( $path ) 331 ); 332 } 333 334 if ( ! isset( $message['code'] ) || ! isset( $message['error'] ) ) { 335 throw new HttpException( 336 'Error response contains JSON but it does not ' . 337 'specify code or error keys: ' . $body, 338 $statusCode, 339 $this->urlFor( $path ) 340 ); 341 } 342 343 $this->handleWebServiceError( 344 $message['error'], 345 $message['code'], 346 $statusCode, 347 $path 348 ); 349 } 350 351 /** 352 * @param string $message the error message from the web service 353 * @param string $code the error code from the web service 354 * @param int $statusCode the HTTP status code 355 * @param string $path the path used in the request 356 * 357 * @throws AuthenticationException 358 * @throws InvalidRequestException 359 * @throws InsufficientFundsException 360 */ 361 private function handleWebServiceError( 362 string $message, 363 string $code, 364 int $statusCode, 365 string $path 366 ): void { 367 switch ( $code ) { 368 case 'IP_ADDRESS_NOT_FOUND': 369 case 'IP_ADDRESS_RESERVED': 370 throw new IpAddressNotFoundException( 371 $message, 372 $code, 373 $statusCode, 374 $this->urlFor( $path ) 375 ); 376 377 case 'ACCOUNT_ID_REQUIRED': 378 case 'ACCOUNT_ID_UNKNOWN': 379 case 'AUTHORIZATION_INVALID': 380 case 'LICENSE_KEY_REQUIRED': 381 case 'USER_ID_REQUIRED': 382 case 'USER_ID_UNKNOWN': 383 throw new AuthenticationException( 384 $message, 385 $code, 386 $statusCode, 387 $this->urlFor( $path ) 388 ); 389 390 case 'OUT_OF_QUERIES': 391 case 'INSUFFICIENT_FUNDS': 392 throw new InsufficientFundsException( 393 $message, 394 $code, 395 $statusCode, 396 $this->urlFor( $path ) 397 ); 398 399 case 'PERMISSION_REQUIRED': 400 throw new PermissionRequiredException( 401 $message, 402 $code, 403 $statusCode, 404 $this->urlFor( $path ) 405 ); 406 407 default: 408 throw new InvalidRequestException( 409 $message, 410 $code, 411 $statusCode, 412 $this->urlFor( $path ) 413 ); 414 } 415 } 416 417 /** 418 * @param int $statusCode the HTTP status code 419 * @param string $service the service name 420 * @param string $path the URI path used in the request 421 * 422 * @throws HttpException 423 */ 424 private function handle5xx( int $statusCode, string $service, string $path ): void { 425 throw new HttpException( 426 "Received a server error ($statusCode) for $service", 427 $statusCode, 428 $this->urlFor( $path ) 429 ); 430 } 431 432 /** 433 * @param int $statusCode the HTTP status code 434 * @param string $service the service name 435 * @param string $path the URI path used in the request 436 * 437 * @throws HttpException 438 */ 439 private function handleUnexpectedStatus( int $statusCode, string $service, string $path ): void { 440 throw new HttpException( 441 'Received an unexpected HTTP status ' . 442 "($statusCode) for $service", 443 $statusCode, 444 $this->urlFor( $path ) 445 ); 446 } 447 448 /** 449 * @param int $statusCode the HTTP status code 450 * @param string|null $body the successful request body 451 * @param string $service the service name 452 * 453 * @throws WebServiceException if a response body is included but not 454 * expected, or is not expected but not 455 * included, or is expected and included 456 * but cannot be decoded as JSON 457 * 458 * @return array|null the decoded request body 459 */ 460 private function handleSuccess( int $statusCode, ?string $body, string $service ): ?array { 461 // A 204 should have no response body 462 if ( $statusCode === 204 ) { 463 if ( $body !== null && $body !== '' ) { 464 throw new WebServiceException( 465 "Received a 204 response for $service along with an " . 466 "unexpected HTTP body: $body" 467 ); 468 } 469 470 return null; 471 } 472 473 // A 200 should have a valid JSON body 474 if ( $body === null || $body === '' ) { 475 throw new WebServiceException( 476 "Received a 200 response for $service but did not " . 477 'receive a HTTP body.' 478 ); 479 } 480 481 $decodedContent = json_decode( $body, true ); 482 if ( $decodedContent === null ) { 483 throw new WebServiceException( 484 "Received a 200 response for $service but could " . 485 'not decode the response as JSON: ' 486 . $this->jsonErrorDescription() . ' Body: ' . $body 487 ); 488 } 489 490 return $decodedContent; 491 } 492 493 private function getCaBundle(): ?string { 494 $curlVersion = curl_version(); 495 496 // On OS X, when the SSL version is "SecureTransport", the system's 497 // keychain will be used. 498 if ( $curlVersion['ssl_version'] === 'SecureTransport' ) { 499 return null; 500 } 501 $cert = CaBundle::getSystemCaRootBundlePath(); 502 503 // Check if the cert is inside a phar. If so, we need to copy the cert 504 // to a temp file so that curl can see it. 505 if ( substr( $cert, 0, 7 ) === 'phar://' ) { 506 $tempDir = sys_get_temp_dir(); 507 $newCert = tempnam( $tempDir, 'geoip2-' ); 508 if ( $newCert === false ) { 509 throw new \RuntimeException( 510 "Unable to create temporary file in $tempDir" 511 ); 512 } 513 if ( ! copy( $cert, $newCert ) ) { 514 throw new \RuntimeException( 515 "Could not copy $cert to $newCert: " 516 . var_export( error_get_last(), true ) 517 ); 518 } 519 520 // We use a shutdown function rather than the destructor as the 521 // destructor isn't called on a fatal error such as an uncaught 522 // exception. 523 register_shutdown_function( 524 function () use ( $newCert ) { 525 unlink( $newCert ); 526 } 527 ); 528 $cert = $newCert; 529 } 530 if ( ! file_exists( $cert ) ) { 531 throw new \RuntimeException( "CA cert does not exist at $cert" ); 532 } 533 534 return $cert; 535 } 546 536 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php
r2771752 r3160131 12 12 * @internal 13 13 */ 14 class CurlRequest implements Request 15 { 16 /** 17 * @var \CurlHandle 18 */ 19 private $ch; 14 class CurlRequest implements Request { 20 15 21 /**22 * @var string 23 */24 private $url;16 /** 17 * @var \CurlHandle 18 */ 19 private $ch; 25 20 26 /**27 * @var array 28 */29 private $options;21 /** 22 * @var string 23 */ 24 private $url; 30 25 31 public function __construct(string $url, array $options) 32 { 33 $this->url = $url; 34 $this->options = $options; 35 $this->ch = $options['curlHandle']; 36 } 26 /** 27 * @var array 28 */ 29 private $options; 37 30 38 /** 39 * @throws HttpException 40 */ 41 public function post(string $body): array 42 { 43 $curl = $this->createCurl(); 31 public function __construct( string $url, array $options ) { 32 $this->url = $url; 33 $this->options = $options; 34 $this->ch = $options['curlHandle']; 35 } 44 36 45 curl_setopt($curl, \CURLOPT_POST, true); 46 curl_setopt($curl, \CURLOPT_POSTFIELDS, $body); 37 /** 38 * @throws HttpException 39 */ 40 public function post( string $body ): array { 41 $curl = $this->createCurl(); 47 42 48 return $this->execute($curl);49 } 43 curl_setopt( $curl, \CURLOPT_POST, true ); 44 curl_setopt( $curl, \CURLOPT_POSTFIELDS, $body ); 50 45 51 public function get(): array 52 { 53 $curl = $this->createCurl(); 46 return $this->execute( $curl ); 47 } 54 48 55 curl_setopt($curl, \CURLOPT_HTTPGET, true); 49 public function get(): array { 50 $curl = $this->createCurl(); 56 51 57 return $this->execute($curl); 58 } 52 curl_setopt( $curl, \CURLOPT_HTTPGET, true ); 59 53 60 /** 61 * @return \CurlHandle 62 */ 63 private function createCurl() 64 { 65 curl_reset($this->ch); 54 return $this->execute( $curl ); 55 } 66 56 67 $opts = []; 68 $opts[\CURLOPT_URL] = $this->url; 57 /** 58 * @return \CurlHandle 59 */ 60 private function createCurl() { 61 curl_reset( $this->ch ); 69 62 70 if (!empty($this->options['caBundle'])) { 71 $opts[\CURLOPT_CAINFO] = $this->options['caBundle']; 72 } 63 $opts = array(); 64 $opts[ \CURLOPT_URL ] = $this->url; 73 65 74 $opts[\CURLOPT_ENCODING] = ''; 75 $opts[\CURLOPT_SSL_VERIFYHOST] = 2; 76 $opts[\CURLOPT_FOLLOWLOCATION] = false; 77 $opts[\CURLOPT_SSL_VERIFYPEER] = true; 78 $opts[\CURLOPT_RETURNTRANSFER] = true; 66 if ( ! empty( $this->options['caBundle'] ) ) { 67 $opts[ \CURLOPT_CAINFO ] = $this->options['caBundle']; 68 } 79 69 80 $opts[\CURLOPT_HTTPHEADER] = $this->options['headers']; 81 $opts[\CURLOPT_USERAGENT] = $this->options['userAgent']; 82 $opts[\CURLOPT_PROXY] = $this->options['proxy']; 70 $opts[ \CURLOPT_ENCODING ] = ''; 71 $opts[ \CURLOPT_SSL_VERIFYHOST ] = 2; 72 $opts[ \CURLOPT_FOLLOWLOCATION ] = false; 73 $opts[ \CURLOPT_SSL_VERIFYPEER ] = true; 74 $opts[ \CURLOPT_RETURNTRANSFER ] = true; 83 75 84 // The defined()s are here as the *_MS opts are not available on older 85 // cURL versions 86 $connectTimeout = $this->options['connectTimeout']; 87 if (\defined('CURLOPT_CONNECTTIMEOUT_MS')) { 88 $opts[\CURLOPT_CONNECTTIMEOUT_MS] = ceil($connectTimeout * 1000); 89 } else { 90 $opts[\CURLOPT_CONNECTTIMEOUT] = ceil($connectTimeout); 91 } 76 $opts[ \CURLOPT_HTTPHEADER ] = $this->options['headers']; 77 $opts[ \CURLOPT_USERAGENT ] = $this->options['userAgent']; 78 $opts[ \CURLOPT_PROXY ] = $this->options['proxy']; 92 79 93 $timeout = $this->options['timeout']; 94 if (\defined('CURLOPT_TIMEOUT_MS')) { 95 $opts[\CURLOPT_TIMEOUT_MS] = ceil($timeout * 1000); 96 } else { 97 $opts[\CURLOPT_TIMEOUT] = ceil($timeout); 98 } 80 // The defined()s are here as the *_MS opts are not available on older 81 // cURL versions 82 $connectTimeout = $this->options['connectTimeout']; 83 if ( \defined( 'CURLOPT_CONNECTTIMEOUT_MS' ) ) { 84 $opts[ \CURLOPT_CONNECTTIMEOUT_MS ] = ceil( $connectTimeout * 1000 ); 85 } else { 86 $opts[ \CURLOPT_CONNECTTIMEOUT ] = ceil( $connectTimeout ); 87 } 99 88 100 curl_setopt_array($this->ch, $opts); 89 $timeout = $this->options['timeout']; 90 if ( \defined( 'CURLOPT_TIMEOUT_MS' ) ) { 91 $opts[ \CURLOPT_TIMEOUT_MS ] = ceil( $timeout * 1000 ); 92 } else { 93 $opts[ \CURLOPT_TIMEOUT ] = ceil( $timeout ); 94 } 101 95 102 return $this->ch; 103 } 96 curl_setopt_array( $this->ch, $opts ); 104 97 105 /** 106 * @param \CurlHandle $curl 107 * 108 * @throws HttpException 109 */ 110 private function execute($curl): array 111 { 112 $body = curl_exec($curl); 113 if ($errno = curl_errno($curl)) { 114 $errorMessage = curl_error($curl); 98 return $this->ch; 99 } 115 100 116 throw new HttpException( 117 "cURL error ({$errno}): {$errorMessage}", 118 0, 119 $this->url 120 ); 121 } 101 /** 102 * @param \CurlHandle $curl 103 * 104 * @throws HttpException 105 */ 106 private function execute( $curl ): array { 107 $body = curl_exec( $curl ); 108 if ( $errno = curl_errno( $curl ) ) { 109 $errorMessage = curl_error( $curl ); 122 110 123 $statusCode = curl_getinfo($curl, \CURLINFO_HTTP_CODE); 124 $contentType = curl_getinfo($curl, \CURLINFO_CONTENT_TYPE); 111 throw new HttpException( 112 "cURL error ({$errno}): {$errorMessage}", 113 0, 114 $this->url 115 ); 116 } 125 117 126 return [ 127 $statusCode, 128 // The PHP docs say "Content-Type: of the requested document. NULL 129 // indicates server did not send valid Content-Type: header" for 130 // CURLINFO_CONTENT_TYPE. However, it will return FALSE if no header 131 // is set. To keep our types simple, we return null in this case. 132 ($contentType === false ? null : $contentType), 133 $body, 134 ]; 135 } 118 $statusCode = curl_getinfo( $curl, \CURLINFO_HTTP_CODE ); 119 $contentType = curl_getinfo( $curl, \CURLINFO_CONTENT_TYPE ); 120 121 return array( 122 $statusCode, 123 // The PHP docs say "Content-Type: of the requested document. NULL 124 // indicates server did not send valid Content-Type: header" for 125 // CURLINFO_CONTENT_TYPE. However, it will return FALSE if no header 126 // is set. To keep our types simple, we return null in this case. 127 ( $contentType === false ? null : $contentType ), 128 $body, 129 ); 130 } 136 131 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Http/Request.php
r2771752 r3160131 10 10 * @internal 11 11 */ 12 interface Request 13 { 14 public function __construct(string $url, array $options); 12 interface Request { 15 13 16 public function post(string $body): array;14 public function __construct( string $url, array $options); 17 15 18 public function get(): array; 16 public function post( string $body): array; 17 18 public function get(): array; 19 19 } -
termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php
r2771752 r3160131 10 10 * @internal 11 11 */ 12 class RequestFactory 13 { 14 /** 15 * Keep the cURL resource here, so that if there are multiple API requests 16 * done the connection is kept alive, SSL resumption can be used 17 * etcetera. 18 * 19 * @var \CurlHandle|null 20 */ 21 private $ch; 12 class RequestFactory { 22 13 23 public function __destruct() 24 { 25 if (!empty($this->ch)) { 26 curl_close($this->ch); 27 } 28 } 14 /** 15 * Keep the cURL resource here, so that if there are multiple API requests 16 * done the connection is kept alive, SSL resumption can be used 17 * etcetera. 18 * 19 * @var \CurlHandle|null 20 */ 21 private $ch; 29 22 30 /** 31 * @return \CurlHandle 32 */ 33 private function getCurlHandle() 34 { 35 if (empty($this->ch)) { 36 $this->ch = curl_init(); 37 } 23 public function __destruct() { 24 if ( ! empty( $this->ch ) ) { 25 curl_close( $this->ch ); 26 } 27 } 38 28 39 return $this->ch; 40 } 29 /** 30 * @return \CurlHandle 31 */ 32 private function getCurlHandle() { 33 if ( empty( $this->ch ) ) { 34 $this->ch = curl_init(); 35 } 41 36 42 public function request(string $url, array $options): Request 43 { 44 $options['curlHandle'] = $this->getCurlHandle(); 37 return $this->ch; 38 } 45 39 46 return new CurlRequest($url, $options); 47 } 40 public function request( string $url, array $options ): Request { 41 $options['curlHandle'] = $this->getCurlHandle(); 42 43 return new CurlRequest( $url, $options ); 44 } 48 45 }
Note: See TracChangeset
for help on using the changeset viewer.